diff --git a/scripts/release.sh b/scripts/release.sh index ec0ed8f..347ebdf 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -16,6 +16,17 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" cd "$ROOT_DIR" +# Print a recovery hint if the script dies between the version bump and the commit. +BUMPED=0 +COMMITTED=0 +on_exit() { + if [[ $? -ne 0 && "$BUMPED" == "1" && "$COMMITTED" == "0" ]]; then + echo -e "\n${YELLOW}⚠ Release interrupted after the version bump.${NC}" >&2 + echo " To undo it: git checkout -- package.json package-lock.json" >&2 + fi +} +trap on_exit EXIT + # ── Prerequisites ───────────────────────────────────────────────────────────── echo "" echo -e "${BOLD}Checking prerequisites...${NC}" @@ -35,6 +46,28 @@ if [[ "$CURRENT_BRANCH" != "main" ]]; then fi info "On branch: $CURRENT_BRANCH" +# ── Quality gate ────────────────────────────────────────────────────────────── +echo "" +echo -e "${BOLD}Quality gate${NC}" + +echo " Running: npm run lint" +npm run lint --silent || error "Lint failed. Fix the issues before releasing." +info "Lint passed." + +echo " Running: npm run format:check" +npm run format:check --silent || error "Formatting check failed. Run 'npm run format' and commit." +info "Formatting is clean." + +echo -n " Run the Playwright test suite now? (slow) [Y/n] " +read -r RUN_TESTS +if [[ "$RUN_TESTS" =~ ^[Nn] ]]; then + warn "Tests skipped — make sure the suite passed recently." +else + echo " Running: npm run test:parallel" + npm run test:parallel || error "Tests failed. Fix them before releasing." + info "Tests passed on Firefox and Chromium." +fi + # ── Commits since last release ──────────────────────────────────────────────── echo "" echo -e "${BOLD}Changes since last release${NC}" @@ -46,18 +79,16 @@ if [[ -n "$LAST_TAG" ]]; then echo " Commits since $LAST_TAG:" echo "" COMMIT_LOG=$(git log "${LAST_TAG}..HEAD" --oneline --no-merges) + if [[ -z "$COMMIT_LOG" ]]; then + warn "No commits since $LAST_TAG. Are you sure you want to release?" + else + while IFS= read -r line; do + echo -e " ${DIM}${line}${NC}" + done <<< "$COMMIT_LOG" + fi else - warn "No previous tag found — listing all commits." - echo "" - COMMIT_LOG=$(git log --oneline --no-merges) -fi - -if [[ -z "$COMMIT_LOG" ]]; then - warn "No commits since $LAST_TAG. Are you sure you want to release?" -else - while IFS= read -r line; do - echo -e " ${DIM}${line}${NC}" - done <<< "$COMMIT_LOG" + COMMIT_LOG="" + info "No previous tag — this is the first release." fi echo "" @@ -73,8 +104,9 @@ read -r VERSION || error "Invalid format. Use MAJOR.MINOR.PATCH without a 'v' prefix." TAG="v$VERSION" -ARCHIVE="trainus-${TAG}-src.zip" -NOTES_FILE="trainus-${TAG}-notes.md" +mkdir -p tmp +ARCHIVE="tmp/trainus-${TAG}-src.zip" +NOTES_FILE="tmp/trainus-${TAG}-notes.md" git tag --list | grep -q "^${TAG}$" \ && error "Tag $TAG already exists locally." @@ -99,7 +131,7 @@ echo " 5. Create a source archive of the current commit" echo " $ARCHIVE (tracked files only, no node_modules, no dist)" echo "" echo " 6. Generate a draft release notes file for you to edit" -echo " $NOTES_FILE (pre-filled with the commit list above)" +echo " $NOTES_FILE (pre-filled draft to edit)" echo "" echo -e "${YELLOW}Nothing will be pushed or sent anywhere. All steps are local.${NC}" echo "" @@ -111,6 +143,7 @@ read -r CONFIRM doing "Step 1/6 — Bumping version in package.json and package-lock.json" echo " Running: npm version $VERSION --no-git-tag-version" npm version "$VERSION" --no-git-tag-version --silent +BUMPED=1 info "package.json and package-lock.json updated to $VERSION." # ── Step 2 — Build ──────────────────────────────────────────────────────────── @@ -125,6 +158,7 @@ echo " Running: git add package.json package-lock.json" echo " git commit -m \"chore: release $TAG\"" git add package.json package-lock.json git commit -m "chore: release $TAG" +COMMITTED=1 info "Commit created: chore: release $TAG" # ── Step 4 — Tag ────────────────────────────────────────────────────────────── @@ -145,45 +179,43 @@ echo " Excludes: node_modules/, dist/, .git/, and any untracked files." doing "Step 6/6 — Generating draft release notes" echo " Writing: $NOTES_FILE" -if [[ -n "$LAST_TAG" ]]; then - RANGE_LABEL="since $LAST_TAG" -else - RANGE_LABEL="(no previous tag — all commits)" -fi - { echo "# TrainUs $TAG — Release notes" echo "" - echo "" - echo "" - echo "## What's new" - echo "" - echo "" - echo "" - echo "-" - echo "" - echo "## Bug fixes" - echo "" - echo "" - echo "" - echo "-" - echo "" - echo "## Breaking changes" - echo "" - echo "None." - echo "" - echo "---" - echo "" - echo "## Commits $RANGE_LABEL" - echo "" - echo "" - echo "" - if [[ -n "$COMMIT_LOG" ]]; then - while IFS= read -r line; do - echo "- $line" - done <<< "$COMMIT_LOG" + if [[ -z "$LAST_TAG" ]]; then + echo "First release $VERSION." else - echo "- (none)" + echo "" + echo "" + echo "## What's new" + echo "" + echo "" + echo "" + echo "-" + echo "" + echo "## Bug fixes" + echo "" + echo "" + echo "" + echo "-" + echo "" + echo "## Breaking changes" + echo "" + echo "None." + echo "" + echo "---" + echo "" + echo "## Commits since $LAST_TAG" + echo "" + echo "" + echo "" + if [[ -n "$COMMIT_LOG" ]]; then + while IFS= read -r line; do + echo "- $line" + done <<< "$COMMIT_LOG" + else + echo "- (none)" + fi fi } > "$NOTES_FILE" @@ -229,6 +261,6 @@ echo " Fill in the placeholders — set draft: false when ready." echo " Write the French version yourself." echo " Rebuild and redeploy the website (step 5)." echo "" -echo -e " ${BOLD}7. Clean up local artifacts${NC}" +echo -e " ${BOLD}7. Clean up local artifacts (optional — tmp/ is gitignored)${NC}" echo " Once uploaded and published: rm $ARCHIVE $NOTES_FILE" echo ""