diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2e684bd..bda0c4d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -56,6 +56,13 @@ jobs: - name: Zip the .app (ditto preserves the signature) run: ditto -c -k --sequesterRsrc --keepParent "gui/dist/Notary.app" "Notary-${{ github.ref_name }}-macos.zip" + # Published beside the zip, the same way each Linux tarball has its + # `.sha256`, so the macOS installer can read the digest of the file it + # downloads by name instead of picking it out of the release JSON, and a + # reader can check a download by hand from the release page. + - name: Write the zip's digest + run: shasum -a 256 "Notary-${{ github.ref_name }}-macos.zip" > "Notary-${{ github.ref_name }}-macos.zip.sha256" + # The tag and the manifest have to agree, and this is the last place it can # be checked. `gui/app.zon` is where the app reads the version it shows, # so tagging v0.5.0 on a tree that still says 0.4.0 ships a build that @@ -91,13 +98,13 @@ jobs: if gh release view "$GITHUB_REF_NAME" >/dev/null 2>&1; then echo "release exists; hiding it and replacing its artifact with the one built here" gh release edit "$GITHUB_REF_NAME" --draft=true - gh release upload "$GITHUB_REF_NAME" "$asset" --clobber + gh release upload "$GITHUB_REF_NAME" "$asset" "$asset.sha256" --clobber else # A DRAFT. The Linux tarballs are built by another job that takes # minutes longer, and a release published before they arrive is one # whose Linux installer 404s for exactly as long as that takes. The # `publish` job below lifts the draft once every artifact is up. - gh release create "$GITHUB_REF_NAME" "$asset" \ + gh release create "$GITHUB_REF_NAME" "$asset" "$asset.sha256" \ --draft \ --title "Notary $GITHUB_REF_NAME" \ --notes-file .github/RELEASE_NOTES.md diff --git a/scripts/check-release-assets.sh b/scripts/check-release-assets.sh index f083ef0..32c3ff7 100755 --- a/scripts/check-release-assets.sh +++ b/scripts/check-release-assets.sh @@ -24,7 +24,7 @@ LINUX_ARCHES="x86_64 aarch64" # Every file a release of $1 should carry, one per line. expected() { local tag="$1" ver="${1#v}" arch - printf '%s\n' "Notary-$tag-macos.zip" + printf '%s\n' "Notary-$tag-macos.zip" "Notary-$tag-macos.zip.sha256" for arch in $LINUX_ARCHES; do printf '%s\n' "notary-$ver-linux-$arch.tar.gz" "notary-$ver-linux-$arch.tar.gz.sha256" done @@ -87,7 +87,9 @@ self_test() { refuses "an unfinished upload" "Notary-v9.9.9-macos.zip" 1 "${full/$from/$to}" from="x86_64.tar.gz${tab}uploaded${tab}1000" to="x86_64.tar.gz${tab}uploaded${tab}0" refuses "an empty file" "notary-9.9.9-linux-x86_64.tar.gz" 1 "${full/$from/$to}" - refuses "a release built for another version" "Notary-v9.9.9-macos.zip" 5 \ + refuses "a macOS zip without its digest" "Notary-v9.9.9-macos.zip.sha256" 1 \ + "$(grep -v 'macos.zip.sha256' <<<"$full")" + refuses "a release built for another version" "Notary-v9.9.9-macos.zip" 6 \ "${full//9.9.9/9.9.8}" local matrix