164 lines
6.4 KiB
Go
164 lines
6.4 KiB
Go
package releasekit_test
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
releasekit "gitea.maximumdirect.net/eric/ReleaseKit"
|
|
)
|
|
|
|
func TestPrepareTaggedCheckoutFetchesExpectedCommitAndDetaches(t *testing.T) {
|
|
repository := newTaggedDeliveryConsumer(t)
|
|
tagCommit := publishPreparationTag(t, repository)
|
|
advancePreparationCheckout(t, repository, "later local commit")
|
|
|
|
if err := releasekit.PrepareTaggedCheckout(context.Background(), releasekit.TaggedCheckoutRequest{
|
|
RepositoryDir: repository,
|
|
Version: "v1.2.3",
|
|
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)
|
|
}
|
|
if branch := buildGit(t, repository, "rev-parse", "--abbrev-ref", "HEAD"); branch != "HEAD" {
|
|
t.Fatalf("prepared checkout branch = %q, want detached HEAD", branch)
|
|
}
|
|
}
|
|
|
|
func TestPrepareTaggedCheckoutRejectsWrongCommitBeforeCheckout(t *testing.T) {
|
|
repository := newTaggedDeliveryConsumer(t)
|
|
tagCommit := publishPreparationTag(t, repository)
|
|
currentCommit := advancePreparationCheckout(t, repository, "later local commit")
|
|
remote := buildGit(t, repository, "remote", "get-url", "origin")
|
|
buildGit(t, repository, "remote", "add", "candidate", remote)
|
|
|
|
err := releasekit.PrepareTaggedCheckout(context.Background(), releasekit.TaggedCheckoutRequest{
|
|
RepositoryDir: repository,
|
|
Version: "v1.2.3",
|
|
Remote: "candidate",
|
|
ExpectedCommit: currentCommit,
|
|
})
|
|
if err == nil {
|
|
t.Fatal("PrepareTaggedCheckout() succeeded for a tag that resolves to another commit")
|
|
}
|
|
if head := buildGit(t, repository, "rev-parse", "HEAD"); head != currentCommit {
|
|
t.Fatalf("wrong-tag rejection changed HEAD to %s, want %s (tag commit %s)", head, currentCommit, tagCommit)
|
|
}
|
|
if branch := buildGit(t, repository, "rev-parse", "--abbrev-ref", "HEAD"); branch == "HEAD" {
|
|
t.Fatal("wrong-tag rejection detached the checkout")
|
|
}
|
|
}
|
|
|
|
func TestPrepareTaggedCheckoutReportsLocalCheckoutConflict(t *testing.T) {
|
|
repository := newTaggedDeliveryConsumer(t)
|
|
tagCommit := publishPreparationTag(t, repository)
|
|
advancePreparationCheckout(t, repository, "later committed content")
|
|
path := filepath.Join(repository, "cmd/app/main.go")
|
|
if err := os.WriteFile(path, []byte("uncommitted conflicting content"), 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
currentCommit := buildGit(t, repository, "rev-parse", "HEAD")
|
|
|
|
err := releasekit.PrepareTaggedCheckout(context.Background(), releasekit.TaggedCheckoutRequest{
|
|
RepositoryDir: repository,
|
|
Version: "v1.2.3",
|
|
ExpectedCommit: tagCommit,
|
|
})
|
|
if err == nil {
|
|
t.Fatal("PrepareTaggedCheckout() succeeded despite a conflicting local edit")
|
|
}
|
|
if head := buildGit(t, repository, "rev-parse", "HEAD"); head != currentCommit {
|
|
t.Fatalf("conflicting checkout changed HEAD to %s, want %s", head, currentCommit)
|
|
}
|
|
contents, err := os.ReadFile(path)
|
|
if err != nil || string(contents) != "uncommitted conflicting content" {
|
|
t.Fatalf("conflicting local file = %q, %v", contents, err)
|
|
}
|
|
}
|
|
|
|
func TestPrepareTaggedCheckoutReportsConflictingLocalTag(t *testing.T) {
|
|
repository := newTaggedDeliveryConsumer(t)
|
|
publishPreparationTag(t, repository)
|
|
currentCommit := advancePreparationCheckout(t, repository, "later local commit")
|
|
buildGit(t, repository, "tag", "v1.2.3")
|
|
|
|
err := releasekit.PrepareTaggedCheckout(context.Background(), releasekit.TaggedCheckoutRequest{
|
|
RepositoryDir: repository,
|
|
Version: "v1.2.3",
|
|
ExpectedCommit: buildGit(t, repository, "rev-parse", "HEAD~1"),
|
|
})
|
|
if err == nil {
|
|
t.Fatal("PrepareTaggedCheckout() replaced a conflicting local tag")
|
|
}
|
|
if head := buildGit(t, repository, "rev-parse", "HEAD"); head != currentCommit {
|
|
t.Fatalf("conflicting tag fetch changed HEAD to %s, want %s", head, currentCommit)
|
|
}
|
|
if tagCommit := buildGit(t, repository, "rev-parse", "refs/tags/v1.2.3^{commit}"); tagCommit != currentCommit {
|
|
t.Fatalf("conflicting local tag changed to %s, want %s", tagCommit, currentCommit)
|
|
}
|
|
}
|
|
|
|
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"},
|
|
} {
|
|
err := releasekit.PrepareTaggedCheckout(context.Background(), request)
|
|
if err == nil {
|
|
t.Fatalf("PrepareTaggedCheckout(%#v) succeeded", request)
|
|
}
|
|
if _, err := buildGitOutput(repository, "show-ref", "--verify", "refs/tags/v1.2.3"); err == nil {
|
|
t.Fatal("input validation fetched the tag before rejecting the request")
|
|
}
|
|
}
|
|
if err := releasekit.PrepareTaggedCheckout(context.Background(), releasekit.TaggedCheckoutRequest{
|
|
RepositoryDir: repository, Version: "invalid", ExpectedCommit: "bad",
|
|
}); !errors.Is(err, releasekit.ErrInvalidVersion) {
|
|
t.Fatalf("invalid-version error = %v, want ErrInvalidVersion", err)
|
|
}
|
|
}
|
|
|
|
func TestPrepareBuildDependenciesRequiresRepositoryDirectory(t *testing.T) {
|
|
if err := releasekit.PrepareBuildDependencies(context.Background(), " "); err == nil {
|
|
t.Fatal("PrepareBuildDependencies() accepted an empty repository directory")
|
|
}
|
|
}
|
|
|
|
func publishPreparationTag(t *testing.T, repository string) string {
|
|
t.Helper()
|
|
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")
|
|
return commit
|
|
}
|
|
|
|
func advancePreparationCheckout(t *testing.T, repository, source string) string {
|
|
t.Helper()
|
|
path := filepath.Join(repository, "cmd/app/main.go")
|
|
if err := os.WriteFile(path, []byte("package main\n// "+source+"\nfunc main() {}\n"), 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
buildGit(t, repository, "add", "cmd/app/main.go")
|
|
buildGit(t, repository, "commit", "-m", source)
|
|
return buildGit(t, repository, "rev-parse", "HEAD")
|
|
}
|
|
|
|
func buildGitOutput(repository string, args ...string) ([]byte, error) {
|
|
command := exec.Command("git", args...)
|
|
command.Dir = repository
|
|
return command.Output()
|
|
}
|