forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 💫
1---
2name: Build and Submit iOS
3
4on:
5 workflow_dispatch:
6 inputs:
7 profile:
8 type: choice
9 description: Build profile to use
10 options:
11 - testflight
12 - production
13
14jobs:
15 build:
16 if: github.repository == 'bluesky-social/social-app'
17 name: Build and Submit iOS
18 runs-on: macos-26-xlarge
19 concurrency:
20 group: ios-build
21 cancel-in-progress: false
22 steps:
23 - name: Check for EXPO_TOKEN
24 run: >
25 if [ -z "${{ secrets.EXPO_TOKEN }}" ]; then
26 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"
27 exit 1
28 fi
29
30 - name: ⬇️ Checkout
31 uses: actions/checkout@v4
32 with:
33 fetch-depth: 5
34
35 - name: 🔧 Setup Node
36 uses: actions/setup-node@v6
37 with:
38 node-version-file: .nvmrc
39 cache: yarn
40
41 - name: 🪛 Setup jq
42 uses: dcarbone/install-jq-action@v2
43
44 - name: 🔨 Setup EAS
45 uses: expo/expo-github-action@main
46 with:
47 expo-version: latest
48 eas-version: latest
49 token: ${{ secrets.EXPO_TOKEN }}
50
51 - name: ⛏️ Setup EAS local builds
52 run: yarn global add eas-cli-local-build-plugin
53
54 - name: ⚙️ Install dependencies
55 run: yarn install --frozen-lockfile
56
57 - uses: maxim-lobanov/setup-xcode@v1
58 with:
59 xcode-version: "26.0"
60
61 - name: ☕️ Setup Cocoapods
62 uses: maxim-lobanov/setup-cocoapods@v1
63 with:
64 version: 1.16.2
65
66 - name: 💾 Cache Pods
67 uses: actions/cache@v4
68 id: pods-cache
69 with:
70 path: ./ios/Pods
71 # We'll use the yarn.lock for our hash since we don't yet have a Podfile.lock. Pod versions will not
72 # change unless the yarn version changes as well.
73 key: ${{ runner.os }}-pods-${{ hashFiles('yarn.lock') }}
74
75 - name: 🔤 Compile translations
76 run: yarn intl:build 2>&1 | tee i18n.log
77
78 - name: Check for i18n compilation errors
79 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
80
81 # EXPO_PUBLIC_ENV is handled in eas.json
82 - name: ✏️ Write environment variables
83 id: env
84 run: |
85 echo "${{ secrets.ENV_TOKEN }}" > .env
86 echo "EXPO_PUBLIC_RELEASE_VERSION=$(jq -r '.version' package.json)" >> .env
87 echo "EXPO_PUBLIC_RELEASE_VERSION=$(jq -r '.version' package.json)" >> $GITHUB_OUTPUT
88 echo "EXPO_PUBLIC_BUNDLE_IDENTIFIER=$(git rev-parse HEAD)" >> .env
89 echo "EXPO_PUBLIC_BUNDLE_IDENTIFIER=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
90 echo "EXPO_PUBLIC_BUNDLE_DATE=$(date -u +"%y%m%d%H")" >> .env
91 echo "EXPO_PUBLIC_SENTRY_DSN=${{ secrets.SENTRY_DSN }}" >> .env
92 echo "EXPO_PUBLIC_BITDRIFT_API_KEY=${{ secrets.BITDRIFT_API_KEY }}" >> .env
93 echo "EXPO_PUBLIC_GCP_PROJECT_ID=${{ secrets.EXPO_PUBLIC_GCP_PROJECT_ID }}" >> .env
94 echo "${{ secrets.GOOGLE_SERVICES_TOKEN }}" > google-services.json
95
96 - name: 🏗️ EAS Build
97 env:
98 PROFILE: ${{ inputs.profile || 'testflight' }}
99 run: >
100 SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }}
101 SENTRY_RELEASE=${{ steps.env.outputs.EXPO_PUBLIC_RELEASE_VERSION }}
102 SENTRY_DIST=${{ steps.env.outputs.EXPO_PUBLIC_BUNDLE_IDENTIFIER }}
103 yarn use-build-number-with-bump
104 eas build -p ios
105 --profile $PROFILE
106 --local --output build.tar.gz --non-interactive
107
108 - name: 📂 Extract build artifact
109 run: |
110 if [ -f "build.tar.gz" ]; then
111 echo "Extracting build.tar.gz..."
112 mkdir ios-build
113 tar -xzf build.tar.gz -C ios-build
114 echo "Extraction completed successfully"
115 else
116 echo "Archive file not found!"
117 exit 1
118 fi
119
120 - name: 🚀 Deploy
121 run: eas submit -p ios --non-interactive --path ios-build/ios/build/Bluesky.ipa
122
123 - name: 🪲 Upload dSYM to Sentry
124 run: >
125 SENTRY_ORG=blueskyweb
126 SENTRY_PROJECT=app
127 SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }}
128 yarn sentry-cli debug-files upload ios-build/ios/build/Bluesky.app.dSYM.zip --include-sources
129
130 - name: 📚 Get version from package.json
131 id: get-build-info
132 run: bash scripts/setGitHubOutput.sh
133
134 - name: 🔔 Notify Slack of Production Build
135 if: ${{ inputs.profile == 'production' }}
136 uses: slackapi/slack-github-action@v1.25.0
137 with:
138 payload: |
139 {
140 "text": "iOS production build for App Store submission is ready!\n```Artifact: Check TestFlight to know when it is available\nVersion Number: ${{ steps.get-build-info.outputs.PACKAGE_VERSION }}\nBuild Number: ${{ steps.get-build-info.outputs.BSKY_IOS_BUILD_NUMBER }}```"
141 }
142 env:
143 SLACK_WEBHOOK_URL: ${{ secrets.SLACK_CLIENT_ALERT_WEBHOOK }}
144 SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK
145
146 - name: ⬇️ Restore Cache
147 id: get-base-commit
148 uses: actions/cache@v4
149 if: ${{ inputs.profile == 'testflight' }}
150 with:
151 path: most-recent-testflight-commit.txt
152 key: most-recent-testflight-commit
153
154 - name: ✏️ Write commit hash to cache
155 env:
156 GITHUB_SHA: ${{ github.sha }}
157 if: ${{ inputs.profile == 'testflight' }}
158 run: echo $GITHUB_SHA > most-recent-testflight-commit.txt