mirror of
https://github.com/apricote/releaser-pleaser.git
synced 2026-02-07 18:27:03 +00:00
Compare commits
5 commits
af96f88454
...
c85e3d96de
| Author | SHA1 | Date | |
|---|---|---|---|
| c85e3d96de | |||
|
|
4e784f2ccc | ||
|
|
093f0f97bd | ||
| f94c8f4ec7 | |||
| 240813a2fd |
6 changed files with 369 additions and 25 deletions
12
go.mod
12
go.mod
|
|
@ -1,15 +1,18 @@
|
|||
module github.com/apricote/releaser-pleaser
|
||||
|
||||
go 1.23.0
|
||||
go 1.23.2
|
||||
|
||||
toolchain go1.23.4
|
||||
|
||||
require (
|
||||
github.com/blang/semver/v4 v4.0.0
|
||||
github.com/go-git/go-billy/v5 v5.5.0
|
||||
github.com/go-git/go-git/v5 v5.12.0
|
||||
github.com/google/go-github/v66 v66.0.0
|
||||
github.com/leodido/go-conventionalcommits v0.12.0
|
||||
github.com/spf13/cobra v1.8.1
|
||||
github.com/stretchr/testify v1.10.0
|
||||
github.com/teekennedy/goldmark-markdown v0.4.0
|
||||
github.com/teekennedy/goldmark-markdown v0.4.1
|
||||
github.com/xanzy/go-gitlab v0.114.0
|
||||
github.com/yuin/goldmark v1.7.8
|
||||
)
|
||||
|
|
@ -23,7 +26,6 @@ require (
|
|||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/emirpasic/gods v1.18.1 // indirect
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||
github.com/go-git/go-billy/v5 v5.5.0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
|
|
@ -39,10 +41,10 @@ require (
|
|||
github.com/skeema/knownhosts v1.3.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
||||
golang.org/x/crypto v0.26.0 // indirect
|
||||
golang.org/x/crypto v0.31.0 // indirect
|
||||
golang.org/x/net v0.28.0 // indirect
|
||||
golang.org/x/oauth2 v0.6.0 // indirect
|
||||
golang.org/x/sys v0.24.0 // indirect
|
||||
golang.org/x/sys v0.28.0 // indirect
|
||||
golang.org/x/time v0.3.0 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/protobuf v1.33.0 // indirect
|
||||
|
|
|
|||
20
go.sum
20
go.sum
|
|
@ -106,8 +106,8 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
|
|||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/teekennedy/goldmark-markdown v0.4.0 h1:1sWac1NtSmxuEeBtQyQu2WqAfLRc+V78rfAFJL46lhA=
|
||||
github.com/teekennedy/goldmark-markdown v0.4.0/go.mod h1:kMhDz8La77A9UHvJGsxejd0QUflN9sS+QXCqnhmxmNo=
|
||||
github.com/teekennedy/goldmark-markdown v0.4.1 h1:z+khlNC+dX1zsZOEmr/IqXBBJ9CwXrJU2KjF46e0DXw=
|
||||
github.com/teekennedy/goldmark-markdown v0.4.1/go.mod h1:HmgaLa1NTxngaJbKPKI+3Cs6ZEHT/FffRTk8A86ognA=
|
||||
github.com/xanzy/go-gitlab v0.114.0 h1:0wQr/KBckwrZPfEMjRqpUz0HmsKKON9UhCYv9KDy19M=
|
||||
github.com/xanzy/go-gitlab v0.114.0/go.mod h1:wKNKh3GkYDMOsGmnfuX+ITCmDuSDWFO0G+C4AygL9RY=
|
||||
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
|
||||
|
|
@ -120,8 +120,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
|
|||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
|
||||
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
|
||||
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
|
||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
|
|
@ -152,15 +152,15 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|||
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
|
||||
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||
golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU=
|
||||
golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk=
|
||||
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
|
||||
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
|
|
@ -169,8 +169,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
|||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
|
||||
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
||||
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
|
|
|
|||
|
|
@ -170,8 +170,19 @@ func (r *Repository) Commit(_ context.Context, message string) (Commit, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (r *Repository) HasChangesWithRemote(ctx context.Context, branch string) (bool, error) {
|
||||
remoteRef, err := r.r.Reference(plumbing.NewRemoteReferenceName(remoteName, branch), false)
|
||||
// HasChangesWithRemote checks if the following two diffs are equal:
|
||||
//
|
||||
// - **Local**: remote/main..branch
|
||||
// - **Remote**: (git merge-base remote/main remote/branch)..remote/branch
|
||||
//
|
||||
// This is done to avoid pushing when the only change would be a rebase of remote/branch onto the current remote/main.
|
||||
func (r *Repository) HasChangesWithRemote(ctx context.Context, mainBranch, prBranch string) (bool, error) {
|
||||
commitOnRemoteMain, err := r.commitFromRef(plumbing.NewRemoteReferenceName(remoteName, mainBranch))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
commitOnRemotePRBranch, err := r.commitFromRef(plumbing.NewRemoteReferenceName(remoteName, prBranch))
|
||||
if err != nil {
|
||||
if err.Error() == "reference not found" {
|
||||
// No remote branch means that there are changes
|
||||
|
|
@ -181,29 +192,60 @@ func (r *Repository) HasChangesWithRemote(ctx context.Context, branch string) (b
|
|||
return false, err
|
||||
}
|
||||
|
||||
remoteCommit, err := r.r.CommitObject(remoteRef.Hash())
|
||||
currentRemotePRMergeBase, err := r.mergeBase(commitOnRemoteMain, commitOnRemotePRBranch)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if currentRemotePRMergeBase == nil {
|
||||
// If there is no merge base something weird has happened with the
|
||||
// remote main branch, and we should definitely push updates.
|
||||
return false, nil
|
||||
}
|
||||
|
||||
remoteDiff, err := currentRemotePRMergeBase.PatchContext(ctx, commitOnRemotePRBranch)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
localRef, err := r.r.Reference(plumbing.NewBranchReferenceName(branch), false)
|
||||
commitOnLocalPRBranch, err := r.commitFromRef(plumbing.NewBranchReferenceName(prBranch))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
localCommit, err := r.r.CommitObject(localRef.Hash())
|
||||
localDiff, err := commitOnRemoteMain.PatchContext(ctx, commitOnLocalPRBranch)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
diff, err := localCommit.PatchContext(ctx, remoteCommit)
|
||||
return remoteDiff.String() == localDiff.String(), nil
|
||||
}
|
||||
|
||||
func (r *Repository) commitFromRef(refName plumbing.ReferenceName) (*object.Commit, error) {
|
||||
ref, err := r.r.Reference(refName, false)
|
||||
if err != nil {
|
||||
return false, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
hasChanges := len(diff.FilePatches()) > 0
|
||||
commit, err := r.r.CommitObject(ref.Hash())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return hasChanges, nil
|
||||
return commit, nil
|
||||
}
|
||||
|
||||
func (r *Repository) mergeBase(a, b *object.Commit) (*object.Commit, error) {
|
||||
mergeBases, err := a.MergeBase(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(mergeBases) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// :shrug: We dont really care which commit we pick, at worst we do an unnecessary push.
|
||||
return mergeBases[0], nil
|
||||
}
|
||||
|
||||
func (r *Repository) ForcePush(ctx context.Context, branch string) error {
|
||||
|
|
|
|||
131
internal/git/git_test.go
Normal file
131
internal/git/git_test.go
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
package git
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
const testMainBranch = "main"
|
||||
const testPRBranch = "releaser-pleaser"
|
||||
|
||||
func TestRepository_HasChangesWithRemote(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
repo TestRepo
|
||||
want bool
|
||||
wantErr assert.ErrorAssertionFunc
|
||||
}{
|
||||
{
|
||||
name: "no remote pr branch",
|
||||
repo: WithTestRepo(
|
||||
WithCommit(
|
||||
"chore: release v1.0.0",
|
||||
OnBranch(plumbing.NewBranchReferenceName(testMainBranch)),
|
||||
AsNewBranch(plumbing.NewRemoteReferenceName(remoteName, testMainBranch)),
|
||||
WithFile("VERSION", "v1.0.0"),
|
||||
),
|
||||
WithCommit(
|
||||
"chore: release v1.1.0",
|
||||
OnBranch(plumbing.NewRemoteReferenceName(remoteName, testMainBranch)),
|
||||
AsNewBranch(plumbing.NewBranchReferenceName(testPRBranch)),
|
||||
WithFile("VERSION", "v1.1.0"),
|
||||
),
|
||||
),
|
||||
want: true,
|
||||
wantErr: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "remote pr branch matches local",
|
||||
repo: WithTestRepo(
|
||||
WithCommit(
|
||||
"chore: release v1.0.0",
|
||||
OnBranch(plumbing.NewBranchReferenceName(testMainBranch)),
|
||||
AsNewBranch(plumbing.NewRemoteReferenceName(remoteName, testMainBranch)),
|
||||
WithFile("VERSION", "v1.0.0"),
|
||||
),
|
||||
WithCommit(
|
||||
"chore: release v1.1.0",
|
||||
OnBranch(plumbing.NewRemoteReferenceName(remoteName, testMainBranch)),
|
||||
AsNewBranch(plumbing.NewBranchReferenceName(testPRBranch)),
|
||||
WithFile("VERSION", "v1.1.0"),
|
||||
),
|
||||
WithCommit(
|
||||
"chore: release v1.1.0",
|
||||
OnBranch(plumbing.NewRemoteReferenceName(remoteName, testMainBranch)),
|
||||
AsNewBranch(plumbing.NewRemoteReferenceName(remoteName, testPRBranch)),
|
||||
WithFile("VERSION", "v1.1.0"),
|
||||
),
|
||||
),
|
||||
want: false,
|
||||
wantErr: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "remote pr only needs rebase",
|
||||
repo: WithTestRepo(
|
||||
WithCommit(
|
||||
"chore: release v1.0.0",
|
||||
OnBranch(plumbing.NewBranchReferenceName(testMainBranch)),
|
||||
AsNewBranch(plumbing.NewRemoteReferenceName(remoteName, testMainBranch)),
|
||||
WithFile("VERSION", "v1.0.0"),
|
||||
),
|
||||
WithCommit(
|
||||
"chore: release v1.1.0",
|
||||
OnBranch(plumbing.NewRemoteReferenceName(remoteName, testMainBranch)),
|
||||
AsNewBranch(plumbing.NewRemoteReferenceName(remoteName, testPRBranch)),
|
||||
WithFile("VERSION", "v1.1.0"),
|
||||
),
|
||||
WithCommit(
|
||||
"feat: new feature on remote",
|
||||
OnBranch(plumbing.NewRemoteReferenceName(remoteName, testMainBranch)),
|
||||
WithFile("feature", "yes"),
|
||||
),
|
||||
WithCommit(
|
||||
"chore: release v1.1.0",
|
||||
OnBranch(plumbing.NewRemoteReferenceName(remoteName, testMainBranch)),
|
||||
AsNewBranch(plumbing.NewBranchReferenceName(testPRBranch)),
|
||||
WithFile("VERSION", "v1.1.0"),
|
||||
),
|
||||
),
|
||||
want: false,
|
||||
wantErr: assert.NoError,
|
||||
},
|
||||
{
|
||||
name: "needs update",
|
||||
repo: WithTestRepo(
|
||||
WithCommit(
|
||||
"chore: release v1.0.0",
|
||||
OnBranch(plumbing.NewBranchReferenceName(testMainBranch)),
|
||||
AsNewBranch(plumbing.NewRemoteReferenceName(remoteName, testMainBranch)),
|
||||
WithFile("VERSION", "v1.0.0"),
|
||||
),
|
||||
WithCommit(
|
||||
"chore: release v1.1.0",
|
||||
OnBranch(plumbing.NewRemoteReferenceName(remoteName, testMainBranch)),
|
||||
AsNewBranch(plumbing.NewRemoteReferenceName(remoteName, testPRBranch)),
|
||||
WithFile("VERSION", "v1.1.0"),
|
||||
),
|
||||
WithCommit(
|
||||
"chore: release v1.2.0",
|
||||
OnBranch(plumbing.NewRemoteReferenceName(remoteName, testMainBranch)),
|
||||
AsNewBranch(plumbing.NewBranchReferenceName(testPRBranch)),
|
||||
WithFile("VERSION", "v1.2.0"),
|
||||
),
|
||||
),
|
||||
want: false,
|
||||
wantErr: assert.NoError,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
repo := tt.repo(t)
|
||||
got, err := repo.HasChangesWithRemote(context.Background(), testMainBranch, testPRBranch)
|
||||
if !tt.wantErr(t, err) {
|
||||
return
|
||||
}
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
169
internal/git/util_test.go
Normal file
169
internal/git/util_test.go
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
package git
|
||||
|
||||
import (
|
||||
"io"
|
||||
"log/slog"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-git/go-billy/v5/memfs"
|
||||
"github.com/go-git/go-git/v5"
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
"github.com/go-git/go-git/v5/plumbing/object"
|
||||
"github.com/go-git/go-git/v5/storage/memory"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var (
|
||||
author = &object.Signature{
|
||||
Name: "releaser-pleaser",
|
||||
When: time.Date(2020, 01, 01, 01, 01, 01, 01, time.UTC),
|
||||
}
|
||||
)
|
||||
|
||||
type CommitOption func(*commitOptions)
|
||||
type commitOptions struct {
|
||||
cleanFiles bool
|
||||
files []commitFile
|
||||
tags []string
|
||||
newRef plumbing.ReferenceName
|
||||
parentRef plumbing.ReferenceName
|
||||
}
|
||||
type commitFile struct {
|
||||
path string
|
||||
content string
|
||||
}
|
||||
|
||||
type TestCommit func(*testing.T, *Repository) error
|
||||
type TestRepo func(*testing.T) *Repository
|
||||
|
||||
func WithCommit(message string, options ...CommitOption) TestCommit {
|
||||
return func(t *testing.T, repo *Repository) error {
|
||||
t.Helper()
|
||||
|
||||
require.NotEmpty(t, message, "commit message is required")
|
||||
|
||||
opts := &commitOptions{}
|
||||
for _, opt := range options {
|
||||
opt(opts)
|
||||
}
|
||||
|
||||
wt, err := repo.r.Worktree()
|
||||
require.NoError(t, err)
|
||||
|
||||
if opts.parentRef != "" {
|
||||
checkoutOptions := &git.CheckoutOptions{}
|
||||
|
||||
if opts.newRef != "" {
|
||||
parentRef, err := repo.r.Reference(opts.parentRef, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
checkoutOptions.Create = true
|
||||
checkoutOptions.Hash = parentRef.Hash()
|
||||
checkoutOptions.Branch = opts.newRef
|
||||
} else {
|
||||
checkoutOptions.Branch = opts.parentRef
|
||||
}
|
||||
|
||||
err = wt.Checkout(checkoutOptions)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
// Yeet all files
|
||||
if opts.cleanFiles {
|
||||
files, err := wt.Filesystem.ReadDir(".")
|
||||
require.NoError(t, err, "failed to get current files")
|
||||
|
||||
for _, fileInfo := range files {
|
||||
err = wt.Filesystem.Remove(fileInfo.Name())
|
||||
require.NoError(t, err, "failed to remove file %q", fileInfo.Name())
|
||||
}
|
||||
}
|
||||
|
||||
// Create new files
|
||||
for _, fileInfo := range opts.files {
|
||||
file, err := wt.Filesystem.Create(fileInfo.path)
|
||||
require.NoError(t, err, "failed to create file %q", fileInfo.path)
|
||||
|
||||
_, err = file.Write([]byte(fileInfo.content))
|
||||
_ = file.Close()
|
||||
require.NoError(t, err, "failed to write content to file %q", fileInfo.path)
|
||||
}
|
||||
|
||||
// Commit
|
||||
commitHash, err := wt.Commit(message, &git.CommitOptions{
|
||||
All: true,
|
||||
AllowEmptyCommits: true,
|
||||
Author: author,
|
||||
Committer: author,
|
||||
})
|
||||
require.NoError(t, err, "failed to commit")
|
||||
|
||||
// Create tags
|
||||
for _, tagName := range opts.tags {
|
||||
_, err = repo.r.CreateTag(tagName, commitHash, nil)
|
||||
require.NoError(t, err, "failed to create tag %q", tagName)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func WithFile(path, content string) CommitOption {
|
||||
return func(opts *commitOptions) {
|
||||
opts.files = append(opts.files, commitFile{path: path, content: content})
|
||||
}
|
||||
}
|
||||
|
||||
func WithCleanFiles() CommitOption {
|
||||
return func(opts *commitOptions) {
|
||||
opts.cleanFiles = true
|
||||
}
|
||||
}
|
||||
|
||||
func AsNewBranch(ref plumbing.ReferenceName) CommitOption {
|
||||
return func(opts *commitOptions) {
|
||||
opts.newRef = ref
|
||||
}
|
||||
}
|
||||
|
||||
func OnBranch(ref plumbing.ReferenceName) CommitOption {
|
||||
return func(opts *commitOptions) {
|
||||
opts.parentRef = ref
|
||||
}
|
||||
}
|
||||
|
||||
func WithTag(name string) CommitOption {
|
||||
return func(opts *commitOptions) {
|
||||
opts.tags = append(opts.tags, name)
|
||||
}
|
||||
}
|
||||
|
||||
func WithTestRepo(commits ...TestCommit) TestRepo {
|
||||
return func(t *testing.T) *Repository {
|
||||
t.Helper()
|
||||
|
||||
repo := &Repository{
|
||||
logger: slog.New(slog.NewTextHandler(io.Discard, nil)),
|
||||
}
|
||||
|
||||
var err error
|
||||
|
||||
repo.r, err = git.InitWithOptions(memory.NewStorage(), memfs.New(), git.InitOptions{
|
||||
DefaultBranch: plumbing.Main,
|
||||
})
|
||||
require.NoError(t, err, "failed to create in-memory repository")
|
||||
|
||||
// Make initial commit
|
||||
err = WithCommit("chore: init")(t, repo)
|
||||
require.NoError(t, err, "failed to create init commit")
|
||||
|
||||
for i, commit := range commits {
|
||||
err = commit(t, repo)
|
||||
require.NoError(t, err, "failed to create commit %d", i)
|
||||
}
|
||||
|
||||
return repo
|
||||
}
|
||||
}
|
||||
|
|
@ -274,7 +274,7 @@ func (rp *ReleaserPleaser) runReconcileReleasePR(ctx context.Context) error {
|
|||
logger.InfoContext(ctx, "created release commit", "commit.hash", releaseCommit.Hash, "commit.message", releaseCommit.Message)
|
||||
|
||||
// Check if anything changed in comparison to the remote branch (if exists)
|
||||
newReleasePRChanges, err := repo.HasChangesWithRemote(ctx, rpBranch)
|
||||
newReleasePRChanges, err := repo.HasChangesWithRemote(ctx, rp.targetBranch, rpBranch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue