Resolve annotated tag events before CI delivery
This commit is contained in:
@@ -20,7 +20,7 @@ steps:
|
||||
git check-ref-format "refs/tags/$${CI_COMMIT_TAG}"
|
||||
git fetch origin "refs/tags/$${CI_COMMIT_TAG}:refs/tags/$${CI_COMMIT_TAG}"
|
||||
tag_commit=$(git rev-parse "refs/tags/$${CI_COMMIT_TAG}^{commit}")
|
||||
expected_commit=$(printf '%s' "$${CI_COMMIT_SHA}" | tr '[:upper:]' '[:lower:]')
|
||||
expected_commit=$(git rev-parse --verify "$${CI_COMMIT_SHA}^{commit}")
|
||||
test "$(printf '%s' "$${tag_commit}" | tr '[:upper:]' '[:lower:]')" = "$${expected_commit}"
|
||||
git checkout --detach "$${tag_commit}"
|
||||
test "$(git rev-parse HEAD | tr '[:upper:]' '[:lower:]')" = "$${expected_commit}"
|
||||
@@ -46,5 +46,5 @@ steps:
|
||||
"$${bootstrap_dir}/releasekit" ci-deliver \
|
||||
--repo "$${CI_WORKSPACE}" \
|
||||
--prepared \
|
||||
--commit "$${CI_COMMIT_SHA}" \
|
||||
--commit "$${expected_commit}" \
|
||||
"$${CI_COMMIT_TAG}"
|
||||
|
||||
@@ -104,7 +104,9 @@ Woodpecker runs ReleaseKit's `ci-deliver` command for tags under
|
||||
- `SHA256SUMS`
|
||||
|
||||
Before running Go, the workflow fetches and verifies the event tag, checks it
|
||||
out detached, and confirms the source tree is clean. It copies the tagged
|
||||
out detached, and confirms the source tree is clean. It peels the event object
|
||||
ID to its commit before comparing it with the tag's commit, accepting both
|
||||
annotated tag objects and commit IDs from Woodpecker. It copies the tagged
|
||||
`go.mod` and `go.sum` into temporary module metadata outside the checkout. Go
|
||||
confirms that this configuration selects ReleaseKit, then builds its CLI using
|
||||
an alternate `-modfile`. The bootstrap executable and temporary files remain
|
||||
@@ -120,7 +122,7 @@ The resulting executable receives:
|
||||
"$${bootstrap_dir}/releasekit" ci-deliver \
|
||||
--repo "$${CI_WORKSPACE}" \
|
||||
--prepared \
|
||||
--commit "$${CI_COMMIT_SHA}" \
|
||||
--commit "$${expected_commit}" \
|
||||
"$${CI_COMMIT_TAG}"
|
||||
```
|
||||
|
||||
|
||||
@@ -118,7 +118,7 @@ func TestDeliveryWorkflowUsesModuleSelectedReleaseKit(t *testing.T) {
|
||||
"git fetch origin", "refs/tags/$${CI_COMMIT_TAG}",
|
||||
"git checkout --detach", "git status --porcelain",
|
||||
"go list", "-modfile=", "-m", "go build", "$${releasekit_module}/cmd/releasekit",
|
||||
"ci-deliver", "--repo \"$${CI_WORKSPACE}\"", "--prepared", "--commit \"$${CI_COMMIT_SHA}\"",
|
||||
"ci-deliver", "--repo \"$${CI_WORKSPACE}\"", "--prepared", "--commit",
|
||||
"\"$${CI_COMMIT_TAG}\"",
|
||||
} {
|
||||
if !strings.Contains(command, fragment) {
|
||||
@@ -160,6 +160,110 @@ func TestReleaseWrapperStopsWhenBootstrapFails(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeliveryWorkflowAcceptsTagObjectsAndCommits(t *testing.T) {
|
||||
var workflow struct {
|
||||
Steps []struct {
|
||||
Commands []string `yaml:"commands"`
|
||||
} `yaml:"steps"`
|
||||
}
|
||||
if err := yaml.Unmarshal([]byte(readText(t, "../.woodpecker/release.yml")), &workflow); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
command := strings.ReplaceAll(workflow.Steps[0].Commands[0], "$${", "${")
|
||||
root := t.TempDir()
|
||||
source := filepath.Join(root, "source")
|
||||
layout := releaseTestLayout{
|
||||
repo: filepath.Join(root, "checkout"), path: filepath.Join(root, "bin"),
|
||||
argsLog: filepath.Join(root, "tool-arguments"),
|
||||
}
|
||||
for _, directory := range []string{source, layout.path} {
|
||||
if err := os.MkdirAll(directory, 0755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
git := func(dir string, args ...string) string {
|
||||
t.Helper()
|
||||
cmd := exec.Command("git", args...)
|
||||
cmd.Dir = dir
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatalf("git %q: %v\n%s", args, err, output)
|
||||
}
|
||||
return strings.TrimSpace(string(output))
|
||||
}
|
||||
git(source, "init", "-b", "main")
|
||||
git(source, "config", "user.name", "Release test")
|
||||
git(source, "config", "user.email", "release-test@example.invalid")
|
||||
writeReleaseTestFile(t, filepath.Join(source, "go.mod"), []byte(readText(t, "../go.mod")), 0644)
|
||||
writeReleaseTestFile(t, filepath.Join(source, "go.sum"), nil, 0644)
|
||||
git(source, "add", "go.mod", "go.sum")
|
||||
git(source, "commit", "-m", "Initial fixture")
|
||||
unrelated := git(source, "rev-parse", "HEAD")
|
||||
git(source, "commit", "--allow-empty", "-m", "Release fixture")
|
||||
commit := git(source, "rev-parse", "HEAD")
|
||||
git(source, "tag", "-a", "v3.1.0", "-m", "Annotated release")
|
||||
git(source, "tag", "v3.1.1")
|
||||
tagObject := git(source, "rev-parse", "v3.1.0")
|
||||
git(root, "clone", "--quiet", source, layout.repo)
|
||||
toolStub := filepath.Join(root, "releasekit-stub")
|
||||
writeReleaseTestFile(t, toolStub, []byte(`#!/bin/sh
|
||||
printf '%s\0' "$@" > "$RELEASEKIT_ARGS_LOG"
|
||||
`), 0755)
|
||||
writeReleaseTestFile(t, filepath.Join(layout.path, "go"), []byte(`#!/bin/sh
|
||||
set -eu
|
||||
case "$1" in
|
||||
list) exit 0 ;;
|
||||
build)
|
||||
while [ "$#" -gt 0 ]; do
|
||||
if [ "$1" = "-o" ]; then
|
||||
cp "$RELEASEKIT_STUB" "$2"
|
||||
exit 0
|
||||
fi
|
||||
shift
|
||||
done ;;
|
||||
esac
|
||||
exit 1
|
||||
`), 0755)
|
||||
for _, tc := range []struct {
|
||||
name, tag, eventID string
|
||||
success bool
|
||||
}{
|
||||
{"annotated tag object", "v3.1.0", tagObject, true},
|
||||
{"annotated tag commit", "v3.1.0", commit, true},
|
||||
{"lightweight tag commit", "v3.1.1", commit, true},
|
||||
{"unrelated commit", "v3.1.0", unrelated, false},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
if err := os.Remove(layout.argsLog); err != nil && !os.IsNotExist(err) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
cmd := exec.Command("sh", "-c", command)
|
||||
cmd.Dir = layout.repo
|
||||
cmd.Env = layout.environment(map[string]string{
|
||||
"CI_WORKSPACE": layout.repo, "CI_COMMIT_TAG": tc.tag, "CI_COMMIT_SHA": tc.eventID,
|
||||
"RELEASEKIT_ARGS_LOG": layout.argsLog, "RELEASEKIT_STUB": toolStub,
|
||||
})
|
||||
output, err := cmd.CombinedOutput()
|
||||
if tc.success {
|
||||
if err != nil {
|
||||
t.Fatalf("workflow failed: %v\n%s", err, output)
|
||||
}
|
||||
want := []string{"ci-deliver", "--repo", layout.repo, "--prepared", "--commit", commit, tc.tag}
|
||||
if got := readNULArguments(t, layout.argsLog); !reflect.DeepEqual(got, want) {
|
||||
t.Fatalf("delivery arguments = %q, want %q", got, want)
|
||||
}
|
||||
} else {
|
||||
if err == nil {
|
||||
t.Fatal("workflow accepted an unrelated commit")
|
||||
}
|
||||
if _, err := os.Stat(layout.argsLog); !os.IsNotExist(err) {
|
||||
t.Fatalf("delivery ran after mismatched event; stat error = %v", err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestReleaseKitProfileDeclaresProductAndDeliverySettings(t *testing.T) {
|
||||
data, err := os.ReadFile("../releasekit.json")
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user