Skip to content

[issues/249] Release script renames + QA issue automation#608

Merged
couimet merged 8 commits into
mainfrom
issues/249-qa-pass
May 27, 2026
Merged

[issues/249] Release script renames + QA issue automation#608
couimet merged 8 commits into
mainfrom
issues/249-qa-pass

Conversation

@couimet
Copy link
Copy Markdown
Owner

@couimet couimet commented May 27, 2026

Summary

Regroups the three release scripts under a release: prefix for logical grouping, renames "finalize" to "prepare" to better reflect its role in the lifecycle, and chains QA issue generation into release:lock so one command both locks the version and creates the GitHub issue tracker.

Changes

  • Renamed release pnpm scripts: lock-versionrelease:lock, finalize-releaserelease:prepare, start-releaserelease:start
  • Added orchestrate-release-lock.sh — single command for the full lock workflow: creates release/vX.Y.Z branch, runs lock + QA issue generation, writes commit message
  • generate-qa-issue.sh skips its interactive prompt when stdin is not a terminal
  • Added final "Release Ready" checkbox to generated QA issues — points to release:prepare as the next step
  • Refactored generate-qa-issue.sh to eliminate duplicated content between GitHub and local output modes
  • Added mermaid lifecycle diagram to RELEASE-STRATEGY.md; TESTING.md now references it instead of duplicating
  • Documentation: CHANGELOG not needed (internal tooling); README not needed

Test Plan

  • All 1979 Jest tests pass (98.52% coverage)
  • All 172 BATS tests pass
  • Manual: pnpm release:lock:vscode-extension <version> creates the QA issue in one step

Related

Summary by CodeRabbit

  • New Features

    • Added a smoke-test phase to publishing instructions and an automated release-lock orchestration.
    • Added version-generation and release-documentation generation commands; QA issue generation now handles interactive vs non-interactive runs.
  • Documentation

    • Updated release workflow docs and QA guidance to use the new release:* command names.
    • Clarified QA rule QA002 to reference release:lock.
  • Chores

    • Renamed and namespaced release scripts to release:lock/prepare/start.
  • Bug Fixes / Tests

    • Dirty-tree detection switched to git status --porcelain and related tests added/updated (including publishing-instructions and orchestration).

Review Change Stack

couimet added 4 commits May 27, 2026 09:32
…A issue generation into lock

Rename the three release pnpm scripts for logical grouping and clarity:
- `lock-version` → `release:lock` (freeze version for QA)
- `finalize-release` → `release:prepare` (prepare docs for publication)
- `start-release` → `release:start` (open next dev cycle)

`release:lock` now chains `generate-qa-issue.sh` automatically — running one
command both locks the version and creates the GitHub QA issue tracker. The
issue generator skips its interactive prompt when stdin is not a terminal.

Also refactors `generate-qa-issue.sh` to eliminate duplicated content between
GitHub and local output modes, and adds a final "Release Ready" checkbox
that points to the next step (`release:prepare`).

Benefits:
- `release:` prefix groups related scripts in pnpm's flat namespace
- "prepare" replaces the misleading "finalize" (which isn't the terminal step)
- One command to lock + create QA issue instead of two
- Local mode reuses GitHub body instead of duplicating it
- QA issue includes explicit next-step instruction
… full lock workflow

Wraps branch creation, version locking, QA issue generation, and commit
message generation into one script. `pnpm release:lock:vscode-extension X.Y.Z`
now:

1. Creates a `release/vX.Y.Z` branch from main
2. Runs lock-version.sh (rename YAML, bump .version, regenerate instructions)
3. Runs generate-qa-issue.sh (creates GitHub issue with correct versioned title)
4. Writes a commit message file with the QA issue URL
5. Prints the remaining manual steps (review, commit, push, QA)

Benefits:
- Predictable branch naming (`release/vX.Y.Z`)
- QA issue URL is embedded in the commit message and summary
- lock-version.sh stays focused on locking — orchestration lives separately
- No more chained `&&` in package.json
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 27, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: bb340c9d-151f-4141-95fe-c8a15be2b77e

📥 Commits

Reviewing files that changed from the base of the PR and between dc4bf69 and 58183d2.

📒 Files selected for processing (4)
  • packages/rangelink-vscode-extension/scripts/generate-publishing-instructions.sh
  • packages/rangelink-vscode-extension/scripts/orchestrate-release-lock.sh
  • tests/shell/generate-publishing-instructions.bats
  • tests/shell/orchestrate-release-lock.bats
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/rangelink-vscode-extension/scripts/generate-publishing-instructions.sh

Walkthrough

Rename release commands to a namespaced release:lock/prepare/start, add an orchestration script to lock releases and generate QA issues, make QA-issue generation TTY-aware and refactor body assembly, add a smoke-test phase to publishing instructions, and update scripts/tests for git status-based dirty checks.

Changes

Release workflow scheme update

Layer / File(s) Summary
Release command scheme rename across docs and configs
CLAUDE.md, docs/RELEASE-STRATEGY.md, package.json, packages/rangelink-vscode-extension/TESTING.md, packages/rangelink-vscode-extension/package.json
Replace lock-version/finalize-release/start-release with release:lock/release:prepare/release:start in docs and package scripts; update QA guidance and examples.
Release-lock orchestration script
packages/rangelink-vscode-extension/scripts/orchestrate-release-lock.sh
Add script to validate SemVer and git state, create release/vX.Y.Z branch, invoke lock-version and generate QA issue, extract issue URL, and create a templated commit message file plus next-step output.
QA issue generation interactivity and body refactoring
packages/rangelink-vscode-extension/scripts/generate-qa-issue.sh
Make YAML selection prompt TTY-aware, precompute TOTAL_ASSISTED/TOTAL_MANUAL, build a BODY_FOOTER, append to ISSUE_BODY, and write the full ISSUE_BODY for local output.
Publishing instructions smoke-test phase and phase renumbering
packages/rangelink-vscode-extension/scripts/generate-publishing-instructions.sh, tests/shell/generate-publishing-instructions.bats
Insert "Phase 1: Smoke Test" into generated publishing instructions (local install & verification steps), renumber subsequent phases, and add a smoke-test Bats test validating generated output.
Working-tree dirty checks and test stubs update
packages/rangelink-vscode-extension/scripts/finalize-release.sh, packages/rangelink-vscode-extension/scripts/lock-version.sh, tests/shell/*
Switch dirty-tree checks to use git status --porcelain and update test git stubs to match git status invocation patterns.
Orchestrate-release-lock tests
tests/shell/orchestrate-release-lock.bats
Add Bats tests verifying .commit-msgs numbering and fixture behavior for the new orchestration script.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • couimet/rangeLink#388: Prior updates to QA issue generation and release-lock orchestration that this PR builds on.
  • couimet/rangeLink#553: Related QA issue generation and checklist/layout changes touching the same scripts.
  • couimet/rangeLink#606: Earlier release-gating changes to lock/finalize scripts and dirty-check logic.

Poem

🐰 I hop and I rename with nimble delight,
release:lock by day and prepare by night,
A smoke-test to sniff any sneaky surprise,
QA issues crafted with careful eyes,
The rabbit stamps the branch and bounds off light.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: release script renames (lock-version → release:lock, etc.) and QA issue automation (orchestrate-release-lock.sh, generate-qa-issue.sh refactoring).
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issues/249-qa-pass

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/rangelink-vscode-extension/scripts/orchestrate-release-lock.sh`:
- Around line 38-41: The current "clean tree" guard uses git -C "$REPO_ROOT"
diff-index --quiet HEAD -- which ignores untracked files; update the guard to
fail when any untracked or uncommitted changes exist by running a
repository-level check that includes untracked files (e.g., run git -C
"$REPO_ROOT" status --porcelain and treat any non-empty output as dirty) in the
same block that references REPO_ROOT so the script exits with the same error
message if the workspace is not truly clean.
- Around line 84-85: The pipeline assigning LAST in orchestrate-release-lock.sh
fails on first run when COMMIT_MSGS_DIR is empty because grep exits non-zero;
update the LAST assignment to tolerate no matches (e.g., change LAST=$(ls
"$COMMIT_MSGS_DIR" | grep -o '^[0-9]\{4\}' | sort -n | tail -1) to include a
fallback such as LAST=$(ls "$COMMIT_MSGS_DIR" | grep -o '^[0-9]\{4\}' || true |
sort -n | tail -1) or use a safe alternative like find/printf that returns empty
without a non-zero exit), leaving NEXT_NUM computation (printf ...
$((10#${LAST:-0} + 1))) unchanged so the first commit file is numbered
correctly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 042233b7-e03f-4511-b7c8-72136b36f879

📥 Commits

Reviewing files that changed from the base of the PR and between 6e29373 and 45e3234.

📒 Files selected for processing (8)
  • CLAUDE.md
  • docs/RELEASE-STRATEGY.md
  • package.json
  • packages/rangelink-vscode-extension/TESTING.md
  • packages/rangelink-vscode-extension/package.json
  • packages/rangelink-vscode-extension/scripts/generate-publishing-instructions.sh
  • packages/rangelink-vscode-extension/scripts/generate-qa-issue.sh
  • packages/rangelink-vscode-extension/scripts/orchestrate-release-lock.sh

Comment thread packages/rangelink-vscode-extension/scripts/orchestrate-release-lock.sh Outdated
Comment thread packages/rangelink-vscode-extension/scripts/orchestrate-release-lock.sh Outdated
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

…e scripts

Replace `git diff-index --quiet HEAD --` with `git status --porcelain` in
all three release scripts so untracked files also block execution. Add
`|| true` to the commit-message numbering pipeline so the script doesn't
abort on first run when `.commit-msgs/` is empty.

Benefits:
- Untracked files no longer slip past the clean-tree guard
- First-run commit numbering works without aborting
- All three scripts (orchestrate-release-lock, lock-version, finalize-release)
  now use the same clean-tree check

Ref: #608 (review)
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@couimet
Copy link
Copy Markdown
Owner Author

couimet commented May 27, 2026

@coderabbitai full review - I was rate-limited in #608 (comment)

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 27, 2026

@couimet Sure! Triggering a full review of PR #608 now.

(ᴖ‿ᴖ)🐇

✅ Actions performed

Full review triggered.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
packages/rangelink-vscode-extension/scripts/orchestrate-release-lock.sh (1)

84-85: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fix LAST extraction pipeline precedence before arithmetic.

Line 84 currently lets || true short-circuit the sort | tail stage, so LAST can become multi-line and break Line 85 arithmetic when multiple commit-message files exist.

Suggested fix
-LAST=$(ls "$COMMIT_MSGS_DIR" | grep -o '^[0-9]\{4\}' || true | sort -n | tail -1)
+LAST=$(
+  find "$COMMIT_MSGS_DIR" -maxdepth 1 -type f -printf '%f\n' \
+    | sed -n 's/^\([0-9]\{4\}\).*/\1/p' \
+    | sort -n \
+    | tail -1
+)
 NEXT_NUM=$(printf "%04d" $((10#${LAST:-0} + 1)))

Run this to verify the current expression can produce an invalid multi-line LAST:

#!/usr/bin/env bash
set -euo pipefail

tmp="$(mktemp -d)"
mkdir -p "$tmp/.commit-msgs"
touch "$tmp/.commit-msgs/0001-a.txt" "$tmp/.commit-msgs/0010-b.txt"

set +e
out=$(bash -lc '
  set -euo pipefail
  COMMIT_MSGS_DIR="'"$tmp"'/.commit-msgs"
  LAST=$(ls "$COMMIT_MSGS_DIR" | grep -o '\''^[0-9]\{4\}'\'' || true | sort -n | tail -1)
  printf "LAST=<%s>\n" "$LAST"
  NEXT_NUM=$(printf "%04d" $((10#${LAST:-0} + 1)))
  printf "NEXT_NUM=%s\n" "$NEXT_NUM"
' 2>&1)
code=$?
set -e

printf '%s\n' "$out"
echo "exit_code=$code"

Expected: non-zero exit and/or malformed LAST output with multiple entries.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/rangelink-vscode-extension/scripts/orchestrate-release-lock.sh`
around lines 84 - 85, The pipeline that computes LAST lets the "|| true" only
apply to grep, which can leave LAST multi-line and break the arithmetic in
NEXT_NUM; fix by applying the fallback to the entire pipeline (e.g., wrap the
pipeline in a subshell or move "|| true" to the end of the full pipeline) so
LAST is a single value or empty, then NEXT_NUM=$(printf "%04d" $((10#${LAST:-0}
+ 1))) will work reliably.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@packages/rangelink-vscode-extension/scripts/generate-publishing-instructions.sh`:
- Around line 454-456: Update the smoke-test step that currently instructs to
run the wrong command palette entry "RangeLink: Show Extension Info" to use the
actual registered command title "RangeLink: Show Version Info"; modify the
string in the generate-publishing-instructions.sh instructions block so step 2
runs "RangeLink: Show Version Info" (leave the ${VERSION} check unchanged).

---

Duplicate comments:
In `@packages/rangelink-vscode-extension/scripts/orchestrate-release-lock.sh`:
- Around line 84-85: The pipeline that computes LAST lets the "|| true" only
apply to grep, which can leave LAST multi-line and break the arithmetic in
NEXT_NUM; fix by applying the fallback to the entire pipeline (e.g., wrap the
pipeline in a subshell or move "|| true" to the end of the full pipeline) so
LAST is a single value or empty, then NEXT_NUM=$(printf "%04d" $((10#${LAST:-0}
+ 1))) will work reliably.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d1086d4e-cd96-40f2-8bf8-9a7373933297

📥 Commits

Reviewing files that changed from the base of the PR and between 6e29373 and dc4bf69.

📒 Files selected for processing (12)
  • CLAUDE.md
  • docs/RELEASE-STRATEGY.md
  • package.json
  • packages/rangelink-vscode-extension/TESTING.md
  • packages/rangelink-vscode-extension/package.json
  • packages/rangelink-vscode-extension/scripts/finalize-release.sh
  • packages/rangelink-vscode-extension/scripts/generate-publishing-instructions.sh
  • packages/rangelink-vscode-extension/scripts/generate-qa-issue.sh
  • packages/rangelink-vscode-extension/scripts/lock-version.sh
  • packages/rangelink-vscode-extension/scripts/orchestrate-release-lock.sh
  • tests/shell/finalize-release.bats
  • tests/shell/lock-version.bats

…e scripts

Move `|| true` to end of full pipeline in orchestrate-release-lock.sh so
sort/tail always execute when commit-msg files exist. Fix "Show Extension
Info" → "Show Version Info" in generate-publishing-instructions.sh smoke-test
step.

Benefits:
- Commit message numbering works correctly when multiple files exist
- Smoke-test instructions reference the actual registered command title

Ref: #608 (review)
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

The CI workflow only installs bats — no Node.js. Added a node stub so we can support `generate-publishing-instructions.sh` calling node -p "require(...)" to read package.json and version.json.
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

…ns test passes on Ubuntu CI

The script validates VSIX existence, CHANGELOG.md, and README.md before
generating instructions. CI runners have no Node.js, npx, or project files.
Add the missing fixture files and stubs so the test runs without a real
toolchain.

Ref: #608 (review)
@github-actions
Copy link
Copy Markdown

✅ CI / Integration Tests (with extensions) — run summary

Duration 9m 37s
Unit tests Ran in Test & Validate job
Integration tests passing 160
QA TC IDs exercised clipboard-preservation-011, clipboard-preservation-012, custom-ai-assistant-003, claude-code-001, claude-code-006, claude-code-007, gemini-code-assist-001, gemini-code-assist-005, gemini-code-assist-006
Report View run & artifacts

@github-actions
Copy link
Copy Markdown

✅ CI / Test & Validate — run summary

Duration 10m 9s
Unit tests passed 1979 / 1979
Integration tests passing 151
QA TC IDs exercised status-bar-menu-002, status-bar-menu-003, status-bar-menu-005, status-bar-menu-006, bind-to-destination-010, bind-to-destination-013, terminal-picker-001, terminal-picker-002, terminal-picker-003, terminal-picker-004, terminal-picker-005, terminal-picker-007, terminal-picker-008, terminal-picker-011, terminal-picker-012, terminal-picker-013, terminal-picker-014, terminal-picker-015, terminal-picker-016, file-picker-001, file-picker-002, file-picker-003, file-picker-004, file-picker-005, file-picker-009, file-picker-011, file-picker-012, clipboard-preservation-001, clipboard-preservation-002, clipboard-preservation-003, clipboard-preservation-004, clipboard-preservation-005, clipboard-preservation-006, clipboard-preservation-007, clipboard-preservation-008, clipboard-preservation-009, clipboard-preservation-010, clipboard-preservation-013, clipboard-preservation-014, clipboard-preservation-015, clipboard-preservation-016, send-file-path-001, send-file-path-002, send-file-path-004, send-file-path-005, send-file-path-006, send-file-path-007, send-file-path-008, send-file-path-010, send-file-path-011, send-file-path-012, dirty-buffer-warning-004, dirty-buffer-warning-006, dirty-buffer-warning-007, dirty-buffer-warning-019, send-terminal-selection-003, send-terminal-selection-006, send-terminal-selection-007, go-to-link-001, unbind-001, unbind-003, unbind-004, editor-binding-validation-004, full-line-navigation-001, full-line-navigation-002, char-navigation-001, char-navigation-002, full-line-link-generation-001, wrapped-link-navigation-001, wrapped-link-navigation-002, wrapped-link-navigation-003, wrapped-link-navigation-004, markdown-link-navigation-001, url-exclusion-001, stale-viewcolumn-001, hidden-tab-paste-001, hidden-tab-paste-002, full-line-selection-validation-001, core-send-commands-r-l-001, core-send-commands-r-l-002, core-send-commands-r-l-003, core-send-commands-r-c-001, core-send-commands-r-l-004, core-send-commands-r-c-002, core-send-commands-r-l-005, core-send-commands-r-p-001, core-send-commands-r-v-001, clickable-file-paths-001, clickable-file-paths-002, clickable-file-paths-003, clickable-file-paths-004, clickable-file-paths-005, clickable-file-paths-006, clickable-file-paths-007, clickable-file-paths-008, clickable-file-paths-009, clickable-file-paths-010, clickable-file-paths-011, clickable-file-paths-012, smart-padding-001, smart-padding-003, smart-padding-005, smart-padding-006, smart-padding-007, smart-padding-008, smart-padding-011, duplicate-tab-group-001, duplicate-tab-group-002, duplicate-tab-group-003, duplicate-tab-group-004, langswitch-binding-001, langswitch-binding-002, navigation-clamping-001, navigation-clamping-002, navigation-clamping-003, navigation-clamping-004, untitled-navigation-001, untitled-navigation-002, untitled-navigation-003, untitled-navigation-004, untitled-navigation-005, untitled-navigation-006, navigation-toast-settings-001, navigation-toast-settings-002, navigation-toast-settings-003, filename-fallback-navigation-001, filename-fallback-navigation-002, filename-fallback-navigation-003, filename-fallback-navigation-004, custom-ai-assistant-001, custom-ai-assistant-002, custom-ai-assistant-004, custom-ai-assistant-005, custom-ai-assistant-006, custom-ai-assistant-007, custom-ai-assistant-008, custom-ai-assistant-009, custom-ai-assistant-010, custom-ai-assistant-011, custom-ai-assistant-012, custom-ai-assistant-013, custom-ai-assistant-014, custom-ai-assistant-015, custom-ai-assistant-016, custom-ai-assistant-017, github-copilot-chat-001, release-notifier-001, release-notifier-002, status-bar-appearance-001, status-bar-appearance-002
Report View run & artifacts

@couimet couimet merged commit 1a8be4d into main May 27, 2026
5 checks passed
@couimet couimet deleted the issues/249-qa-pass branch May 27, 2026 18:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant