cat / goq
clone

turns a linux box into a private steam streaming appliance: plug in, tap your key, play from another computer

fix/docs-activation-truth
goq / .github / workflows / sigil-release.yml
sigil-release.yml 9.6K
1name: Sigil Release23on:4 workflow_dispatch:5 inputs:6 operation:7 description: Build a draft candidate or verify and promote an offline-signed draft8 required: true9 type: choice10 options:11 - build-candidate12 - promote-signed-draft13 tag:14 description: Existing immutable vVERSION tag15 required: true16 type: string1718permissions:19 contents: read2021concurrency:22 group: public-release-${{ inputs.tag }}23 cancel-in-progress: false2425jobs:26 candidate:27 name: Build clean Sigil candidate28 if: inputs.operation == 'build-candidate'29 runs-on: ubuntu-24.0430 timeout-minutes: 6031 environment: main32 permissions:33 contents: write34 env:35 CARGO_TERM_COLOR: always36 GH_TOKEN: ${{ github.token }}37 RELEASE_TAG: ${{ inputs.tag }}38 steps:39 - name: Check out exact release tag40 uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.141 with:42 ref: ${{ inputs.tag }}43 fetch-depth: 04445 - name: Verify immutable source identity46 run: |47 git show-ref --verify --quiet "refs/tags/$RELEASE_TAG"48 test "$(git rev-parse "refs/tags/$RELEASE_TAG^{commit}")" = "$(git rev-parse HEAD)"49 test -z "$(git status --porcelain=v1)"50 sigil_version="$(sed -n 's/^version = "\([^"]*\)"/\1/p' crates/sigil-host/Cargo.toml | head -n 1)"51 test "$RELEASE_TAG" = "v$sigil_version"5253 - name: Install release build dependencies54 run: |55 sudo apt-get update56 sudo apt-get install --yes --no-install-recommends \57 build-essential \58 ffmpeg \59 gstreamer1.0-plugins-base \60 gstreamer1.0-plugins-bad \61 gstreamer1.0-plugins-good \62 gstreamer1.0-plugins-ugly \63 gstreamer1.0-tools \64 libayatana-appindicator3-dev \65 libgstreamer-plugins-base1.0-dev \66 libgstreamer1.0-dev \67 librsvg2-dev \68 libssl-dev \69 libudev-dev \70 libwebkit2gtk-4.1-dev \71 libxdo-dev \72 pkg-config \73 python3-venv \74 shellcheck75 python3 -m venv "$RUNNER_TEMP/zig-venv"76 "$RUNNER_TEMP/zig-venv/bin/pip" install --disable-pip-version-check 'ziglang==0.16.0'77 install -d "$RUNNER_TEMP/release-bin"78 # Expand runner paths when the generated wrapper executes.79 # shellcheck disable=SC201680 printf '%s\n' \81 '#!/usr/bin/env bash' \82 'exec "$RUNNER_TEMP/zig-venv/bin/python" -m ziglang "$@"' \83 >"$RUNNER_TEMP/release-bin/zig"84 chmod 0755 "$RUNNER_TEMP/release-bin/zig"85 echo "$RUNNER_TEMP/release-bin" >>"$GITHUB_PATH"86 cargo install cargo-zigbuild --locked --version 0.23.08788 - name: Run complete repository gate89 env:90 GOQ_VERIFY_IN_PROCESS_GSTREAMER: "1"91 run: ./scripts/verify-demo-build.sh9293 - name: Build and verify unsigned candidate94 id: candidate95 run: |96 source_commit="$(git rev-parse HEAD)"97 target_contract="$(<release/sigil-target-contract.txt)"98 test "$target_contract" = linux-glibc2.17-x86_6499 asset_name="sigil-$RELEASE_TAG-$target_contract.tar.gz"100 output_dir="$RUNNER_TEMP/sigil-release"101 install -d -m 0700 "$output_dir"102 archive="$output_dir/$asset_name"103 ./scripts/package-bazzite-release.sh \104 --release-tag "$RELEASE_TAG" \105 --output "$archive"106 ./scripts/verify-sigil-release.sh \107 --tag "$RELEASE_TAG" \108 --archive "$archive" \109 --source-commit "$source_commit" \110 --candidate111 echo "archive=$archive" >>"$GITHUB_OUTPUT"112 echo "asset_name=$asset_name" >>"$GITHUB_OUTPUT"113114 - name: Refuse to replace an existing release115 run: |116 if gh release view "$RELEASE_TAG" >/dev/null 2>&1; then117 echo "release $RELEASE_TAG already exists; refusing to replace its assets" >&2118 exit 1119 fi120121 - name: Create draft with unsigned candidate122 run: |123 gh release create "$RELEASE_TAG" \124 --draft \125 --verify-tag \126 --title "goq $RELEASE_TAG public alpha" \127 --notes "Incomplete public-alpha draft. Promotion remains blocked until signed Portal assets and the offline Sigil Minisign signature are attached and jointly verified." \128 "${{ steps.candidate.outputs.archive }}" \129 "${{ steps.candidate.outputs.archive }}.sha256"130131 - name: Retain candidate for offline transfer132 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2133 with:134 name: sigil-${{ inputs.tag }}-offline-signing-candidate135 path: |136 ${{ steps.candidate.outputs.archive }}137 ${{ steps.candidate.outputs.archive }}.sha256138 if-no-files-found: error139 retention-days: 14140141 promote:142 name: Verify offline signature and promote143 if: inputs.operation == 'promote-signed-draft'144 runs-on: macos-26145 timeout-minutes: 30146 environment: main147 permissions:148 contents: write149 env:150 GH_TOKEN: ${{ github.token }}151 RELEASE_TAG: ${{ inputs.tag }}152 steps:153 - name: Check out exact release tag154 uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1155 with:156 ref: ${{ inputs.tag }}157 fetch-depth: 0158159 - name: Verify immutable source identity160 id: source161 run: |162 git show-ref --verify --quiet "refs/tags/$RELEASE_TAG"163 source_commit="$(git rev-parse "refs/tags/$RELEASE_TAG^{commit}")"164 test "$source_commit" = "$(git rev-parse HEAD)"165 test -z "$(git status --porcelain=v1)"166 sigil_version="$(sed -n 's/^version = "\([^"]*\)"/\1/p' crates/sigil-host/Cargo.toml | head -n 1)"167 test "$RELEASE_TAG" = "v$sigil_version"168 echo "commit=$source_commit" >>"$GITHUB_OUTPUT"169170 - name: Install public verification tools171 run: brew install minisign172173 - name: Require the complete signed public-alpha draft174 id: assets175 run: |176 release_json="$(gh release view "$RELEASE_TAG" --json isDraft,tagName,assets)"177 test "$(jq -r '.isDraft' <<<"$release_json")" = true178 test "$(jq -r '.tagName' <<<"$release_json")" = "$RELEASE_TAG"179 target_contract="$(<release/sigil-target-contract.txt)"180 test "$target_contract" = linux-glibc2.17-x86_64181 asset_name="sigil-$RELEASE_TAG-$target_contract.tar.gz"182 version="${RELEASE_TAG#v}"183 expected="$(printf '%s\n' \184 "$asset_name" \185 "$asset_name.minisig" \186 "$asset_name.sha256" \187 "Portal-${version}-arm64.dmg" \188 "Portal-${version}-arm64.dmg.sha256" \189 "Portal-${version}-arm64.json" | sort)"190 actual="$(jq -r '.assets[].name' <<<"$release_json" | sort)"191 test "$actual" = "$expected" || {192 echo "draft release assets do not match the complete six-asset public-alpha contract" >&2193 diff -u <(printf '%s\n' "$expected") <(printf '%s\n' "$actual") >&2 || true194 exit 1195 }196 output_dir="$RUNNER_TEMP/sigil-release"197 install -d -m 0700 "$output_dir"198 gh release download "$RELEASE_TAG" --dir "$output_dir"199 echo "archive=$output_dir/$asset_name" >>"$GITHUB_OUTPUT"200201 - name: Verify detached signature, checksum, archive, and provenance202 run: |203 ./scripts/verify-sigil-release.sh \204 --tag "$RELEASE_TAG" \205 --archive "${{ steps.assets.outputs.archive }}" \206 --source-commit "${{ steps.source.outputs.commit }}" \207 --public-key-file "$GITHUB_WORKSPACE/release/sigil-minisign.pub"208209 - name: Verify Portal assets against the same source tag210 run: |211 portal_dir="$RUNNER_TEMP/portal-release"212 install -d -m 0700 "$portal_dir"213 gh release download "$RELEASE_TAG" --dir "$portal_dir" --pattern 'Portal-*'214 python3 scripts/verify-portal-release.py assets \215 --repo-dir "$GITHUB_WORKSPACE" \216 --release-tag "$RELEASE_TAG" \217 --asset-dir "$portal_dir"218 for asset in "$portal_dir"/*; do219 gh attestation verify "$asset" \220 --repo "$GITHUB_REPOSITORY" \221 --signer-workflow "$GITHUB_REPOSITORY/.github/workflows/portal-release.yml" \222 --source-ref "refs/tags/$RELEASE_TAG" \223 --source-digest "${{ steps.source.outputs.commit }}" \224 --deny-self-hosted-runners > /dev/null225 done226 ./scripts/verify-macos-portal-signature.sh \227 --dmg "$portal_dir/Portal-${RELEASE_TAG#v}-arm64.dmg" \228 --expected-version "${RELEASE_TAG#v}" \229 --signing adhoc230231 - name: Publish verified prerelease232 run: |233 gh release edit "$RELEASE_TAG" \234 --draft=false \235 --prerelease \236 --notes "Verified public alpha for $RELEASE_TAG: Minisign-signed Linux glibc 2.17 x86_64 Sigil host package, validated on the supported Bazzite appliance, plus an ad-hoc signed macOS arm64 Portal DMG. Portal is NOT notarized: macOS will refuse it on first launch until you allow it under System Settings > Privacy & Security. Verify the DMG with its published SHA-256 and with 'gh attestation verify'. Hardware UAT remains tracked separately."237 test "$(gh release view "$RELEASE_TAG" --json isDraft --jq '.isDraft')" = false238 test "$(gh release view "$RELEASE_TAG" --json isPrerelease --jq '.isPrerelease')" = true