diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index dbdae00..1467694 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -28,7 +28,8 @@ jobs: "https://github.com/GoCodeAlone/workflow/releases/download/v0.63.2/wfctl-linux-amd64" chmod +x "${RUNNER_TEMP}/wfctl-bin/wfctl" - name: Validate plugin contract for publish (pre-build) - run: "${{ runner.temp }}/wfctl-bin/wfctl plugin validate-contract --for-publish --tag ${{ github.ref_name }} ." + run: | + "${{ runner.temp }}/wfctl-bin/wfctl" plugin validate-contract --for-publish --tag "${{ github.ref_name }}" . - uses: goreleaser/goreleaser-action@v7 with: distribution: goreleaser @@ -36,6 +37,26 @@ jobs: args: release --clean env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # workflow#765: runtime truth-check via plugin verify-capabilities. + - name: Verify capabilities (runtime truth-check) + run: | + if [ ! -f dist/artifacts.json ]; then + echo "::error::dist/artifacts.json was not generated by GoReleaser" + exit 1 + fi + RUNNER_ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/') + BIN=$(jq -r --arg arch "$RUNNER_ARCH" \ + '[.[] | select(.type=="Binary" and .goos=="linux" and .goarch==$arch and (.name|startswith("workflow-plugin-migrations")))] | .[0].path // ""' \ + dist/artifacts.json) + if [ -z "$BIN" ] || [ "$BIN" = "null" ]; then + echo "::error::No matching linux/$RUNNER_ARCH workflow-plugin-migrations binary in dist/artifacts.json" + jq '.[] | {name, type, goos, goarch, path}' dist/artifacts.json + exit 1 + fi + "${{ runner.temp }}/wfctl-bin/wfctl" plugin verify-capabilities --binary "$BIN" . + - name: Verify shipped plugin.json carries tag (post-build) + run: | + "${{ runner.temp }}/wfctl-bin/wfctl" plugin validate-contract --for-publish --tag "${{ github.ref_name }}" --release-dir . . docker: name: Build & Push workflow-migrate image diff --git a/internal/plugin_test.go b/internal/plugin_test.go index 9e42664..b4f9664 100644 --- a/internal/plugin_test.go +++ b/internal/plugin_test.go @@ -5,6 +5,7 @@ import ( "os" "os/exec" "reflect" + "regexp" "sort" "strings" "testing" @@ -321,14 +322,13 @@ func TestPlugin_DownloadsMatchGoReleaserMainArchiveMatrix(t *testing.T) { for _, goos := range build.Goos { for _, goarch := range build.Goarch { key := goos + "/" + goarch - want[key] = "https://github.com/GoCodeAlone/workflow-plugin-migrations/releases/download/v" + - manifest.Version + "/workflow-plugin-migrations-" + goos + "-" + goarch + ".tar.gz" + want[key] = "https://github.com/GoCodeAlone/workflow-plugin-migrations/releases/download/v/workflow-plugin-migrations-" + goos + "-" + goarch + ".tar.gz" } } got := make(map[string]string) for _, d := range manifest.Downloads { - got[d.OS+"/"+d.Arch] = d.URL + got[d.OS+"/"+d.Arch] = normalizeReleaseDownloadURL(d.URL) } if !reflect.DeepEqual(got, want) { t.Fatalf("plugin.json downloads do not match GoReleaser main archive matrix\ngot: %#v\nwant: %#v", got, want) @@ -337,15 +337,14 @@ func TestPlugin_DownloadsMatchGoReleaserMainArchiveMatrix(t *testing.T) { func TestPlugin_GoReleaserManifestRewriteUpdatesDownloadURLs(t *testing.T) { cfg := readGoReleaserConfig(t) - hook := "" + var hooks []string for _, candidate := range cfg.Before.Hooks { if strings.Contains(candidate, "/releases/download/") && strings.Contains(candidate, "/releases/download/v{{ .Version }}/") { - hook = candidate - break + hooks = append(hooks, candidate) } } - if hook == "" { + if len(hooks) == 0 { t.Fatalf("GoReleaser before hook must rewrite download URLs with the v tag prefix") } @@ -361,10 +360,12 @@ func TestPlugin_GoReleaserManifestRewriteUpdatesDownloadURLs(t *testing.T) { } const snapshotVersion = "0.3.6-SNAPSHOT-test" - cmd := exec.Command("sh", "-c", strings.ReplaceAll(hook, "{{ .Version }}", snapshotVersion)) - cmd.Dir = tmp - if out, err := cmd.CombinedOutput(); err != nil { - t.Fatalf("run GoReleaser manifest rewrite hook: %v\n%s", err, out) + for _, hook := range hooks { + cmd := exec.Command("sh", "-c", strings.ReplaceAll(hook, "{{ .Version }}", snapshotVersion)) + cmd.Dir = tmp + if out, err := cmd.CombinedOutput(); err != nil { + t.Fatalf("run GoReleaser manifest rewrite hook: %v\n%s", err, out) + } } for _, name := range []string{"plugin.json", "plugin.atlas.json"} { @@ -380,6 +381,12 @@ func TestPlugin_GoReleaserManifestRewriteUpdatesDownloadURLs(t *testing.T) { } } +var releaseDownloadURLRe = regexp.MustCompile(`/releases/download/v[^/]+/`) + +func normalizeReleaseDownloadURL(url string) string { + return releaseDownloadURLRe.ReplaceAllString(url, "/releases/download/v/") +} + func TestPlugin_GoReleaserArchivesPackageCorrectManifestsAndContracts(t *testing.T) { cfg := readGoReleaserConfig(t) diff --git a/plugin.json b/plugin.json index 26dfd22..2af89d0 100644 --- a/plugin.json +++ b/plugin.json @@ -1,6 +1,6 @@ { "name": "workflow-plugin-migrations", - "version": "0.3.9", + "version": "0.0.0", "description": "Database migration plugin for the workflow engine: golang-migrate + goose + atlas drivers, pre-deploy runner, wfctl migrate CLI, static lint tool", "author": "GoCodeAlone", "license": "Apache-2.0",