Private CA Desktop Release #24
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --- | |
| # yamllint disable rule:line-length | |
| # yamllint disable rule:comments | |
| name: Private CA Desktop Release | |
| "on": | |
| schedule: | |
| - cron: "5 15 * * *" | |
| workflow_dispatch: | |
| issues: | |
| types: [labeled] | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: private-ca-release-${{ github.event.issue.number || github.run_id }} | |
| cancel-in-progress: false | |
| env: | |
| UPSTREAM_REPOSITORY: block/buzz | |
| PRIVATE_CA_PATCH_COMMIT: 6d03a38da5e3402bf97df1b3c46152887eb3778e | |
| SECURITY_PATCH_COMMIT: 7dbfcd785be0a9c002863a793c4fbab89a6258c3 | |
| jobs: | |
| monitor: | |
| if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| permissions: | |
| contents: read | |
| issues: write | |
| steps: | |
| - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 | |
| - name: Create one BUILD or SKIP ticket | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| set -euo pipefail | |
| release="$(gh api "repos/${UPSTREAM_REPOSITORY}/releases/latest")" | |
| tag="$(jq -r '.tag_name' <<<"${release}")" | |
| tag="$(scripts/normalize-private-ca-desktop-tag.sh "${tag}")" | |
| existing="$(gh issue list --state all --search "[Buzz update] ${tag} available in:title" --json number --jq '.[0].number // empty')" | |
| [[ -z "${existing}" ]] || { echo "ticket already exists: #${existing}"; exit 0; } | |
| work="$(mktemp -d)"; trap 'rm -rf "${work}"' EXIT | |
| git clone --depth 1 --branch "${tag}" "https://github.com/${UPSTREAM_REPOSITORY}.git" "${work}/source" | |
| source_sha="$(git -C "${work}/source" rev-parse HEAD)" | |
| if for patch_commit in "${PRIVATE_CA_PATCH_COMMIT}" "${SECURITY_PATCH_COMMIT}"; do | |
| git -C "${work}/source" fetch --depth 2 "https://github.com/${GITHUB_REPOSITORY}.git" "${patch_commit}" | |
| git -C "${work}/source" cherry-pick --no-commit "${patch_commit}" | |
| done; then | |
| patch_status=clean | |
| else | |
| patch_status=conflict | |
| fi | |
| git -C "${work}/source" reset --hard "${source_sha}" | |
| for label in buzz-update build-approved skip remediation-required built accepted; do | |
| gh label create "${label}" --force --color 0E8A16 --description "Buzz private-CA release lifecycle" >/dev/null | |
| done | |
| cat >"${work}/issue.md" <<EOF | |
| <!-- buzz-private-ca-release tag=${tag} source_sha=${source_sha} private_ca_patch_sha=${PRIVATE_CA_PATCH_COMMIT} security_patch_sha=${SECURITY_PATCH_COMMIT} patch_status=${patch_status} --> | |
| ## Buzz ${tag} is available | |
| Upstream release: $(jq -r '.html_url' <<<"${release}") | |
| Published: $(jq -r '.published_at' <<<"${release}") | |
| Immutable source SHA: \`${source_sha}\` | |
| Certified patch-series applicability: **${patch_status}** | |
| ### Changelog | |
| $(jq -r '.body // "No upstream release notes supplied."' <<<"${release}") | |
| ### Decision required | |
| - Add \`build-approved\` to start the guarded arm64 build. Only @BrianInAz can approve. | |
| - Add \`skip\` and close this issue to record no build is wanted. | |
| - If applicability is \`conflict\`, use \`remediation-required\`; do not approve. | |
| EOF | |
| labels=(--label buzz-update) | |
| if [[ "${patch_status}" == conflict ]]; then | |
| labels+=(--label remediation-required) | |
| fi | |
| gh issue create --title "[Buzz update] ${tag} available" "${labels[@]}" --assignee BrianInAz --body-file "${work}/issue.md" | |
| skip: | |
| if: >- | |
| github.event_name == 'issues' && github.event.action == 'labeled' && | |
| github.event.label.name == 'skip' && github.actor == 'BrianInAz' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| permissions: | |
| issues: write | |
| steps: | |
| - name: Record the explicit no-build decision | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| set -euo pipefail | |
| gh issue comment "${{ github.event.issue.number }}" --repo "${GITHUB_REPOSITORY}" --body "Skipped by @BrianInAz; no private-CA package was built." | |
| gh issue close "${{ github.event.issue.number }}" --repo "${GITHUB_REPOSITORY}" | |
| accepted: | |
| if: >- | |
| github.event_name == 'issues' && github.event.action == 'labeled' && | |
| github.event.label.name == 'accepted' && github.actor == 'BrianInAz' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| permissions: | |
| issues: write | |
| steps: | |
| - name: Close an accepted release ticket | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| ISSUE_NUMBER: ${{ github.event.issue.number }} | |
| run: | | |
| set -euo pipefail | |
| body="$(gh issue view "${ISSUE_NUMBER}" --repo "${GITHUB_REPOSITORY}" --json body --jq .body)" | |
| grep -Eq '^<!-- buzz-private-ca-release tag=(desktop-)?v[0-9]+\.[0-9]+\.[0-9]+ source_sha=[0-9a-f]{40} private_ca_patch_sha=[0-9a-f]{40} security_patch_sha=[0-9a-f]{40} patch_status=clean -->$' <<<"${body}" || { echo "not a clean monitor-created ticket" >&2; exit 1; } | |
| labels="$(gh issue view "${ISSUE_NUMBER}" --repo "${GITHUB_REPOSITORY}" --json labels --jq '.labels[].name')" | |
| grep -Fxq built <<<"${labels}" || { echo "accepted requires the built lifecycle state" >&2; exit 1; } | |
| gh issue comment "${ISSUE_NUMBER}" --repo "${GITHUB_REPOSITORY}" --body "Accepted by @BrianInAz after private WSS, state-preserving install, restart, reconnect, and history-restoration evidence was recorded." | |
| gh issue close "${ISSUE_NUMBER}" --repo "${GITHUB_REPOSITORY}" | |
| approval: | |
| if: >- | |
| github.event_name == 'issues' && github.event.action == 'labeled' && | |
| github.event.label.name == 'build-approved' && github.actor == 'BrianInAz' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| permissions: | |
| contents: read | |
| issues: read | |
| outputs: | |
| issue_number: ${{ steps.verify.outputs.issue_number }} | |
| tag: ${{ steps.verify.outputs.tag }} | |
| source_sha: ${{ steps.verify.outputs.source_sha }} | |
| steps: | |
| - id: verify | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| ISSUE_NUMBER: ${{ github.event.issue.number }} | |
| run: | | |
| set -euo pipefail | |
| body="$(gh issue view "${ISSUE_NUMBER}" --repo "${GITHUB_REPOSITORY}" --json body --jq .body)" | |
| marker="$(grep -E '^<!-- buzz-private-ca-release tag=(desktop-)?v[0-9]+\.[0-9]+\.[0-9]+ source_sha=[0-9a-f]{40} private_ca_patch_sha=[0-9a-f]{40} security_patch_sha=[0-9a-f]{40} patch_status=clean -->$' <<<"${body}")" | |
| [[ -n "${marker}" ]] || { echo "not a clean monitor-created ticket" >&2; exit 1; } | |
| tag="$(sed -E 's/.*tag=([^ ]+).*/\1/' <<<"${marker}")" | |
| source_sha="$(sed -E 's/.*source_sha=([^ ]+).*/\1/' <<<"${marker}")" | |
| private_ca_patch_sha="$(sed -E 's/.*private_ca_patch_sha=([^ ]+).*/\1/' <<<"${marker}")" | |
| security_patch_sha="$(sed -E 's/.*security_patch_sha=([^ ]+).*/\1/' <<<"${marker}")" | |
| [[ "${private_ca_patch_sha}" == "${PRIVATE_CA_PATCH_COMMIT}" ]] || { echo "wrong private-CA patch" >&2; exit 1; } | |
| [[ "${security_patch_sha}" == "${SECURITY_PATCH_COMMIT}" ]] || { echo "wrong security patch" >&2; exit 1; } | |
| remote_sha="$(git ls-remote "https://github.com/${UPSTREAM_REPOSITORY}.git" "refs/tags/${tag}^{}" | awk '{print $1}')" | |
| [[ -n "${remote_sha}" ]] || remote_sha="$(git ls-remote "https://github.com/${UPSTREAM_REPOSITORY}.git" "refs/tags/${tag}" | awk '{print $1}')" | |
| [[ "${remote_sha}" == "${source_sha}" ]] || { echo "tag SHA changed" >&2; exit 1; } | |
| echo "issue_number=${ISSUE_NUMBER}" >> "$GITHUB_OUTPUT" | |
| echo "tag=${tag}" >> "$GITHUB_OUTPUT" | |
| echo "source_sha=${source_sha}" >> "$GITHUB_OUTPUT" | |
| validate: | |
| needs: approval | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 60 | |
| permissions: | |
| contents: read | |
| steps: | |
| - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 | |
| - uses: cashapp/activate-hermit@cea9af7913204a965fd488637a8d1811bba2e616 # v1 | |
| - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 | |
| - name: Fetch immutable source and apply certified patch series | |
| run: | | |
| set -euo pipefail | |
| git clone --depth 1 --branch "${{ needs.approval.outputs.tag }}" "https://github.com/${UPSTREAM_REPOSITORY}.git" "$RUNNER_TEMP/source" | |
| [[ "$(git -C "$RUNNER_TEMP/source" rev-parse HEAD)" == "${{ needs.approval.outputs.source_sha }}" ]] | |
| for patch_commit in "${PRIVATE_CA_PATCH_COMMIT}" "${SECURITY_PATCH_COMMIT}"; do | |
| git -C "$RUNNER_TEMP/source" fetch --depth 2 "https://github.com/${GITHUB_REPOSITORY}.git" "${patch_commit}" | |
| git -C "$RUNNER_TEMP/source" cherry-pick --no-commit "${patch_commit}" | |
| done | |
| git -C "$RUNNER_TEMP/source" diff --check | |
| - name: Reject vulnerable root and Apple Silicon desktop graphs | |
| working-directory: ${{ runner.temp }}/source | |
| run: | | |
| set -euo pipefail | |
| cargo-deny --locked check --config deny.toml advisories | |
| cargo-deny --locked \ | |
| --manifest-path desktop/src-tauri/Cargo.toml \ | |
| --target aarch64-apple-darwin \ | |
| --exclude-dev \ | |
| check --config deny.toml advisories | |
| - name: Run full upstream CI | |
| working-directory: ${{ runner.temp }}/source | |
| run: just ci | |
| - name: Stub Tauri sidecar binaries for test compilation | |
| working-directory: ${{ runner.temp }}/source | |
| run: | | |
| set -euo pipefail | |
| host_triple="$(rustc -vV | sed -n 's/^host: //p')" | |
| mkdir -p desktop/src-tauri/binaries | |
| for sidecar in buzz-acp buzz-agent buzz-dev-mcp git-credential-nostr buzz; do | |
| touch "desktop/src-tauri/binaries/${sidecar}-${host_triple}" | |
| done | |
| - name: Run focused native connector test | |
| working-directory: ${{ runner.temp }}/source | |
| run: cargo test --manifest-path desktop/src-tauri/Cargo.toml native_websocket::tests::native_websocket_platform_tls_connector_is_available | |
| package: | |
| name: Build private-CA package on standard hosted Apple Silicon | |
| needs: [approval, validate] | |
| runs-on: macos-15 | |
| timeout-minutes: 90 | |
| permissions: | |
| contents: read | |
| issues: write | |
| steps: | |
| - name: Require free standard public ARM64 runner | |
| env: | |
| REPOSITORY_IS_PRIVATE: ${{ github.event.repository.private }} | |
| run: | | |
| set -euo pipefail | |
| [[ "${REPOSITORY_IS_PRIVATE}" == "false" ]] || { | |
| echo "This package lane is approved only for free standard runners in a public repository." >&2 | |
| exit 1 | |
| } | |
| [[ "$(uname -m)" == "arm64" ]] || { | |
| echo "macos-15 must resolve to a standard Apple Silicon runner." >&2 | |
| exit 1 | |
| } | |
| - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 | |
| with: | |
| persist-credentials: false | |
| - uses: cashapp/activate-hermit@cea9af7913204a965fd488637a8d1811bba2e616 # v1 | |
| - name: Build and verify ad-hoc-signed package | |
| env: | |
| SOURCE_SHA: ${{ needs.approval.outputs.source_sha }} | |
| TAG: ${{ needs.approval.outputs.tag }} | |
| run: | | |
| set -euo pipefail | |
| output_directory="${RUNNER_TEMP}/private-ca/${TAG}" | |
| scripts/build-private-ca-macos.sh "${TAG}" "${SOURCE_SHA}" "${output_directory}" | |
| ( | |
| cd "${output_directory}" | |
| shasum -a 256 -c SHA256SUMS | |
| ) | |
| - name: Upload short-lived private-CA candidate | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 | |
| with: | |
| name: buzz-private-ca-${{ needs.approval.outputs.tag }}-${{ needs.approval.outputs.source_sha }} | |
| path: ${{ runner.temp }}/private-ca/${{ needs.approval.outputs.tag }}/ | |
| if-no-files-found: error | |
| compression-level: 0 | |
| retention-days: 7 | |
| - name: Record hosted package evidence | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| ARTIFACT_NAME: buzz-private-ca-${{ needs.approval.outputs.tag }}-${{ needs.approval.outputs.source_sha }} | |
| ISSUE_NUMBER: ${{ needs.approval.outputs.issue_number }} | |
| SOURCE_SHA: ${{ needs.approval.outputs.source_sha }} | |
| TAG: ${{ needs.approval.outputs.tag }} | |
| run: | | |
| set -euo pipefail | |
| run_url="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" | |
| gh issue comment "${ISSUE_NUMBER}" --repo "${GITHUB_REPOSITORY}" --body "GitHub-hosted macOS package built on the free standard macos-15 Apple Silicon runner. Source: \`${SOURCE_SHA}\`. Certified patches: \`${PRIVATE_CA_PATCH_COMMIT}\`, \`${SECURITY_PATCH_COMMIT}\`. Artifact: \`${ARTIFACT_NAME}\` (retained 7 days). Run: ${run_url}. The app is ad-hoc signed; no Apple signing identity or secret was used. Next: run the private WSS gate, then download and perform state-preserving installation and acceptance on Brian's MacBook before adding \`accepted\`." | |
| gh issue edit "${ISSUE_NUMBER}" --repo "${GITHUB_REPOSITORY}" --add-label built |