Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@ charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.json]
insert_final_newline = ignore

[Makefile]
indent_style = tab

Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/check.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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: |
Expand Down
65 changes: 53 additions & 12 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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"

Expand All @@ -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 }}
Expand All @@ -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."
28 changes: 14 additions & 14 deletions docs/specs/live/cli-non-interactive-mode.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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)
Expand Down
26 changes: 13 additions & 13 deletions docs/specs/live/interactive-worktree-selector.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
12 changes: 6 additions & 6 deletions docs/specs/live/repo-switching.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
20 changes: 10 additions & 10 deletions docs/specs/live/upgrade-notifications.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
20 changes: 10 additions & 10 deletions docs/specs/live/worktree-deletion.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 2 additions & 0 deletions mise.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
[tools]
node = "lts"
yarn = "4"
shellcheck = "latest"
shfmt = "latest"

[tasks.test]
description = "Run CLI tests"
Expand Down
Loading