diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml index 1eb0a4a..32b71d4 100644 --- a/.github/release-drafter.yml +++ b/.github/release-drafter.yml @@ -23,6 +23,23 @@ categories: - title: "Other Changes" labels: - "*" +autolabeler: + - label: "feature" + branch: + - "/^feat/" + - label: "fix" + branch: + - "/^fix/" + - "/^bugfix/" + - "/^hotfix/" + - label: "docs" + branch: + - "/^docs/" + - label: "enhancement" + branch: + - "/^improve/" + - "/^refactor/" + - "/^chore/" version-resolver: major: labels: diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index a0406be..8d1563b 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -3,6 +3,7 @@ name: Release Drafter on: push: branches: [main] + workflow_dispatch: permissions: contents: read @@ -17,6 +18,12 @@ jobs: pull-requests: write steps: + # Brief delay to allow GitHub API to propagate commit/PR data. + # Without this, the GraphQL query for associated pull requests + # can return empty results when run immediately after a push. + - name: Wait for API propagation + run: sleep 10 + - uses: release-drafter/release-drafter@v6 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/internal/workspace/workspace.go b/internal/workspace/workspace.go index 2c3f38e..d58a544 100644 --- a/internal/workspace/workspace.go +++ b/internal/workspace/workspace.go @@ -234,8 +234,11 @@ func (s *Service) Render(ctx context.Context, id string, progress func(msg strin if err != nil { return fmt.Errorf("getting default branch for %s: %w", repo.URL, err) } - s.log().Debug("creating worktree with new branch", "path", worktreePath, "branch", repo.Branch, "from", defaultBranch) - if err := s.Git.AddWorktreeNewBranch(ctx, barePath, worktreePath, repo.Branch, defaultBranch); err != nil { + // Use the remote ref to ensure we branch from the latest fetched state, + // not a potentially stale local branch ref in the bare repo. + startPoint := "origin/" + defaultBranch + s.log().Debug("creating worktree with new branch", "path", worktreePath, "branch", repo.Branch, "from", startPoint) + if err := s.Git.AddWorktreeNewBranch(ctx, barePath, worktreePath, repo.Branch, startPoint); err != nil { return fmt.Errorf("creating worktree for %s: %w", repo.URL, err) } progress(fmt.Sprintf(" └── %s (%s, new branch from %s) ✓", repoPath, repo.Branch, defaultBranch)) diff --git a/internal/workspace/workspace_test.go b/internal/workspace/workspace_test.go index 661215e..23a3d4c 100644 --- a/internal/workspace/workspace_test.go +++ b/internal/workspace/workspace_test.go @@ -15,10 +15,11 @@ import ( // mockRunner records calls without executing git. type mockRunner struct { - clones []string - fetches []string - worktrees []string - removed []string + clones []string + fetches []string + worktrees []string + removed []string + startPoints []string cloneErr error fetchErr error @@ -47,7 +48,8 @@ func (m *mockRunner) AddWorktree(_ context.Context, _, worktreePath, _ string) e return os.MkdirAll(worktreePath, 0o755) } -func (m *mockRunner) AddWorktreeNewBranch(_ context.Context, _, worktreePath, _, _ string) error { +func (m *mockRunner) AddWorktreeNewBranch(_ context.Context, _, worktreePath, _, startPoint string) error { + m.startPoints = append(m.startPoints, startPoint) m.worktrees = append(m.worktrees, worktreePath) if m.addWTErr != nil { return m.addWTErr @@ -415,6 +417,32 @@ func TestRenderAddWorktreeError(t *testing.T) { } } +func TestRenderNewBranchUsesRemoteRef(t *testing.T) { + svc, mock := testService(t) + ctx := context.Background() + + st := state.NewState("Remote ref test", "Test new branch uses origin/ prefix", []state.Repo{ + {URL: "github.com/org/repo", Branch: "feat/new-feature", Path: "./repo"}, + }) + if err := svc.Create("remote-ref", st); err != nil { + t.Fatal(err) + } + + // branchExists=false triggers the new branch path + mock.branchExists = false + err := svc.Render(ctx, "remote-ref", noop) + if err != nil { + t.Fatalf("Render: %v", err) + } + + if len(mock.startPoints) != 1 { + t.Fatalf("startPoints = %d, want 1", len(mock.startPoints)) + } + if mock.startPoints[0] != "origin/main" { + t.Errorf("startPoint = %q, want origin/main", mock.startPoints[0]) + } +} + func TestRenderNotFound(t *testing.T) { svc, _ := testService(t) ctx := context.Background()