ci: publish OTA to denis (S3) + automatic per-PR previews (#11235)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,50 @@
|
|||||||
|
---
|
||||||
|
name: Setup denis CLI
|
||||||
|
description: >
|
||||||
|
Download and verify the denis OTA publish binary from the (private)
|
||||||
|
bluesky-social/tango releases and put it on PATH. Uses a short-lived GitHub
|
||||||
|
App token scoped to contents:read on tango, since the default GITHUB_TOKEN
|
||||||
|
cannot read a private repo's releases.
|
||||||
|
|
||||||
|
inputs:
|
||||||
|
release-tag:
|
||||||
|
description: denis release tag in bluesky-social/tango to download
|
||||||
|
required: true
|
||||||
|
app-id:
|
||||||
|
description: GitHub App ID for the token used to read tango releases
|
||||||
|
required: true
|
||||||
|
private-key:
|
||||||
|
description: GitHub App private key
|
||||||
|
required: true
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: composite
|
||||||
|
steps:
|
||||||
|
- name: 🔑 Mint tango read token
|
||||||
|
id: tango-token
|
||||||
|
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
|
||||||
|
with:
|
||||||
|
app-id: ${{ inputs.app-id }}
|
||||||
|
private-key: ${{ inputs.private-key }}
|
||||||
|
repositories: tango
|
||||||
|
permission-contents: read
|
||||||
|
|
||||||
|
- name: ⬇️ Download and verify denis binary
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ steps.tango-token.outputs.token }}
|
||||||
|
RELEASE_TAG: ${{ inputs.release-tag }}
|
||||||
|
run: |
|
||||||
|
BIN_DIR="$RUNNER_TEMP/denis-bin"
|
||||||
|
mkdir -p "$BIN_DIR"
|
||||||
|
cd "$BIN_DIR"
|
||||||
|
gh release download "$RELEASE_TAG" \
|
||||||
|
--repo bluesky-social/tango \
|
||||||
|
--pattern denis-linux-amd64 \
|
||||||
|
--pattern denis-linux-amd64.sha256 \
|
||||||
|
--clobber
|
||||||
|
# Verify before making it executable / putting it on PATH.
|
||||||
|
sha256sum -c denis-linux-amd64.sha256
|
||||||
|
mv denis-linux-amd64 denis
|
||||||
|
chmod +x denis
|
||||||
|
echo "$BIN_DIR" >> "$GITHUB_PATH"
|
||||||
@@ -22,11 +22,21 @@ on:
|
|||||||
permissions:
|
permissions:
|
||||||
contents: read
|
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:
|
jobs:
|
||||||
bundleDeploy:
|
bundleDeploy:
|
||||||
if: github.repository == 'bluesky-social/social-app'
|
if: github.repository == 'bluesky-social/social-app'
|
||||||
name: Bundle and Deploy EAS Update
|
name: Bundle and Deploy EAS Update
|
||||||
runs-on: ubuntu-latest
|
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:
|
concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.ref }}-deploy
|
group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.ref }}-deploy
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
@@ -155,6 +165,36 @@ jobs:
|
|||||||
RUNTIME_VERSION: ${{ inputs.runtimeVersion }}
|
RUNTIME_VERSION: ${{ inputs.runtimeVersion }}
|
||||||
CHANNEL_NAME: ${{ inputs.channel || 'testflight' }}
|
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
|
- name: ⬇️ Restore Cache
|
||||||
id: get-base-commit
|
id: get-base-commit
|
||||||
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
||||||
|
|||||||
@@ -1,221 +0,0 @@
|
|||||||
---
|
|
||||||
name: PR Comment Trigger
|
|
||||||
|
|
||||||
on:
|
|
||||||
issue_comment:
|
|
||||||
types: [created]
|
|
||||||
|
|
||||||
# Permissions are granted per-job below; anything unlisted defaults to none
|
|
||||||
permissions: {}
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
handle-comment:
|
|
||||||
if: github.event.issue.pull_request
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
outputs:
|
|
||||||
should-deploy: ${{ steps.check-org.outputs.result }}
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Check if bot is mentioned
|
|
||||||
id: check-mention
|
|
||||||
env:
|
|
||||||
COMMENT: ${{ github.event.comment.body }}
|
|
||||||
run: |
|
|
||||||
if [[ "$COMMENT" == *"@github-actions"* ]] || \
|
|
||||||
[[ "$COMMENT" == *"github-actions[bot]"* ]]; then
|
|
||||||
bot_mentioned=true
|
|
||||||
else
|
|
||||||
bot_mentioned=false
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
if [[ "$COMMENT" == *"ota"* ]]; then
|
|
||||||
has_ota=true
|
|
||||||
else
|
|
||||||
has_ota=false
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
if [[ "$bot_mentioned" == "true" ]] && [[ "$has_ota" == "true" ]]; then
|
|
||||||
echo "mentioned=true" >> $GITHUB_OUTPUT
|
|
||||||
else
|
|
||||||
echo "mentioned=false" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Check commenter has write access
|
|
||||||
if: steps.check-mention.outputs.mentioned == 'true'
|
|
||||||
id: check-org
|
|
||||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
try {
|
|
||||||
const { data: perm } = await github.rest.repos.getCollaboratorPermissionLevel({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
username: context.payload.comment.user.login
|
|
||||||
});
|
|
||||||
|
|
||||||
const hasAccess = ['admin', 'write'].includes(perm.permission);
|
|
||||||
console.log(`User has ${perm.permission} access`);
|
|
||||||
|
|
||||||
return hasAccess;
|
|
||||||
} catch(error) {
|
|
||||||
console.log('User has no repository access');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bundle-deploy:
|
|
||||||
name: Bundle and Deploy EAS Update
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: [handle-comment]
|
|
||||||
if: needs.handle-comment.outputs.should-deploy == 'true'
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Get PR HEAD SHA
|
|
||||||
env:
|
|
||||||
ISSUE_NUMBER: ${{ github.event.issue.number }}
|
|
||||||
id: pr-info
|
|
||||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
const pr = await github.rest.pulls.get({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
pull_number: process.env.ISSUE_NUMBER,
|
|
||||||
});
|
|
||||||
|
|
||||||
// This workflow runs with repo secrets in scope, so never build
|
|
||||||
// code from a fork: the commenter authorizes the deploy, but a
|
|
||||||
// fork controls what code would run during it
|
|
||||||
const expected = `${context.repo.owner}/${context.repo.repo}`;
|
|
||||||
const head = pr.data.head.repo?.full_name;
|
|
||||||
if (head !== expected) {
|
|
||||||
core.setFailed(`OTA deploys are only allowed for branches in ${expected}, not forks (got ${head})`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`PR HEAD SHA: ${pr.data.head.sha}`);
|
|
||||||
console.log(`PR HEAD REF: ${pr.data.head.ref}`);
|
|
||||||
|
|
||||||
core.setOutput('head-sha', pr.data.head.sha);
|
|
||||||
core.setOutput('head-ref', pr.data.head.ref);
|
|
||||||
|
|
||||||
- name: 💬 Drop a comment
|
|
||||||
uses: marocchino/sticky-pull-request-comment@5770ad5eb8f42dd2c4f34da00c94c5381e49af88 # v3.0.5
|
|
||||||
with:
|
|
||||||
header: pull-request-eas-build-${{ steps.pr-info.outputs.head-sha }}
|
|
||||||
number: ${{ github.event.issue.number }}
|
|
||||||
message: |
|
|
||||||
An OTA deployment has been requested and is now running for `${{ steps.pr-info.outputs.head-sha }}`.
|
|
||||||
|
|
||||||
[Here is some music to listen to while you wait...](https://www.youtube.com/watch?v=VBlFHuCzPgY)
|
|
||||||
---
|
|
||||||
*Generated by [PR labeler](https://github.com/expo/expo/actions/workflows/pr-labeler.yml) 🤖*
|
|
||||||
|
|
||||||
- name: Check for EXPO_TOKEN
|
|
||||||
run: >
|
|
||||||
if [ -z "${{ secrets.EXPO_TOKEN }}" ]; then
|
|
||||||
echo "You must provide an EXPO_TOKEN secret linked to this project's Expo account in this repo's secrets. Learn more: https://docs.expo.dev/eas-update/github-actions"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: ⬇️ Checkout
|
|
||||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
||||||
with:
|
|
||||||
ref: ${{ steps.pr-info.outputs.head-sha }}
|
|
||||||
|
|
||||||
- uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
|
|
||||||
|
|
||||||
- name: 🔧 Setup Node
|
|
||||||
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
|
||||||
with:
|
|
||||||
node-version-file: package.json
|
|
||||||
cache: pnpm
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
|
|
||||||
- name: 🔤 Compile translations
|
|
||||||
run: pnpm intl:build 2>&1 | tee i18n.log
|
|
||||||
|
|
||||||
- name: Check for i18n compilation errors
|
|
||||||
run: if grep -q "invalid syntax" "i18n.log"; then echo "\n\nFound compilation errors!\n\n" && exit 1; else echo "\n\nNo compilation errors!\n\n"; fi
|
|
||||||
|
|
||||||
- name: Lint check
|
|
||||||
run: pnpm lint
|
|
||||||
|
|
||||||
- name: Type check
|
|
||||||
run: pnpm typecheck
|
|
||||||
|
|
||||||
- name: 🔨 Setup EAS
|
|
||||||
uses: expo/expo-github-action@eab7a230208c952974db8c3245cfd78402c7b385 # 9.0.0
|
|
||||||
with:
|
|
||||||
eas-version: '19.0.5'
|
|
||||||
packager: 'pnpm --allow-build=dtrace-provider'
|
|
||||||
token: ${{ secrets.EXPO_TOKEN }}
|
|
||||||
|
|
||||||
- name: 🪛 Setup jq
|
|
||||||
uses: dcarbone/install-jq-action@4fcb5062d7ce9bc4382d1a352d19ba3ba2c317c1 # v4.0.1
|
|
||||||
|
|
||||||
- name: Env
|
|
||||||
id: env
|
|
||||||
run: |
|
|
||||||
export json='${{ secrets.GOOGLE_SERVICES_TOKEN }}'
|
|
||||||
echo "${{ secrets.ENV_TOKEN }}" > .env
|
|
||||||
echo "EXPO_PUBLIC_ENV=testflight" >> .env
|
|
||||||
echo "EXPO_PUBLIC_RELEASE_VERSION=$(jq -r '.version' package.json)" >> .env
|
|
||||||
echo "EXPO_PUBLIC_RELEASE_VERSION=$(jq -r '.version' package.json)" >> $GITHUB_OUTPUT
|
|
||||||
echo "EXPO_PUBLIC_BUNDLE_IDENTIFIER=$(git rev-parse HEAD)" >> .env
|
|
||||||
echo "EXPO_PUBLIC_BUNDLE_IDENTIFIER=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
|
|
||||||
echo "EXPO_PUBLIC_BUNDLE_DATE=$(date -u +"%y%m%d%H")" >> .env
|
|
||||||
echo "EXPO_PUBLIC_SENTRY_DSN=${{ secrets.SENTRY_DSN }}" >> .env
|
|
||||||
echo "EXPO_PUBLIC_BITDRIFT_API_KEY=${{ secrets.BITDRIFT_API_KEY }}" >> .env
|
|
||||||
echo "EXPO_PUBLIC_GCP_PROJECT_ID=${{ secrets.EXPO_PUBLIC_GCP_PROJECT_ID }}" >> .env
|
|
||||||
echo "$json" > google-services.json
|
|
||||||
|
|
||||||
- name: 🏗️ Create Bundle
|
|
||||||
run: >
|
|
||||||
SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }}
|
|
||||||
SENTRY_RELEASE=${{ steps.env.outputs.EXPO_PUBLIC_RELEASE_VERSION }}
|
|
||||||
SENTRY_DIST=${{ steps.env.outputs.EXPO_PUBLIC_BUNDLE_IDENTIFIER }}
|
|
||||||
pnpm export
|
|
||||||
|
|
||||||
- name: 📦 Package Bundle and 🚀 Deploy
|
|
||||||
run: pnpm use-build-number bash scripts/bundleUpdate.sh
|
|
||||||
env:
|
|
||||||
DENIS_API_KEY: ${{ secrets.DENIS_API_KEY }}
|
|
||||||
CHANNEL_NAME: pull-request-${{ github.event.issue.number }}
|
|
||||||
RUNTIME_VERSION:
|
|
||||||
|
|
||||||
- name: 💬 Drop a comment
|
|
||||||
uses: marocchino/sticky-pull-request-comment@5770ad5eb8f42dd2c4f34da00c94c5381e49af88 # v3.0.5
|
|
||||||
env:
|
|
||||||
ISSUE_NUMBER: ${{ github.event.issue.number }}
|
|
||||||
with:
|
|
||||||
header: pull-request-eas-build-${{ steps.pr-info.outputs.head-sha }}
|
|
||||||
number: ${{ github.event.issue.number }}
|
|
||||||
message: |
|
|
||||||
Your requested OTA deployment was successful! You may now apply it by either scanning the QR code or opening the deep link below in your browser:
|
|
||||||
|
|
||||||
<img src="https://bsky-qr.vercel.app?channel=pull-request-$ISSUE_NUMBER" width=300 height=300>
|
|
||||||
|
|
||||||
`bluesky://intent/apply-ota?channel=pull-request-${{ github.event.issue.number }}`
|
|
||||||
---
|
|
||||||
|
|
||||||
*Generated by [PR labeler](https://github.com/expo/expo/actions/workflows/pr-labeler.yml) 🤖*
|
|
||||||
|
|
||||||
- name: 💬 Drop a comment
|
|
||||||
uses: marocchino/sticky-pull-request-comment@5770ad5eb8f42dd2c4f34da00c94c5381e49af88 # v3.0.5
|
|
||||||
if: failure()
|
|
||||||
with:
|
|
||||||
header: pull-request-eas-build-${{ steps.pr-info.outputs.head-sha }}
|
|
||||||
number: ${{ github.event.issue.number }}
|
|
||||||
message: |
|
|
||||||
Your requested OTA deployment was unsuccessful. See action logs for more details.
|
|
||||||
---
|
|
||||||
*Generated by [PR labeler](https://github.com/expo/expo/actions/workflows/pr-labeler.yml) 🤖*
|
|
||||||
@@ -18,6 +18,11 @@ concurrency:
|
|||||||
# bundle-size and fingerprint diffs
|
# bundle-size and fingerprint diffs
|
||||||
permissions: {}
|
permissions: {}
|
||||||
|
|
||||||
|
# denis release tag in bluesky-social/tango whose linux-amd64 binary the PR OTA
|
||||||
|
# job downloads. Bump this one line to roll denis.
|
||||||
|
env:
|
||||||
|
DENIS_RELEASE_TAG: denis-v0.1.1
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
# Populate this from main so every PR can restore the same trusted baseline.
|
# Populate this from main so every PR can restore the same trusted baseline.
|
||||||
webpack-analyzer-base:
|
webpack-analyzer-base:
|
||||||
@@ -220,3 +225,96 @@ jobs:
|
|||||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||||
run: |
|
run: |
|
||||||
gh pr edit "$PR_NUMBER" --remove-label "bot: fingerprint changed" || true
|
gh pr edit "$PR_NUMBER" --remove-label "bot: fingerprint changed" || true
|
||||||
|
|
||||||
|
# Automatic per-PR OTA preview, published to the pull-request-<N> channel on
|
||||||
|
# denis. Replaces the old `@github-actions ota` comment trigger. Gated to
|
||||||
|
# same-repo PRs (fork guard): a branch can only exist in this repo if someone
|
||||||
|
# with write access pushed it, so an outside contributor (who can only open a
|
||||||
|
# PR from a fork) never runs this job with the denis publish role in scope.
|
||||||
|
# This matches the fork-guard gate the other jobs in this workflow use;
|
||||||
|
# author_association is deliberately NOT checked (it can't identify a private
|
||||||
|
# org member and would skip their PRs).
|
||||||
|
publish-pr-ota:
|
||||||
|
name: Publish PR OTA to denis
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: >-
|
||||||
|
github.event_name == 'pull_request' &&
|
||||||
|
github.event.pull_request.head.repo.full_name == github.repository
|
||||||
|
concurrency:
|
||||||
|
group: pr-ota-${{ github.event.pull_request.number }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
permissions:
|
||||||
|
id-token: write
|
||||||
|
contents: read
|
||||||
|
steps:
|
||||||
|
- name: ⬇️ Checkout
|
||||||
|
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||||
|
with:
|
||||||
|
ref: ${{ github.event.pull_request.head.sha }}
|
||||||
|
|
||||||
|
- name: 🛠️ Setup Expo project
|
||||||
|
uses: ./.github/actions/setup-expo-project
|
||||||
|
with:
|
||||||
|
expo-token: ${{ secrets.EXPO_TOKEN }}
|
||||||
|
|
||||||
|
- name: 🔤 Compile translations
|
||||||
|
uses: ./.github/actions/compile-i18n
|
||||||
|
|
||||||
|
- name: ✏️ Write environment variables
|
||||||
|
id: env
|
||||||
|
uses: ./.github/actions/write-env
|
||||||
|
with:
|
||||||
|
env-token: ${{ secrets.ENV_TOKEN }}
|
||||||
|
sentry-dsn: ${{ secrets.SENTRY_DSN }}
|
||||||
|
bitdrift-api-key: ${{ secrets.BITDRIFT_API_KEY }}
|
||||||
|
gcp-project-id: ${{ secrets.EXPO_PUBLIC_GCP_PROJECT_ID }}
|
||||||
|
google-services-token: ${{ secrets.GOOGLE_SERVICES_TOKEN }}
|
||||||
|
expo-public-env: testflight
|
||||||
|
|
||||||
|
- name: 🏗️ Create Bundle
|
||||||
|
run: >
|
||||||
|
SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||||
|
SENTRY_RELEASE=${{ steps.env.outputs.release-version }}
|
||||||
|
SENTRY_DIST=${{ steps.env.outputs.bundle-identifier }}
|
||||||
|
pnpm export
|
||||||
|
|
||||||
|
- name: ☁️ Configure AWS credentials (denis, PR-scoped)
|
||||||
|
uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1
|
||||||
|
with:
|
||||||
|
role-to-assume: arn:aws:iam::007404326489:role/denis-ci-publish-pr
|
||||||
|
aws-region: us-east-2
|
||||||
|
# Defense-in-depth: the base role is already scoped to pr/*, but narrow
|
||||||
|
# this session further to just THIS PR's prefix so a bug can't write to
|
||||||
|
# another PR's objects or the prod tree.
|
||||||
|
inline-session-policy: |-
|
||||||
|
{
|
||||||
|
"Version": "2012-10-17",
|
||||||
|
"Statement": [
|
||||||
|
{
|
||||||
|
"Effect": "Allow",
|
||||||
|
"Action": ["s3:PutObject", "s3:DeleteObject"],
|
||||||
|
"Resource": "arn:aws:s3:::bsky-denis-ota-prod/pr/${{ github.event.pull_request.number }}/*"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Effect": "Allow",
|
||||||
|
"Action": "s3:ListBucket",
|
||||||
|
"Resource": "arn:aws:s3:::bsky-denis-ota-prod",
|
||||||
|
"Condition": {
|
||||||
|
"StringLike": { "s3:prefix": "pr/${{ github.event.pull_request.number }}/*" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
- name: ⬇️ Setup denis CLI
|
||||||
|
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)
|
||||||
|
run: pnpm use-build-number bash scripts/denisPublish.sh
|
||||||
|
env:
|
||||||
|
RUNTIME_VERSION: ''
|
||||||
|
CHANNEL_NAME: pull-request-${{ github.event.pull_request.number }}
|
||||||
|
|||||||
Executable
+45
@@ -0,0 +1,45 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -o errexit
|
||||||
|
set -o pipefail
|
||||||
|
set -o nounset
|
||||||
|
|
||||||
|
# Publishes the just-exported Expo bundle to the denis OTA service (S3) via the
|
||||||
|
# `denis publish` CLI. Mirrors bundleUpdate.sh's inputs (runtime version, bundle
|
||||||
|
# version, build numbers) but targets denis instead of the legacy ota1 upload.
|
||||||
|
# Expects: the `denis` binary on PATH (setup-denis action), ambient AWS creds
|
||||||
|
# (configure-aws-credentials OIDC), and BSKY_IOS_BUILD_NUMBER /
|
||||||
|
# BSKY_ANDROID_VERSION_CODE from the use-build-number wrapper.
|
||||||
|
|
||||||
|
rm -rf bundleTempDir
|
||||||
|
|
||||||
|
echo "Assembling bundle directory..."
|
||||||
|
node scripts/bundleUpdate.js
|
||||||
|
|
||||||
|
if [ -z "$RUNTIME_VERSION" ]; then
|
||||||
|
RUNTIME_VERSION=$(cat package.json | jq '.version' -r)
|
||||||
|
fi
|
||||||
|
|
||||||
|
BUNDLE_VERSION=$(date +%s)
|
||||||
|
DENIS_CDN_DOMAIN="${DENIS_CDN_DOMAIN:-updates.bsky.app}"
|
||||||
|
DENIS_S3_BUCKET="${DENIS_S3_BUCKET:-bsky-denis-ota-prod}"
|
||||||
|
|
||||||
|
echo "Publishing to denis..."
|
||||||
|
echo " runtime-version: $RUNTIME_VERSION"
|
||||||
|
echo " bundle-version: $BUNDLE_VERSION"
|
||||||
|
echo " channel: $CHANNEL_NAME"
|
||||||
|
echo " ios-build-number: $BSKY_IOS_BUILD_NUMBER"
|
||||||
|
echo " android-build-number: $BSKY_ANDROID_VERSION_CODE"
|
||||||
|
echo " cdn-domain: $DENIS_CDN_DOMAIN"
|
||||||
|
echo " s3-bucket: $DENIS_S3_BUCKET"
|
||||||
|
|
||||||
|
denis publish \
|
||||||
|
--bundle-dir bundleTempDir \
|
||||||
|
--runtime-version "$RUNTIME_VERSION" \
|
||||||
|
--bundle-version "$BUNDLE_VERSION" \
|
||||||
|
--channel "$CHANNEL_NAME" \
|
||||||
|
--ios-build-number "$BSKY_IOS_BUILD_NUMBER" \
|
||||||
|
--android-build-number "$BSKY_ANDROID_VERSION_CODE" \
|
||||||
|
--cdn-domain "$DENIS_CDN_DOMAIN" \
|
||||||
|
--s3-bucket "$DENIS_S3_BUCKET"
|
||||||
|
|
||||||
|
rm -rf bundleTempDir
|
||||||
Reference in New Issue
Block a user