|
| 1 | +name: amdsev-snp-tools-release |
| 2 | + |
| 3 | +# Publishes a prebuilt snp-digest as a dedicated `snp-tools-v<X.Y.Z>` GitHub |
| 4 | +# Release. snp-digest changes far less often than the TEE VM image, so it |
| 5 | +# gets its own release stream instead of being rebuilt and re-attached on |
| 6 | +# every tee-vm-v* release; consumers pin ONE snp-tools release: |
| 7 | +# |
| 8 | +# - misc/AMDSEV/build-config carries SNP_DIGEST_RELEASE + SNP_DIGEST_SHA256. |
| 9 | +# The tee-vm release pipeline (amdsev-release.yml) downloads that pinned |
| 10 | +# binary to compute the published launch measurement, and install.sh |
| 11 | +# downloads it on SNP hosts so measurement verification needs no Rust |
| 12 | +# toolchain. Empty pins mean both fall back to building from source. |
| 13 | +# |
| 14 | +# Runbook: dispatch this workflow with the new version, then open a PR |
| 15 | +# bumping the two pins in build-config to the new tag + the SHA256 printed |
| 16 | +# in the release notes. The prebuilt is a convenience copy, not the trust |
| 17 | +# root — auditors rebuild snp-digest from the tagged snp-tools source |
| 18 | +# (pinned rust-toolchain.toml + Cargo.lock) rather than trusting the asset. |
| 19 | +# |
| 20 | +# Cut a new release when the snp-tools crate changes in a way that affects |
| 21 | +# snp-digest's output or interface (measurement algorithm inputs, CLI flags), |
| 22 | +# then bump the pins. Runner-only build: snp-digest is pure userspace |
| 23 | +# hashing; no SNP hardware involved. |
| 24 | + |
| 25 | +on: |
| 26 | + workflow_dispatch: |
| 27 | + inputs: |
| 28 | + version: |
| 29 | + description: 'snp-tools version to publish (SemVer, no prefix; e.g. 0.1.0)' |
| 30 | + required: true |
| 31 | + type: string |
| 32 | + |
| 33 | +concurrency: |
| 34 | + group: amdsev-snp-tools-release |
| 35 | + cancel-in-progress: false |
| 36 | + |
| 37 | +defaults: |
| 38 | + run: |
| 39 | + working-directory: misc/AMDSEV/snp-tools |
| 40 | + |
| 41 | +jobs: |
| 42 | + release: |
| 43 | + runs-on: ubuntu-latest |
| 44 | + timeout-minutes: 30 |
| 45 | + permissions: |
| 46 | + contents: write |
| 47 | + steps: |
| 48 | + - uses: actions/checkout@v4 |
| 49 | + |
| 50 | + - name: Validate version and tag availability |
| 51 | + id: ctx |
| 52 | + env: |
| 53 | + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
| 54 | + VERSION: ${{ inputs.version }} |
| 55 | + run: | |
| 56 | + if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-rc\.[0-9]+)?$ ]]; then |
| 57 | + echo "version must be plain SemVer (optionally -rc.N), got: $VERSION" >&2 |
| 58 | + exit 1 |
| 59 | + fi |
| 60 | + tag="snp-tools-v${VERSION}" |
| 61 | + if gh release view "$tag" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then |
| 62 | + echo "release $tag already exists" >&2 |
| 63 | + exit 1 |
| 64 | + fi |
| 65 | + echo "tag=$tag" >> "$GITHUB_OUTPUT" |
| 66 | + echo "sha=$GITHUB_SHA" >> "$GITHUB_OUTPUT" |
| 67 | +
|
| 68 | + - uses: Swatinem/rust-cache@v2 |
| 69 | + with: |
| 70 | + workspaces: misc/AMDSEV/snp-tools |
| 71 | + |
| 72 | + - name: Test |
| 73 | + # Same gate as PR CI (amdsev-snp-tools.yml): snp-digest computes the |
| 74 | + # measurement verifiers pin against — never ship an untested build. |
| 75 | + run: cargo test --release --locked |
| 76 | + |
| 77 | + - name: Build snp-digest |
| 78 | + # snp-tools/.cargo/config.toml pins build.target, so the binary lands |
| 79 | + # under target/<triple>/release; locate it explicitly rather than |
| 80 | + # hardcoding the triple here. |
| 81 | + run: | |
| 82 | + cargo build --release --locked |
| 83 | + SNP_DIGEST="$(find target -type f -name snp-digest -perm -u+x | head -n1)" |
| 84 | + if [ -z "$SNP_DIGEST" ]; then |
| 85 | + echo "snp-digest binary not found after build" >&2 |
| 86 | + exit 1 |
| 87 | + fi |
| 88 | + "$SNP_DIGEST" --help >/dev/null |
| 89 | + echo "SNP_DIGEST=$PWD/$SNP_DIGEST" >> "$GITHUB_ENV" |
| 90 | +
|
| 91 | + - name: Stage release artifacts |
| 92 | + id: stage |
| 93 | + env: |
| 94 | + TAG: ${{ steps.ctx.outputs.tag }} |
| 95 | + run: | |
| 96 | + mkdir -p release |
| 97 | + cp "$SNP_DIGEST" "release/snp-digest-${TAG}" |
| 98 | + sha="$(sha256sum "release/snp-digest-${TAG}" | awk '{print $1}')" |
| 99 | + printf '%s\n' "$sha" > "release/snp-digest-${TAG}.sha256" |
| 100 | + echo "sha=$sha" >> "$GITHUB_OUTPUT" |
| 101 | +
|
| 102 | + - name: Generate release notes |
| 103 | + env: |
| 104 | + TAG: ${{ steps.ctx.outputs.tag }} |
| 105 | + SHA: ${{ steps.stage.outputs.sha }} |
| 106 | + run: | |
| 107 | + toolchain="$(sed -n 's/^channel = "\(.*\)"$/\1/p' rust-toolchain.toml | head -n1)" |
| 108 | + { |
| 109 | + echo "# snp-tools ${TAG}" |
| 110 | + echo |
| 111 | + echo "Prebuilt \`snp-digest\` (x86_64 Linux, Rust ${toolchain}, \`--locked\`) — the" |
| 112 | + echo "SEV-SNP launch-measurement calculator used by the TEE VM release pipeline" |
| 113 | + echo "and by \`misc/AMDSEV/install.sh\` on SNP hosts." |
| 114 | + echo |
| 115 | + echo '```' |
| 116 | + echo "snp-digest-${TAG} SHA-256: ${SHA}" |
| 117 | + echo '```' |
| 118 | + echo |
| 119 | + echo "To adopt this release, bump both pins in \`misc/AMDSEV/build-config\`:" |
| 120 | + echo |
| 121 | + echo '```sh' |
| 122 | + echo "SNP_DIGEST_RELEASE=\"${TAG}\"" |
| 123 | + echo "SNP_DIGEST_SHA256=\"${SHA}\"" |
| 124 | + echo '```' |
| 125 | + echo |
| 126 | + echo "This is a convenience copy, not the trust root: auditors should rebuild" |
| 127 | + echo "\`snp-digest\` from this tag's \`misc/AMDSEV/snp-tools\` source (pinned" |
| 128 | + echo "\`rust-toolchain.toml\` + \`Cargo.lock\`)." |
| 129 | + } > release/release-notes.md |
| 130 | +
|
| 131 | + - name: Create GitHub Release |
| 132 | + uses: softprops/action-gh-release@v2 |
| 133 | + with: |
| 134 | + tag_name: ${{ steps.ctx.outputs.tag }} |
| 135 | + target_commitish: ${{ steps.ctx.outputs.sha }} |
| 136 | + prerelease: ${{ contains(inputs.version, '-rc.') }} |
| 137 | + body_path: misc/AMDSEV/snp-tools/release/release-notes.md |
| 138 | + files: | |
| 139 | + misc/AMDSEV/snp-tools/release/snp-digest-* |
0 commit comments