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