Use shared release scripts in Woodpecker
This commit is contained in:
@@ -2,74 +2,26 @@ when:
|
|||||||
- event: tag
|
- event: tag
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
validate:
|
validate-release:
|
||||||
image: golang:1.25
|
image: golang:1.25.5
|
||||||
commands:
|
commands:
|
||||||
- go test ./...
|
- ./scripts/check-release-candidate.sh "$CI_COMMIT_TAG"
|
||||||
- go test -race ./...
|
|
||||||
- go vet ./...
|
|
||||||
- go build ./...
|
|
||||||
- go test ./internal/doccheck
|
|
||||||
- go test ./internal/config -run '^TestExamplesLoadAndValidate$'
|
|
||||||
|
|
||||||
cross-build:
|
|
||||||
image: golang:1.25
|
|
||||||
depends_on: validate
|
|
||||||
commands:
|
|
||||||
- |
|
|
||||||
set -eu
|
|
||||||
output_dir="$(mktemp -d)"
|
|
||||||
trap 'rm -rf "$output_dir"' EXIT
|
|
||||||
for target in linux/amd64 linux/arm64 darwin/amd64 darwin/arm64 windows/amd64 windows/arm64; do
|
|
||||||
goos="${target%/*}"
|
|
||||||
goarch="${target#*/}"
|
|
||||||
CGO_ENABLED=0 GOOS="$goos" GOARCH="$goarch" go build -o "$output_dir/narratio-$goos-$goarch" ./cmd/narratio
|
|
||||||
done
|
|
||||||
|
|
||||||
build-release-assets:
|
build-release-assets:
|
||||||
image: golang:1.25
|
image: golang:1.25.5
|
||||||
depends_on: [validate, cross-build]
|
depends_on:
|
||||||
|
- validate-release
|
||||||
commands:
|
commands:
|
||||||
- |
|
- |
|
||||||
set -eu
|
set -eu
|
||||||
|
case "$PWD" in
|
||||||
version="$CI_COMMIT_TAG"
|
/*) ;;
|
||||||
dist="dist"
|
*) echo "release workspace must have an absolute path" >&2; exit 1 ;;
|
||||||
pkg="gitea.maximumdirect.net/eric/narratio/cmd/narratio"
|
esac
|
||||||
|
./scripts/build-release-assets.sh "$CI_COMMIT_TAG" "$PWD/dist"
|
||||||
rm -rf "$dist"
|
|
||||||
mkdir -p "$dist"
|
|
||||||
|
|
||||||
build_binary() {
|
|
||||||
goos="$1"
|
|
||||||
goarch="$2"
|
|
||||||
suffix="$3"
|
|
||||||
output="$dist/narratio-$version-$goos-$goarch$suffix"
|
|
||||||
|
|
||||||
CGO_ENABLED=0 GOOS="$goos" GOARCH="$goarch" \
|
|
||||||
go build -trimpath -ldflags "-s -w -X gitea.maximumdirect.net/eric/narratio/internal/buildinfo.Version=$version" \
|
|
||||||
-o "$output" "$pkg"
|
|
||||||
}
|
|
||||||
|
|
||||||
build_binary linux amd64 ""
|
|
||||||
build_binary linux arm64 ""
|
|
||||||
build_binary darwin amd64 ""
|
|
||||||
build_binary darwin arm64 ""
|
|
||||||
build_binary windows amd64 ".exe"
|
|
||||||
build_binary windows arm64 ".exe"
|
|
||||||
|
|
||||||
smoke_binary="$dist/narratio-version-smoke"
|
|
||||||
go build -trimpath -ldflags "-s -w -X gitea.maximumdirect.net/eric/narratio/internal/buildinfo.Version=$version" \
|
|
||||||
-o "$smoke_binary" "$pkg"
|
|
||||||
reported_version="$("$smoke_binary" version)"
|
|
||||||
rm -f "$smoke_binary"
|
|
||||||
if [ "$reported_version" != "narratio $version" ]; then
|
|
||||||
echo "release binary reported unexpected version: $reported_version" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
publish-release:
|
publish-release:
|
||||||
image: woodpeckerci/plugin-release
|
image: woodpeckerci/plugin-release:0.3.1
|
||||||
depends_on:
|
depends_on:
|
||||||
- build-release-assets
|
- build-release-assets
|
||||||
settings:
|
settings:
|
||||||
@@ -77,6 +29,8 @@ steps:
|
|||||||
from_secret: GITEA_RELEASE_TOKEN
|
from_secret: GITEA_RELEASE_TOKEN
|
||||||
files:
|
files:
|
||||||
- dist/narratio-*
|
- dist/narratio-*
|
||||||
|
title: Narratio ${CI_COMMIT_TAG}
|
||||||
|
note: docs/releases/${CI_COMMIT_TAG}.md
|
||||||
checksum: sha256
|
checksum: sha256
|
||||||
checksum-file: SHA256SUMS
|
checksum-file: SHA256SUMS
|
||||||
checksum-flatten: true
|
checksum-flatten: true
|
||||||
|
|||||||
@@ -329,7 +329,7 @@ lightweight tag and stops immediately when the upstream Git push succeeds.
|
|||||||
|
|
||||||
## Stage 4 — Asynchronous Woodpecker Release Integration
|
## Stage 4 — Asynchronous Woodpecker Release Integration
|
||||||
|
|
||||||
**Status: Pending**
|
**Status: Completed**
|
||||||
|
|
||||||
### Goal
|
### Goal
|
||||||
|
|
||||||
|
|||||||
@@ -60,9 +60,58 @@ func TestReleaseWorkflowRequiresValidation(t *testing.T) {
|
|||||||
if err := yaml.Unmarshal(data, &workflow); err != nil {
|
if err := yaml.Unmarshal(data, &workflow); err != nil {
|
||||||
t.Fatalf("parse release workflow: %v", err)
|
t.Fatalf("parse release workflow: %v", err)
|
||||||
}
|
}
|
||||||
if !workflowDependsOn(workflow.Steps, "publish-release", "validate", map[string]bool{}) {
|
validate, ok := workflow.Steps["validate-release"]
|
||||||
t.Fatal("publish-release must depend on validate so validation failures block releases")
|
if !ok {
|
||||||
|
t.Fatal("release workflow must define validate-release")
|
||||||
}
|
}
|
||||||
|
if validate.Image != "golang:1.25.5" || !containsWorkflowCommand(validate.Commands, `./scripts/check-release-candidate.sh "$CI_COMMIT_TAG"`) {
|
||||||
|
t.Fatalf("validate-release = %#v, want the shared candidate checker in golang:1.25.5", validate)
|
||||||
|
}
|
||||||
|
assets, ok := workflow.Steps["build-release-assets"]
|
||||||
|
if !ok {
|
||||||
|
t.Fatal("release workflow must define build-release-assets")
|
||||||
|
}
|
||||||
|
if assets.Image != "golang:1.25.5" || !workflowDependsOn(workflow.Steps, "build-release-assets", "validate-release", map[string]bool{}) {
|
||||||
|
t.Fatalf("build-release-assets = %#v, want validated golang:1.25.5 asset construction", assets)
|
||||||
|
}
|
||||||
|
assetCommands := strings.Join(assets.Commands, "\n")
|
||||||
|
if !strings.Contains(assetCommands, `./scripts/build-release-assets.sh "$CI_COMMIT_TAG" "$PWD/dist"`) || strings.Contains(assetCommands, "GOOS=") || strings.Contains(assetCommands, "go build") {
|
||||||
|
t.Fatalf("build-release-assets commands must delegate target construction: %q", assetCommands)
|
||||||
|
}
|
||||||
|
publish, ok := workflow.Steps["publish-release"]
|
||||||
|
if !ok {
|
||||||
|
t.Fatal("release workflow must define publish-release")
|
||||||
|
}
|
||||||
|
if publish.Image != "woodpeckerci/plugin-release:0.3.1" || !workflowDependsOn(workflow.Steps, "publish-release", "validate-release", map[string]bool{}) || !workflowDependsOn(workflow.Steps, "publish-release", "build-release-assets", map[string]bool{}) {
|
||||||
|
t.Fatalf("publish-release = %#v, want transitive validation and asset dependencies", publish)
|
||||||
|
}
|
||||||
|
for key, want := range map[string]any{
|
||||||
|
"title": "Narratio ${CI_COMMIT_TAG}",
|
||||||
|
"note": "docs/releases/${CI_COMMIT_TAG}.md",
|
||||||
|
"checksum": "sha256",
|
||||||
|
"checksum-file": "SHA256SUMS",
|
||||||
|
"checksum-flatten": true,
|
||||||
|
"file-exists": "skip",
|
||||||
|
"overwrite": false,
|
||||||
|
"prerelease": false,
|
||||||
|
} {
|
||||||
|
if got := publish.Settings[key]; got != want {
|
||||||
|
t.Fatalf("publish-release setting %q = %#v, want %#v", key, got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
files, ok := publish.Settings["files"].([]any)
|
||||||
|
if !ok || len(files) != 1 || files[0] != "dist/narratio-*" {
|
||||||
|
t.Fatalf("publish-release files = %#v", publish.Settings["files"])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func containsWorkflowCommand(commands []string, want string) bool {
|
||||||
|
for _, command := range commands {
|
||||||
|
if strings.Contains(command, want) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func repositoryRoot(t *testing.T) string {
|
func repositoryRoot(t *testing.T) string {
|
||||||
@@ -130,6 +179,9 @@ type woodpeckerWorkflow struct {
|
|||||||
|
|
||||||
type woodpeckerStep struct {
|
type woodpeckerStep struct {
|
||||||
DependsOn woodpeckerDependencies `yaml:"depends_on"`
|
DependsOn woodpeckerDependencies `yaml:"depends_on"`
|
||||||
|
Image string `yaml:"image"`
|
||||||
|
Commands []string `yaml:"commands"`
|
||||||
|
Settings map[string]any `yaml:"settings"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type woodpeckerDependencies []string
|
type woodpeckerDependencies []string
|
||||||
|
|||||||
Reference in New Issue
Block a user