From c1a42c8338b1ae0920e6a9b1bd20fd650cc5fe7a Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 23 Mar 2026 01:24:30 +0000 Subject: [PATCH 1/4] feat: add platform-specific release assets for mise/ubi support Upload platform-named copies of the bash script (linux-amd64, linux-arm64, darwin-amd64, darwin-arm64) as release assets so `mise install ubi:nsheaps/git-wt` works out of the box. Also aligns the update-homebrew job with the consistent pattern used across other repos (close stale PRs, auto-merge with retry, sha256sum). https://claude.ai/code/session_01UNAUtVFRfFTyfXXLy7dJNz --- .github/workflows/release.yaml | 65 +++++++++++++++++++++++++++------- 1 file changed, 53 insertions(+), 12 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index ce0a45e..e7fc577 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -38,12 +38,29 @@ jobs: - name: Run release-it id: release + env: + GITHUB_TOKEN: ${{ steps.auth.outputs.token }} run: | yarn release-it --ci TAG=$(git describe --tags --abbrev=0) echo "tag=$TAG" >> "$GITHUB_OUTPUT" echo "version=${TAG#v}" >> "$GITHUB_OUTPUT" + - name: Upload release assets + env: + GITHUB_TOKEN: ${{ steps.auth.outputs.token }} + run: | + TAG="${{ steps.release.outputs.tag }}" + # git-wt is a platform-independent bash script, but ubi (used by + # mise) expects assets named with OS/arch patterns. Upload copies + # for each supported platform so `mise install ubi:nsheaps/git-wt` + # works out of the box. + for platform in linux-amd64 linux-arm64 darwin-amd64 darwin-arm64; do + cp bin/git-wt "git-wt-${platform}" + done + gh release upload "$TAG" git-wt-linux-amd64 git-wt-linux-arm64 git-wt-darwin-amd64 git-wt-darwin-arm64 + rm -f git-wt-linux-amd64 git-wt-linux-arm64 git-wt-darwin-amd64 git-wt-darwin-arm64 + update-homebrew: needs: release runs-on: ubuntu-latest @@ -72,11 +89,10 @@ jobs: echo "tag=$TAG" >> "$GITHUB_OUTPUT" # Download archive tarball and calculate SHA256 - # Archive is available instantly (no CDN delay like release assets) TARBALL_URL="https://github.com/${{ github.repository }}/archive/refs/tags/${TAG}.tar.gz" echo "Downloading tarball from: $TARBALL_URL" curl -fsSL "$TARBALL_URL" -o /tmp/archive.tar.gz - SHA256=$(shasum -a 256 /tmp/archive.tar.gz | cut -d' ' -f1) + SHA256=$(sha256sum /tmp/archive.tar.gz | cut -d' ' -f1) echo "sha256=$SHA256" >> "$GITHUB_OUTPUT" echo "Successfully got SHA256: $SHA256" @@ -96,7 +112,17 @@ jobs: run: | gomplate -f Formula/git-wt.rb.gotmpl -o homebrew-devsetup/Formula/git-wt.rb - - name: Create PR to update formula with auto-merge + - name: Close stale formula PRs + run: | + cd homebrew-devsetup + # Close any open PRs from previous formula updates — they're superseded + gh pr list --state open --search "chore: update git-wt to" --json number,title --jq '.[].number' | while read -r pr_num; do + echo "Closing superseded PR #${pr_num}" + gh pr close "$pr_num" --comment "Superseded by v${{ steps.release.outputs.version }} update." + done + + - name: Create PR to update formula + id: formula-pr env: RELEASE_URL: https://github.com/${{ github.repository }}/releases/tag/${{ steps.release.outputs.tag }} JOB_URL: ${{ env.GITHUB_JOB_URL }} @@ -105,22 +131,37 @@ jobs: run: | cd homebrew-devsetup BRANCH="bump-git-wt-${VERSION}" + + # Delete remote branch if it exists from a previous failed run + git push origin --delete "$BRANCH" 2>/dev/null || true + git checkout -b "$BRANCH" git add Formula/git-wt.rb git commit -m "chore: update git-wt to ${VERSION}" git push -u origin "$BRANCH" - # Create PR body file - cat > /tmp/pr-body.md << 'BODY_EOF' - Automated formula update from git-wt release - BODY_EOF - echo "" >> /tmp/pr-body.md - echo "**Release:** ${RELEASE_URL}" >> /tmp/pr-body.md - echo "**Workflow:** ${JOB_URL}" >> /tmp/pr-body.md + printf 'Automated formula update from git-wt release\n\n**Release:** %s\n**Workflow:** %s\n' "$RELEASE_URL" "$JOB_URL" > /tmp/pr-body.md PR_URL=$(gh pr create \ --title "chore: update git-wt to ${VERSION}" \ --body-file /tmp/pr-body.md \ --base main) - # Enable auto-merge with squash - gh pr merge "$PR_URL" --auto --squash + echo "pr_url=$PR_URL" >> "$GITHUB_OUTPUT" + + - name: Enable auto-merge with retry + env: + PR_URL: ${{ steps.formula-pr.outputs.pr_url }} + run: | + # Retry auto-merge — CI checks on the target repo need time to start, + # and the GraphQL API rejects enablePullRequestAutoMerge while the PR + # is in "unstable" (checks pending) status. + for attempt in 1 2 3 4 5; do + if gh pr merge "$PR_URL" --auto --squash; then + echo "Auto-merge enabled successfully on attempt ${attempt}" + exit 0 + fi + wait=$((attempt * 10)) + echo "Auto-merge not ready (attempt ${attempt}/5), waiting ${wait}s..." + sleep "$wait" + done + echo "::warning::Could not enable auto-merge after 5 attempts. PR was created successfully at ${PR_URL} — merge manually or re-run." From 946699906156e13765af09cb09f58aa64b73ba2d Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 23 Mar 2026 03:27:13 +0000 Subject: [PATCH 2/4] fix(ci): add mise setup and shfmt/shellcheck tools to check workflow The check workflow was failing because shfmt and shellcheck were not installed. Add jdx/mise-action setup step (matching op-exec pattern) and add shellcheck/shfmt to mise.toml tools. https://claude.ai/code/session_01UNAUtVFRfFTyfXXLy7dJNz --- .github/workflows/check.yaml | 3 +++ mise.toml | 2 ++ 2 files changed, 5 insertions(+) diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml index 9a0b7d1..0e6b55a 100644 --- a/.github/workflows/check.yaml +++ b/.github/workflows/check.yaml @@ -14,6 +14,9 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 + - name: Setup mise + uses: jdx/mise-action@v2 + - name: Find bash scripts id: find-bash run: | diff --git a/mise.toml b/mise.toml index ee7bb1e..5412468 100644 --- a/mise.toml +++ b/mise.toml @@ -1,6 +1,8 @@ [tools] node = "lts" yarn = "4" +shellcheck = "latest" +shfmt = "latest" [tasks.test] description = "Run CLI tests" From a336d8bcb4dfd6236d11663c3e5974b0ec3df369 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 23 Mar 2026 03:40:45 +0000 Subject: [PATCH 3/4] fix(ci): resolve editorconfig-checker failures in docs and config - Change 3-space list indents to 4-space in all docs/specs/live/*.md files to satisfy indent_size=2 (must be multiple of 2) - Change insert_final_newline from "ignore" to "false" for JSON files in .editorconfig (ignore is not a valid boolean value) https://claude.ai/code/session_01UNAUtVFRfFTyfXXLy7dJNz --- .editorconfig | 2 +- docs/specs/live/cli-non-interactive-mode.md | 28 +++++++++---------- .../live/interactive-worktree-selector.md | 26 ++++++++--------- docs/specs/live/repo-switching.md | 12 ++++---- docs/specs/live/upgrade-notifications.md | 20 ++++++------- docs/specs/live/worktree-deletion.md | 20 ++++++------- 6 files changed, 54 insertions(+), 54 deletions(-) diff --git a/.editorconfig b/.editorconfig index 3d26fa0..ed07297 100644 --- a/.editorconfig +++ b/.editorconfig @@ -10,7 +10,7 @@ trim_trailing_whitespace = true insert_final_newline = true [*.json] -insert_final_newline = ignore +insert_final_newline = false [Makefile] indent_style = tab diff --git a/docs/specs/live/cli-non-interactive-mode.md b/docs/specs/live/cli-non-interactive-mode.md index b03091c..86e991c 100644 --- a/docs/specs/live/cli-non-interactive-mode.md +++ b/docs/specs/live/cli-non-interactive-mode.md @@ -11,26 +11,26 @@ Command-line interface for scripting and non-TTY environments. ### Functional Requirements 1. **TTY Detection** - - Detect when stdin/stdout are not TTY - - Automatically switch to non-interactive behavior + - Detect when stdin/stdout are not TTY + - Automatically switch to non-interactive behavior 2. **Usage Display (no arguments)** - - Print usage information - - List existing worktrees with paths - - List branches without worktrees + - Print usage information + - List existing worktrees with paths + - List branches without worktrees 3. **Branch Switch (`git-wt [branch]`)** - - Create worktree if doesn't exist - - Print worktree path to stdout (for `cd "$(git-wt branch)"`) - - Silent operation (no interactive prompts) + - Create worktree if doesn't exist + - Print worktree path to stdout (for `cd "$(git-wt branch)"`) + - Silent operation (no interactive prompts) 4. **Exec Flags** - - `--exec` - Spawn shell in worktree (override default) - - `--no-exec` - Print path only (default in CLI mode) + - `--exec` - Spawn shell in worktree (override default) + - `--no-exec` - Print path only (default in CLI mode) 5. **Error Handling** - - Exit with non-zero status on errors - - Print errors to stderr + - Exit with non-zero status on errors + - Print errors to stderr ### Non-Functional Requirements @@ -58,8 +58,8 @@ cd "$(git-wt feature-branch)" ### Usage Output ``` -Usage: git-wt [branch] Switch to or create worktree - git-wt d [branch] Delete worktree (requires --force) +Usage: git-wt [branch] Switch to or create worktree + git-wt d [branch] Delete worktree (requires --force) Options: --exec Spawn shell in worktree (instead of printing path) diff --git a/docs/specs/live/interactive-worktree-selector.md b/docs/specs/live/interactive-worktree-selector.md index 178f662..888c4c1 100644 --- a/docs/specs/live/interactive-worktree-selector.md +++ b/docs/specs/live/interactive-worktree-selector.md @@ -11,27 +11,27 @@ The primary interactive TUI for selecting and managing git worktrees using fzf. ### Functional Requirements 1. **Worktree Listing** - - Display all existing worktrees with their branch names and paths - - Show root checkout labeled as `[root]` - - Show worktrees labeled as `[worktree]` + - Display all existing worktrees with their branch names and paths + - Show root checkout labeled as `[root]` + - Show worktrees labeled as `[worktree]` 2. **Branch Listing** - - Display local branches without worktrees - - Display remote branches (with `origin/` prefix stripped in display) + - Display local branches without worktrees + - Display remote branches (with `origin/` prefix stripped in display) 3. **Selection Interface** - - Use fzf for fuzzy-finding selection - - Support keyboard navigation - - Show preview panel with PR information (if gh CLI available) + - Use fzf for fuzzy-finding selection + - Support keyboard navigation + - Show preview panel with PR information (if gh CLI available) 4. **Actions on Selection** - - Switch to existing worktree - - Create new worktree for branch without one - - Create new branch and worktree + - Switch to existing worktree + - Create new worktree for branch without one + - Create new branch and worktree 5. **Post-Selection Behavior** - - Spawn new shell in selected worktree directory - - Support `--no-exec` to print path instead + - Spawn new shell in selected worktree directory + - Support `--no-exec` to print path instead ### Non-Functional Requirements diff --git a/docs/specs/live/repo-switching.md b/docs/specs/live/repo-switching.md index 484e0f9..0768585 100644 --- a/docs/specs/live/repo-switching.md +++ b/docs/specs/live/repo-switching.md @@ -11,16 +11,16 @@ Switch between different git repositories when not already in a repo. ### Functional Requirements 1. **Repo Discovery** - - Scan configured directory for git repositories - - Default scan directory: `~/src` - - Configurable via `--scan-dir DIR` + - Scan configured directory for git repositories + - Default scan directory: `~/src` + - Configurable via `--scan-dir DIR` 2. **Repo Selection** - - Use fzf for fuzzy-finding repos - - Display repo paths for selection + - Use fzf for fuzzy-finding repos + - Display repo paths for selection 3. **Post-Selection** - - Continue to normal worktree selector for chosen repo + - Continue to normal worktree selector for chosen repo ### Non-Functional Requirements diff --git a/docs/specs/live/upgrade-notifications.md b/docs/specs/live/upgrade-notifications.md index b0abd1f..83d6b22 100644 --- a/docs/specs/live/upgrade-notifications.md +++ b/docs/specs/live/upgrade-notifications.md @@ -11,22 +11,22 @@ Background check for new releases with non-intrusive notification. ### Functional Requirements 1. **Background Check** - - Check GitHub releases API asynchronously - - Do not block main script execution - - Cache/throttle to avoid excessive API calls + - Check GitHub releases API asynchronously + - Do not block main script execution + - Cache/throttle to avoid excessive API calls 2. **Version Comparison** - - Compare current version against latest release - - Only notify if newer version available + - Compare current version against latest release + - Only notify if newer version available 3. **Notification Display** - - Show at script exit (after main operation completes) - - Display current version and available version - - Provide upgrade command + - Show at script exit (after main operation completes) + - Display current version and available version + - Provide upgrade command 4. **Suppression** - - Do NOT show in non-interactive mode - - Only show when TTY available + - Do NOT show in non-interactive mode + - Only show when TTY available ### Non-Functional Requirements diff --git a/docs/specs/live/worktree-deletion.md b/docs/specs/live/worktree-deletion.md index 050ca22..f199fce 100644 --- a/docs/specs/live/worktree-deletion.md +++ b/docs/specs/live/worktree-deletion.md @@ -11,22 +11,22 @@ Delete git worktrees with appropriate safety confirmations. ### Functional Requirements 1. **Delete Command** - - `git-wt d [branch]` to delete worktree for specified branch - - Cannot delete root checkout + - `git-wt d [branch]` to delete worktree for specified branch + - Cannot delete root checkout 2. **Interactive Mode** - - Show confirmation prompt via gum - - If uncommitted changes, show force confirmation - - Use gum spinner during deletion + - Show confirmation prompt via gum + - If uncommitted changes, show force confirmation + - Use gum spinner during deletion 3. **Non-Interactive Mode** - - Require `--force` flag - - Fail with helpful error if `--force` not provided + - Require `--force` flag + - Fail with helpful error if `--force` not provided 4. **Error Handling** - - Error if branch has no worktree - - Error if trying to delete root checkout - - Handle uncommitted changes gracefully + - Error if branch has no worktree + - Error if trying to delete root checkout + - Handle uncommitted changes gracefully ### Non-Functional Requirements From 605db8cc3db89341aa5298a47da93d160e61b310 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 23 Mar 2026 03:41:49 +0000 Subject: [PATCH 4/4] fix(ci): remove JSON insert_final_newline override in .editorconfig JSON files already have final newlines, so they should inherit the default insert_final_newline=true from [*] instead of overriding to false (which was originally "ignore", an invalid value). https://claude.ai/code/session_01UNAUtVFRfFTyfXXLy7dJNz --- .editorconfig | 3 --- 1 file changed, 3 deletions(-) diff --git a/.editorconfig b/.editorconfig index ed07297..1b9b3e9 100644 --- a/.editorconfig +++ b/.editorconfig @@ -9,9 +9,6 @@ charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true -[*.json] -insert_final_newline = false - [Makefile] indent_style = tab