Support full-tag prepared CI delivery

This commit is contained in:
2026-10-10 03:40:10 +00:00
parent f837871b77
commit c0cc50b127
11 changed files with 272 additions and 55 deletions

View File

@@ -6,6 +6,7 @@ import (
"os"
"os/exec"
"path/filepath"
"strings"
"testing"
releasekit "gitea.maximumdirect.net/eric/ReleaseKit"
@@ -18,7 +19,7 @@ func TestPrepareTaggedCheckoutFetchesExpectedCommitAndDetaches(t *testing.T) {
if err := releasekit.PrepareTaggedCheckout(context.Background(), releasekit.TaggedCheckoutRequest{
RepositoryDir: repository,
Version: "v1.2.3",
Tag: "v1.2.3",
ExpectedCommit: tagCommit,
}); err != nil {
t.Fatal(err)
@@ -31,6 +32,22 @@ func TestPrepareTaggedCheckoutFetchesExpectedCommitAndDetaches(t *testing.T) {
}
}
func TestPrepareTaggedCheckoutAcceptsNestedFullTag(t *testing.T) {
repository := newTaggedDeliveryConsumer(t)
tag := "integrations/ckconfig/v1.2.3"
tagCommit := publishPreparationTagNamed(t, repository, tag)
advancePreparationCheckout(t, repository, "later local commit")
if err := releasekit.PrepareTaggedCheckout(context.Background(), releasekit.TaggedCheckoutRequest{
RepositoryDir: repository, Tag: tag, ExpectedCommit: tagCommit,
}); err != nil {
t.Fatal(err)
}
if head := buildGit(t, repository, "rev-parse", "HEAD"); head != tagCommit {
t.Fatalf("prepared HEAD = %s, want %s", head, tagCommit)
}
}
func TestPrepareTaggedCheckoutRejectsWrongCommitBeforeCheckout(t *testing.T) {
repository := newTaggedDeliveryConsumer(t)
tagCommit := publishPreparationTag(t, repository)
@@ -40,7 +57,7 @@ func TestPrepareTaggedCheckoutRejectsWrongCommitBeforeCheckout(t *testing.T) {
err := releasekit.PrepareTaggedCheckout(context.Background(), releasekit.TaggedCheckoutRequest{
RepositoryDir: repository,
Version: "v1.2.3",
Tag: "v1.2.3",
Remote: "candidate",
ExpectedCommit: currentCommit,
})
@@ -67,7 +84,7 @@ func TestPrepareTaggedCheckoutReportsLocalCheckoutConflict(t *testing.T) {
err := releasekit.PrepareTaggedCheckout(context.Background(), releasekit.TaggedCheckoutRequest{
RepositoryDir: repository,
Version: "v1.2.3",
Tag: "v1.2.3",
ExpectedCommit: tagCommit,
})
if err == nil {
@@ -90,7 +107,7 @@ func TestPrepareTaggedCheckoutReportsConflictingLocalTag(t *testing.T) {
err := releasekit.PrepareTaggedCheckout(context.Background(), releasekit.TaggedCheckoutRequest{
RepositoryDir: repository,
Version: "v1.2.3",
Tag: "v1.2.3",
ExpectedCommit: buildGit(t, repository, "rev-parse", "HEAD~1"),
})
if err == nil {
@@ -108,9 +125,9 @@ func TestPrepareTaggedCheckoutValidatesInputsBeforeFetching(t *testing.T) {
repository := newTaggedDeliveryConsumer(t)
publishPreparationTag(t, repository)
for _, request := range []releasekit.TaggedCheckoutRequest{
{RepositoryDir: repository, Version: "not-a-version", ExpectedCommit: buildGit(t, repository, "rev-parse", "HEAD")},
{RepositoryDir: repository, Version: "v1.2.3"},
{RepositoryDir: repository, Version: "v1.2.3", ExpectedCommit: "not-an-object-id"},
{RepositoryDir: repository, Tag: "not-a-version", ExpectedCommit: buildGit(t, repository, "rev-parse", "HEAD")},
{RepositoryDir: repository, Tag: "v1.2.3"},
{RepositoryDir: repository, Tag: "v1.2.3", ExpectedCommit: "not-an-object-id"},
} {
err := releasekit.PrepareTaggedCheckout(context.Background(), request)
if err == nil {
@@ -121,12 +138,77 @@ func TestPrepareTaggedCheckoutValidatesInputsBeforeFetching(t *testing.T) {
}
}
if err := releasekit.PrepareTaggedCheckout(context.Background(), releasekit.TaggedCheckoutRequest{
RepositoryDir: repository, Version: "invalid", ExpectedCommit: "bad",
RepositoryDir: repository, Tag: "invalid", ExpectedCommit: "bad",
}); !errors.Is(err, releasekit.ErrInvalidVersion) {
t.Fatalf("invalid-version error = %v, want ErrInvalidVersion", err)
}
}
func TestPrepareTaggedCheckoutVerifyOnlyIsReadOnly(t *testing.T) {
for _, test := range []struct {
name string
wrong bool
mutate func(t *testing.T, repository string)
}{
{name: "wrong expected commit", wrong: true},
{name: "dirty checkout", mutate: func(t *testing.T, repository string) {
if err := os.WriteFile(filepath.Join(repository, "dirty.txt"), []byte("dirty"), 0o600); err != nil {
t.Fatal(err)
}
}},
{name: "missing tag", mutate: func(t *testing.T, repository string) {
buildGit(t, repository, "tag", "-d", "v1.2.3")
}},
{name: "moved tag", mutate: func(t *testing.T, repository string) {
advancePreparationCheckout(t, repository, "moved tagged commit")
buildGit(t, repository, "tag", "--force", "v1.2.3")
}},
} {
t.Run(test.name, func(t *testing.T) {
repository := newTaggedDeliveryConsumer(t)
tagCommit := publishPreparationTag(t, repository)
if err := releasekit.PrepareTaggedCheckout(context.Background(), releasekit.TaggedCheckoutRequest{
RepositoryDir: repository, Tag: "v1.2.3", ExpectedCommit: tagCommit,
}); err != nil {
t.Fatal(err)
}
if test.mutate != nil {
test.mutate(t, repository)
}
commit := tagCommit
if test.wrong {
commit = strings.Repeat("0", len(tagCommit))
}
if err := releasekit.PrepareTaggedCheckout(context.Background(), releasekit.TaggedCheckoutRequest{
RepositoryDir: repository, Tag: "v1.2.3", Remote: "missing-remote",
ExpectedCommit: commit, VerifyOnly: true,
}); err == nil {
t.Fatal("VerifyOnly accepted an inconsistent prepared checkout")
}
})
}
repository := newTaggedDeliveryConsumer(t)
tagCommit := publishPreparationTag(t, repository)
if err := releasekit.PrepareTaggedCheckout(context.Background(), releasekit.TaggedCheckoutRequest{
RepositoryDir: repository, Tag: "v1.2.3", ExpectedCommit: tagCommit,
}); err != nil {
t.Fatal(err)
}
if err := releasekit.PrepareTaggedCheckout(context.Background(), releasekit.TaggedCheckoutRequest{
RepositoryDir: repository, Tag: "v1.2.3", Remote: "missing-remote",
ExpectedCommit: tagCommit, VerifyOnly: true,
}); err != nil {
t.Fatalf("VerifyOnly rejected a prepared checkout: %v", err)
}
if head := buildGit(t, repository, "rev-parse", "HEAD"); head != tagCommit {
t.Fatalf("VerifyOnly changed HEAD to %s, want %s", head, tagCommit)
}
if branch := buildGit(t, repository, "rev-parse", "--abbrev-ref", "HEAD"); branch != "HEAD" {
t.Fatalf("VerifyOnly changed checkout branch to %q", branch)
}
}
func TestPrepareBuildDependenciesRequiresRepositoryDirectory(t *testing.T) {
if err := releasekit.PrepareBuildDependencies(context.Background(), releasekit.DependencyPreparationRequest{RepositoryDir: " "}); err == nil {
t.Fatal("PrepareBuildDependencies() accepted an empty repository directory")
@@ -161,13 +243,22 @@ func TestPrepareBuildDependenciesUsesSelectedModuleDirectory(t *testing.T) {
func publishPreparationTag(t *testing.T, repository string) string {
t.Helper()
return publishPreparationTagNamed(t, repository, "v1.2.3")
}
func publishPreparationTagNamed(t *testing.T, repository, tag string) string {
t.Helper()
ref := "refs/tags/" + tag
if _, err := buildGitOutput(repository, "show-ref", "--verify", "--quiet", ref); err != nil {
buildGit(t, repository, "tag", tag)
}
remoteDir := t.TempDir()
remote := filepath.Join(remoteDir, "origin.git")
buildGit(t, remoteDir, "init", "--bare", remote)
buildGit(t, repository, "remote", "add", "origin", remote)
commit := buildGit(t, repository, "rev-parse", "refs/tags/v1.2.3^{commit}")
buildGit(t, repository, "push", "origin", "refs/tags/v1.2.3")
buildGit(t, repository, "tag", "-d", "v1.2.3")
commit := buildGit(t, repository, "rev-parse", ref+"^{commit}")
buildGit(t, repository, "push", "origin", ref)
buildGit(t, repository, "tag", "-d", tag)
return commit
}