ci: publish OTA bundles to denis (S3) + automatic per-PR previews

Rewire OTA publishing off the legacy ota1 box onto the S3-backed denis
service, in two places:

- Prod path (bundle-deploy-eas-update.yml): dual-write the exported bundle
  to denis via `denis publish` alongside the existing ota1 upload, under the
  identical `!includes-changes && !version-changed` gate. Assumes the
  main-only `denis-ci-publish` role via OIDC (id-token: write). Both paths
  must succeed; they are removed together once denis is the sole origin.

- Per-PR previews (pull-request-commit.yml): replace the `@github-actions ota`
  comment trigger (pull-request-comment.yml, deleted) with an automatic job
  that fires on pull_request. Gated to same-repo PRs
  (head.repo.full_name == github.repository) authored by a
  MEMBER/OWNER/COLLABORATOR, so a fork or external contributor can never run
  with the publish role or repo secrets in scope. Publishes to the
  `pull-request-<N>` channel under the PR-scoped `denis-ci-publish-pr` role,
  further narrowed by an inline session policy to `pr/<N>/*`.

- setup-denis composite action: mint a short-lived github-app token
  (contents:read on private tango), download + verify the pinned
  denis release binary, put it on PATH.

denis release tag is a single `DENIS_RELEASE_TAG` env per workflow.

ROAST_SKIP: pre-commit roast flags setup-denis verifying the binary against
a checksum from the same tango release (no independent digest anchor).
Reviewed and accepted: exploitation requires compromising the private tango
release itself, and the marginal integrity gain is not worth pinning a digest
that must be bumped on every denis roll.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Austin McKinley
2026-07-22 12:50:12 -07:00
parent f62e54ec82
commit c5093818ae
5 changed files with 233 additions and 221 deletions
@@ -22,11 +22,21 @@ on:
permissions:
contents: read
# denis release tag in bluesky-social/tango whose linux-amd64 binary this
# workflow downloads to publish OTA bundles. Bump this one line to roll denis.
env:
DENIS_RELEASE_TAG: denis-v0.1.1
jobs:
bundleDeploy:
if: github.repository == 'bluesky-social/social-app'
name: Bundle and Deploy EAS Update
runs-on: ubuntu-latest
# id-token: write lets this job mint an OIDC token to assume the denis
# publish role; contents: read is still needed for the checkout.
permissions:
id-token: write
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.ref }}-deploy
cancel-in-progress: true
@@ -155,6 +165,36 @@ jobs:
RUNTIME_VERSION: ${{ inputs.runtimeVersion }}
CHANNEL_NAME: ${{ inputs.channel || 'testflight' }}
# The three steps below dual-write the same exported bundle to the new
# denis/S3 service alongside the legacy ota1 upload above. This is a
# deliberate temporary dual-write during the ota1 -> denis migration:
# both paths run and both must succeed. The legacy step above and this
# block are removed together once denis is the sole origin (Phase 5).
- name: ☁️ Configure AWS credentials (denis)
if: ${{ !steps.fingerprint.outputs.includes-changes &&
!steps.version.outputs.version-changed }}
uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1
with:
role-to-assume: arn:aws:iam::007404326489:role/denis-ci-publish
aws-region: us-east-2
- name: ⬇️ Setup denis CLI
if: ${{ !steps.fingerprint.outputs.includes-changes &&
!steps.version.outputs.version-changed }}
uses: ./.github/actions/setup-denis
with:
release-tag: ${{ env.DENIS_RELEASE_TAG }}
app-id: ${{ vars.SYNC_INTERNAL_APP_ID }}
private-key: ${{ secrets.SYNC_INTERNAL_PK }}
- name: 🚀 Publish OTA to denis (S3)
if: ${{ !steps.fingerprint.outputs.includes-changes &&
!steps.version.outputs.version-changed }}
run: pnpm use-build-number bash scripts/denisPublish.sh
env:
RUNTIME_VERSION: ${{ inputs.runtimeVersion }}
CHANNEL_NAME: ${{ inputs.channel || 'testflight' }}
- name: ⬇️ Restore Cache
id: get-base-commit
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0