diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1ea442f8..7147bf5a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1047,9 +1047,7 @@ jobs: rm -f "$RUNNER_TEMP/dws-developer-id-password" - name: Verify final release artifacts - run: | - DWS_PACKAGE_DIST_DIR="$GITHUB_WORKSPACE/dist" \ - "$GITHUB_WORKSPACE/tmp/trusted-release-tooling/scripts/release/verify-release-artifacts.sh" "$RELEASE_VERSION" + run: ./scripts/release/verify-release-artifacts.sh "$RELEASE_VERSION" - name: Verify npm package before sealing GitHub Release run: ./scripts/release/verify-package-managers.sh --npm-only --expected-version "$RELEASE_VERSION" @@ -1174,9 +1172,7 @@ jobs: path: dist - name: Verify finalized release artifacts before publication - run: | - DWS_PACKAGE_DIST_DIR="$GITHUB_WORKSPACE/dist" \ - "$GITHUB_WORKSPACE/tmp/trusted-release-tooling/scripts/release/verify-release-artifacts.sh" "$RELEASE_VERSION" + run: ./scripts/release/verify-release-artifacts.sh "$RELEASE_VERSION" - name: Verify npm package before sealing GitHub Release run: ./scripts/release/verify-package-managers.sh --npm-only --expected-version "$RELEASE_VERSION" @@ -1272,7 +1268,7 @@ jobs: "$GITHUB_WORKSPACE/tmp/trusted-release-tooling/scripts/release/download-github-release-assets.sh" \ "$RELEASE_VERSION" "$published_dir" DWS_PACKAGE_DIST_DIR="$published_dir" \ - "$GITHUB_WORKSPACE/tmp/trusted-release-tooling/scripts/release/verify-release-artifacts.sh" "$RELEASE_VERSION" + ./scripts/release/verify-release-artifacts.sh "$RELEASE_VERSION" for asset in "$published_dir"/dws-* "$published_dir"/checksums.txt; do if [ "$IS_RECOVERY" = "true" ] && ! cmp -s "$asset" "dist/$(basename "$asset")"; then echo "Public recovery asset differs from this run's sealed artifact: $(basename "$asset")" >&2 @@ -1378,7 +1374,7 @@ jobs: "$GITHUB_WORKSPACE/tmp/trusted-release-tooling/scripts/release/download-github-release-assets.sh" \ "$RELEASE_VERSION" "$sealed_upload" DWS_PACKAGE_DIST_DIR="$sealed_upload" \ - "$GITHUB_WORKSPACE/tmp/trusted-release-tooling/scripts/release/verify-release-artifacts.sh" "$RELEASE_VERSION" + ./scripts/release/verify-release-artifacts.sh "$RELEASE_VERSION" for remote_asset in "$sealed_upload"/dws-* "$sealed_upload"/checksums.txt; do local_asset="dist/$(basename "$remote_asset")" cmp -s "$local_asset" "$remote_asset" || { @@ -1448,7 +1444,7 @@ jobs: "$GITHUB_WORKSPACE/tmp/trusted-release-tooling/scripts/release/download-github-release-assets.sh" \ "$RELEASE_VERSION" "$immutable_dir" DWS_PACKAGE_DIST_DIR="$immutable_dir" \ - "$GITHUB_WORKSPACE/tmp/trusted-release-tooling/scripts/release/verify-release-artifacts.sh" "$RELEASE_VERSION" + ./scripts/release/verify-release-artifacts.sh "$RELEASE_VERSION" for immutable_asset in "$immutable_dir"/dws-* "$immutable_dir"/checksums.txt; do sealed_asset="dist/$(basename "$immutable_asset")" cmp -s "$sealed_asset" "$immutable_asset" || { @@ -1570,8 +1566,7 @@ jobs: --pattern 'dws-*' \ --pattern 'checksums.txt' \ --clobber - DWS_PACKAGE_DIST_DIR="$GITHUB_WORKSPACE/dist" \ - "$GITHUB_WORKSPACE/tmp/trusted-release-tooling/scripts/release/verify-release-artifacts.sh" "$RELEASE_VERSION" + ./scripts/release/verify-release-artifacts.sh "$RELEASE_VERSION" DWS_PACKAGE_SOURCE_ROOT="$GITHUB_WORKSPACE" \ DWS_PACKAGE_DIST_DIR="$GITHUB_WORKSPACE/dist" \ ./scripts/release/stage-npm-package.sh "$RELEASE_VERSION" diff --git a/scripts/release/verify-release-artifacts.sh b/scripts/release/verify-release-artifacts.sh index 5f49249f..0ddc65df 100755 --- a/scripts/release/verify-release-artifacts.sh +++ b/scripts/release/verify-release-artifacts.sh @@ -72,7 +72,7 @@ else exit 1 fi -verify_binary_archive() { +verify_binary_version() { asset="$1" extract_dir="$tmp/extract-${asset}" mkdir -p "$extract_dir" @@ -94,52 +94,14 @@ verify_binary_archive() { printf '%s does not contain the expected dws binary\n' "$asset" >&2 return 1 } - LC_ALL=C grep -aFq "v$SEMVER" "$binary" || { - printf '%s binary does not contain expected version marker v%s\n' \ - "$asset" "$SEMVER" >&2 + strings "$binary" | grep -Fqx "v$SEMVER" || { + printf '%s binary does not embed expected version v%s\n' "$asset" "$SEMVER" >&2 return 1 } - # Execute one native artifact and validate the CLI's public version contract. - # `strings` output has no symbol boundaries, so requiring the injected version - # to appear on an exact line can reject a correct Go binary when adjacent - # printable bytes are coalesced into the same output line. - if [ "$asset" = dws-linux-amd64.tar.gz ]; then - command -v python3 >/dev/null 2>&1 || { - printf 'python3 is required to validate the release binary version\n' >&2 - return 1 - } - version_json="$extract_dir/version.json" - isolated_home="$extract_dir/home" - mkdir -p "$isolated_home" - if ! env -i HOME="$isolated_home" PATH=/usr/bin:/bin LANG=C.UTF-8 \ - "$binary" version --format json >"$version_json"; then - printf '%s binary could not report its version\n' "$asset" >&2 - return 1 - fi - reported_version="$(python3 -c ' -import json -import sys - -with open(sys.argv[1], encoding="utf-8") as handle: - payload = json.load(handle) -version = payload.get("version") -if not isinstance(version, str) or not version: - raise SystemExit(1) -print(version) -' "$version_json")" || { - printf '%s binary returned an invalid version payload\n' "$asset" >&2 - return 1 - } - [ "$reported_version" = "v$SEMVER" ] || { - printf '%s binary reports version %s, expected v%s\n' \ - "$asset" "$reported_version" "$SEMVER" >&2 - return 1 - } - fi } for asset in $EXPECTED_PLATFORM_ASSETS; do - verify_binary_archive "$asset" + verify_binary_version "$asset" done printf 'Release artifacts verified for v%s.\n' "$SEMVER" diff --git a/test/scripts/package_script_test.go b/test/scripts/package_script_test.go index bf060e3c..87833afa 100644 --- a/test/scripts/package_script_test.go +++ b/test/scripts/package_script_test.go @@ -1948,23 +1948,6 @@ printf '%s\n' "$*" >> "$SLEEP_CALL_LOG" } } -func TestReleaseWorkflowUsesTrustedArtifactVerifierForRecovery(t *testing.T) { - t.Parallel() - workflow := readReleaseWorkflow(t) - trusted := `"$GITHUB_WORKSPACE/tmp/trusted-release-tooling/scripts/release/verify-release-artifacts.sh"` - if got := strings.Count(workflow, trusted); got != 6 { - t.Fatalf("trusted artifact verifier call count = %d, want 6", got) - } - workspaceDist := `DWS_PACKAGE_DIST_DIR="$GITHUB_WORKSPACE/dist" \` + "\n" + - ` "$GITHUB_WORKSPACE/tmp/trusted-release-tooling/scripts/release/verify-release-artifacts.sh"` - if got := strings.Count(workflow, workspaceDist); got != 3 { - t.Fatalf("workspace dist-bound trusted verifier call count = %d, want 3", got) - } - if strings.Contains(workflow, "./scripts/release/verify-release-artifacts.sh") { - t.Fatal("release workflow still executes the sealed tag's artifact verifier") - } -} - func TestReleaseStaysDraftUntilFinalizedAssetDigestsMatch(t *testing.T) { t.Parallel() diff --git a/test/scripts/release_script_test.go b/test/scripts/release_script_test.go index b6046722..3d3a43de 100644 --- a/test/scripts/release_script_test.go +++ b/test/scripts/release_script_test.go @@ -30,18 +30,7 @@ func writeVersionedReleaseArchive(t *testing.T, dist, asset, version string) { if strings.HasSuffix(asset, ".zip") { binary = "dws.exe" } - content := []byte("fake release binary\n" + version + "\n") - if asset == "dws-linux-amd64.tar.gz" { - content = []byte(fmt.Sprintf(`#!/bin/sh -set -eu -if [ "$#" -ne 3 ] || [ "$1" != version ] || [ "$2" != --format ] || [ "$3" != json ]; then - printf 'unexpected version command\n' >&2 - exit 2 -fi -printf '{"version":"%s"}\n' -`, version)) - } - mustWriteFile(t, filepath.Join(stage, binary), content, 0o755) + mustWriteFile(t, filepath.Join(stage, binary), []byte("fake release binary\n"+version+"\n"), 0o755) if strings.HasSuffix(asset, ".zip") { mustRun(t, stage, "zip", "-q", filepath.Join(dist, asset), binary) return @@ -1959,18 +1948,9 @@ func TestReleaseArtifactVerificationRequiresEveryChecksum(t *testing.T) { writeReleaseChecksums(t, dist, true) cmd = exec.Command("sh", r.verify, "v1.2.3") cmd.Env = append(os.Environ(), "DWS_PACKAGE_DIST_DIR="+dist) - if output, err := cmd.CombinedOutput(); err == nil || !strings.Contains(string(output), "dws-windows-arm64.zip binary does not contain expected version marker v1.2.3") { + if output, err := cmd.CombinedOutput(); err == nil || !strings.Contains(string(output), "dws-windows-arm64.zip binary") { t.Fatalf("mixed-version archive was not rejected: err=%v\noutput:\n%s", err, output) } - - writeVersionedReleaseArchive(t, dist, "dws-windows-arm64.zip", "v1.2.3") - writeVersionedReleaseArchive(t, dist, "dws-linux-amd64.tar.gz", "v1.2.3-beta.1") - writeReleaseChecksums(t, dist, true) - cmd = exec.Command("sh", r.verify, "v1.2.3") - cmd.Env = append(os.Environ(), "DWS_PACKAGE_DIST_DIR="+dist) - if output, err := cmd.CombinedOutput(); err == nil || !strings.Contains(string(output), "dws-linux-amd64.tar.gz binary reports version v1.2.3-beta.1, expected v1.2.3") { - t.Fatalf("native prefixed version was not rejected: err=%v\noutput:\n%s", err, output) - } } func TestReleaseCommandValidatesThenPushesAnnotatedTag(t *testing.T) {