Skip to content

Commit 4c429a2

Browse files
committed
fix(repo): Fetch tags for release
1 parent 39bfa46 commit 4c429a2

File tree

5 files changed

+87
-21
lines changed

5 files changed

+87
-21
lines changed

.github/workflows/release.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ jobs:
6161
- uses: actions/checkout@v4
6262
with:
6363
fetch-depth: 0
64+
fetch-tags: true
6465

6566
- uses: ./.github/actions/setup-go
6667
with:
@@ -94,6 +95,7 @@ jobs:
9495
- uses: actions/checkout@v4
9596
with:
9697
fetch-depth: 0
98+
fetch-tags: true
9799

98100
- uses: ./.github/actions/setup-go
99101
with:
@@ -134,6 +136,7 @@ jobs:
134136
- uses: actions/checkout@v4
135137
with:
136138
fetch-depth: 0
139+
fetch-tags: true
137140

138141
- name: Set up Go with caching
139142
uses: ./.github/actions/setup-go

pkg/release/internal/orchestrator/pr_release.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,17 +150,26 @@ func (o *PRReleaseOrchestrator) updateAndCreatePR(
150150
if err := o.updatePackageVersions(ctx, version); err != nil {
151151
return fmt.Errorf("failed to update package versions: %w", err)
152152
}
153+
153154
changelog, err := o.generateChangelog(ctx, version, "unreleased")
154155
if err != nil {
155156
return fmt.Errorf("failed to generate changelog: %w", err)
156157
}
158+
159+
// Dry-run: stop here so no commit, push or PR is made.
160+
if cfg.DryRun {
161+
o.printStatus(cfg.CIOutput,
162+
fmt.Sprintf("🛈 Dry-run complete – release %s prepared locally (no commit/push/PR).", version))
163+
return nil
164+
}
165+
157166
if err := o.commitChanges(ctx, version); err != nil {
158167
return fmt.Errorf("failed to commit changes: %w", err)
159168
}
160169
if err := o.gitRepo.PushBranch(ctx, branchName); err != nil {
161170
return fmt.Errorf("failed to push branch: %w", err)
162171
}
163-
if !cfg.SkipPR && !cfg.DryRun {
172+
if !cfg.SkipPR {
164173
if err := o.createPullRequest(ctx, version, changelog, branchName); err != nil {
165174
return fmt.Errorf("failed to create pull request: %w", err)
166175
}

pkg/release/internal/repository/git_impl.go

Lines changed: 65 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"github.com/go-git/go-git/v5/config"
1111
"github.com/go-git/go-git/v5/plumbing"
1212
"github.com/go-git/go-git/v5/plumbing/object"
13+
"github.com/go-git/go-git/v5/plumbing/storer"
1314
"github.com/go-git/go-git/v5/plumbing/transport/http"
1415
)
1516

@@ -39,14 +40,23 @@ func NewGitExtendedRepository() (GitExtendedRepository, error) {
3940

4041
// LatestTag returns the latest git tag.
4142
func (r *gitRepository) LatestTag(_ context.Context) (string, error) {
43+
// First, try to fetch tags from remote to ensure we have the latest
44+
remote, err := r.repo.Remote("origin")
45+
if err == nil {
46+
// Fetch tags from remote (ignore error if already up to date)
47+
_ = remote.Fetch(&git.FetchOptions{
48+
RefSpecs: []config.RefSpec{
49+
config.RefSpec("+refs/tags/*:refs/tags/*"),
50+
},
51+
Auth: r.getAuth(),
52+
})
53+
}
4254
tagRefs, err := r.repo.Tags()
4355
if err != nil {
4456
return "", fmt.Errorf("failed to get tags: %w", err)
4557
}
46-
4758
var latestTag string
4859
var latestCommitTime time.Time
49-
5060
if err := tagRefs.ForEach(func(ref *plumbing.Reference) error {
5161
// Try to get the commit directly first (lightweight tag)
5262
commit, err := r.repo.CommitObject(ref.Hash())
@@ -61,7 +71,6 @@ func (r *gitRepository) LatestTag(_ context.Context) (string, error) {
6171
return nil // Skip if we can't get the commit
6272
}
6373
}
64-
6574
if commit.Committer.When.After(latestCommitTime) {
6675
latestCommitTime = commit.Committer.When
6776
latestTag = ref.Name().Short()
@@ -70,27 +79,72 @@ func (r *gitRepository) LatestTag(_ context.Context) (string, error) {
7079
}); err != nil {
7180
return "", fmt.Errorf("failed to iterate tags: %w", err)
7281
}
73-
7482
return latestTag, nil
7583
}
7684

7785
// CommitsSinceTag returns the number of commits since the given tag.
7886
func (r *gitRepository) CommitsSinceTag(_ context.Context, tag string) (int, error) {
87+
// First, try to fetch the tag from remote if it doesn't exist locally
7988
tagRef, err := r.repo.Tag(tag)
8089
if err != nil {
81-
return 0, fmt.Errorf("failed to get tag %s: %w", tag, err)
90+
// Tag doesn't exist locally, try to fetch it from remote
91+
remote, err := r.repo.Remote("origin")
92+
if err != nil {
93+
return 0, fmt.Errorf("failed to get remote: %w", err)
94+
}
95+
// Fetch tags from remote
96+
if err := remote.Fetch(&git.FetchOptions{
97+
RefSpecs: []config.RefSpec{
98+
config.RefSpec("+refs/tags/*:refs/tags/*"),
99+
},
100+
Auth: r.getAuth(),
101+
}); err != nil && err != git.NoErrAlreadyUpToDate {
102+
return 0, fmt.Errorf("failed to fetch tags from remote: %w", err)
103+
}
104+
// Try to get the tag again
105+
tagRef, err = r.repo.Tag(tag)
106+
if err != nil {
107+
return 0, fmt.Errorf("failed to get tag %s after fetching: %w", tag, err)
108+
}
82109
}
83-
84-
commits, err := r.repo.Log(&git.LogOptions{From: tagRef.Hash()})
110+
// Resolve the tag to a commit hash (handles lightweight *and* annotated tags)
111+
var tagCommitHash plumbing.Hash
112+
if commit, err := r.repo.CommitObject(tagRef.Hash()); err == nil {
113+
// Lightweight tag – hash already points to commit
114+
tagCommitHash = commit.Hash
115+
} else if tagObj, err := r.repo.TagObject(tagRef.Hash()); err == nil {
116+
// Annotated tag – resolve to the tagged commit
117+
if commit, err := r.repo.CommitObject(tagObj.Target); err == nil {
118+
tagCommitHash = commit.Hash
119+
}
120+
}
121+
if tagCommitHash == (plumbing.Hash{}) {
122+
return 0, fmt.Errorf("failed to resolve commit for tag %s", tag)
123+
}
124+
// Get HEAD commit
125+
head, err := r.repo.Head()
85126
if err != nil {
86-
return 0, fmt.Errorf("failed to get commits since tag %s: %w", tag, err)
127+
return 0, fmt.Errorf("failed to get HEAD: %w", err)
87128
}
88-
129+
headCommit, err := r.repo.CommitObject(head.Hash())
130+
if err != nil {
131+
return 0, fmt.Errorf("failed to get HEAD commit: %w", err)
132+
}
133+
// Count commits from tag to HEAD (excluding the tag commit itself)
89134
var count int
90-
if err := commits.ForEach(func(_ *object.Commit) error {
135+
commits, err := r.repo.Log(&git.LogOptions{From: headCommit.Hash})
136+
if err != nil {
137+
return 0, fmt.Errorf("failed to get commits: %w", err)
138+
}
139+
err = commits.ForEach(func(c *object.Commit) error {
140+
// Stop when we reach the tag commit
141+
if c.Hash == tagCommitHash {
142+
return storer.ErrStop
143+
}
91144
count++
92145
return nil
93-
}); err != nil {
146+
})
147+
if err != nil && err != storer.ErrStop {
94148
return 0, fmt.Errorf("failed to iterate commits: %w", err)
95149
}
96150
return count, nil

pkg/release/internal/service/cliff_impl.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,10 +115,11 @@ func (s *cliffService) CalculateNextVersion(ctx context.Context, latestTag strin
115115
return nil, fmt.Errorf("invalid latest tag: %w", err)
116116
}
117117

118+
// git-cliff determines the next version relative to the most recent tag
119+
// automatically. Supplying --tag together with --bumped-version makes it
120+
// interpret the given tag as the *target* version, which results in the
121+
// same tag being echoed back. Therefore we only need --bumped-version.
118122
args := []string{"--bumped-version"}
119-
if latestTag != "" {
120-
args = append(args, "--tag", latestTag)
121-
}
122123

123124
output, err := s.executeCommand(ctx, "git-cliff", args...)
124125
if err != nil {

pkg/release/internal/usecase/check_changes.go

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,19 @@ func (uc *CheckChangesUseCase) Execute(ctx context.Context) (bool, string, error
2121
if err != nil {
2222
return false, "", fmt.Errorf("failed to get latest tag: %w", err)
2323
}
24-
2524
if latestTag == "" {
2625
return true, "", nil // Initial release
2726
}
28-
2927
commitsSince, err := uc.GitRepo.CommitsSinceTag(ctx, latestTag)
30-
if err != nil || commitsSince == 0 {
31-
return false, latestTag, err
28+
if err != nil {
29+
return false, latestTag, fmt.Errorf("failed to get commits since tag: %w", err)
30+
}
31+
if commitsSince == 0 {
32+
return false, latestTag, nil
3233
}
33-
3434
nextVer, err := uc.CliffSvc.CalculateNextVersion(ctx, latestTag)
3535
if err != nil {
3636
return false, latestTag, fmt.Errorf("failed to calculate next version: %w", err)
3737
}
38-
3938
return nextVer.String() != latestTag, latestTag, nil
4039
}

0 commit comments

Comments
 (0)