···20202121jobs:
2222 bundleDeploy:
2323+ if: github.repository == 'bluesky-social/social-app'
2324 name: Bundle and Deploy EAS Update
2425 runs-on: ubuntu-latest
2526 concurrency:
···150151 needs: [bundleDeploy]
151152 # Gotta check if its NOT '[]' because any md5 hash in the outputs is detected as a possible secret and won't be
152153 # available here
153153- if: ${{ inputs.channel != 'production' && needs.bundleDeploy.outputs.changes-detected }}
154154+ if: ${{ inputs.channel != 'production' && needs.bundleDeploy.outputs.changes-detected && github.repository == 'bluesky-social/social-app' }}
154155 steps:
155156 - name: Check for EXPO_TOKEN
156157 run: >
···239240 needs: [bundleDeploy]
240241 # Gotta check if its NOT '[]' because any md5 hash in the outputs is detected as a possible secret and won't be
241242 # available here
242242- if: ${{ inputs.channel != 'production' && needs.bundleDeploy.outputs.changes-detected }}
243243+ if: ${{ inputs.channel != 'production' && needs.bundleDeploy.outputs.changes-detected && github.repository == 'bluesky-social/social-app'}}
243244244245 steps:
245246 - name: Check for EXPO_TOKEN
+202
.github/workflows/pull-request-comment.yml
···11+---
22+name: PR Comment Trigger
33+44+on:
55+ issue_comment:
66+ types: [created]
77+88+# Permissiosn to make comments in the pull request
99+permissions:
1010+ pull-requests: write
1111+ actions: write
1212+ contents: read
1313+1414+jobs:
1515+ handle-comment:
1616+ if: github.event.issue.pull_request
1717+ runs-on: ubuntu-latest
1818+ outputs:
1919+ should-deploy: ${{ steps.check-org.outputs.result }}
2020+2121+ steps:
2222+ - name: Check if bot is mentioned
2323+ id: check-mention
2424+ env:
2525+ COMMENT: ${{ github.event.comment.body }}
2626+ run: |
2727+ if [[ "$COMMENT" == *"@github-actions"* ]] || \
2828+ [[ "$COMMENT" == *"github-actions[bot]"* ]]; then
2929+ bot_mentioned=true
3030+ else
3131+ bot_mentioned=false
3232+ fi
3333+3434+3535+ if [[ "${{ github.event.comment.body }}" == *"ota"* ]]; then
3636+ has_ota=true
3737+ else
3838+ has_ota=false
3939+ fi
4040+4141+4242+ if [[ "$bot_mentioned" == "true" ]] && [[ "$has_ota" == "true" ]]; then
4343+ echo "mentioned=true" >> $GITHUB_OUTPUT
4444+ else
4545+ echo "mentioned=false" >> $GITHUB_OUTPUT
4646+ fi
4747+4848+ - name: Check organization membership
4949+ if: steps.check-mention.outputs.mentioned == 'true'
5050+ id: check-org
5151+ uses: actions/github-script@v7
5252+ with:
5353+ script: |
5454+ try {
5555+ const { data: perm } = await github.rest.repos.getCollaboratorPermissionLevel({
5656+ owner: context.repo.owner,
5757+ repo: context.repo.repo,
5858+ username: context.payload.comment.user.login
5959+ });
6060+6161+ const hasAccess = ['admin', 'write'].includes(perm.permission);
6262+ console.log(`User has ${perm.permission} access`);
6363+6464+ return hasAccess;
6565+ } catch(error) {
6666+ console.log('User has no repository access');
6767+ return false;
6868+ }
6969+7070+ bundle-deploy:
7171+ name: Bundle and Deploy EAS Update
7272+ runs-on: ubuntu-latest
7373+ needs: [handle-comment]
7474+ if: needs.handle-comment.outputs.should-deploy == 'true'
7575+7676+ steps:
7777+ - name: Get PR HEAD SHA
7878+ id: pr-info
7979+ uses: actions/github-script@v7
8080+ with:
8181+ script: |
8282+ const pr = await github.rest.pulls.get({
8383+ owner: context.repo.owner,
8484+ repo: context.repo.repo,
8585+ pull_number: ${{ github.event.issue.number }}
8686+ });
8787+8888+ console.log(`PR HEAD SHA: ${pr.data.head.sha}`);
8989+ console.log(`PR HEAD REF: ${pr.data.head.ref}`);
9090+9191+ core.setOutput('head-sha', pr.data.head.sha);
9292+ core.setOutput('head-ref', pr.data.head.ref);
9393+9494+ - name: 💬 Drop a comment
9595+ uses: marocchino/sticky-pull-request-comment@v2
9696+ with:
9797+ header: pull-request-eas-build-${{ steps.pr-info.outputs.head-sha }}
9898+ number: ${{ github.event.issue.number }}
9999+ message: |
100100+ An OTA deployment has been requested and is now running for `${{ steps.pr-info.outputs.head-sha }}`.
101101+102102+ [Here is some music to listen to while you wait...](https://www.youtube.com/watch?v=VBlFHuCzPgY)
103103+ ---
104104+ *Generated by [PR labeler](https://github.com/expo/expo/actions/workflows/pr-labeler.yml) 🤖*
105105+106106+ - name: Check for EXPO_TOKEN
107107+ run: >
108108+ if [ -z "${{ secrets.EXPO_TOKEN }}" ]; then
109109+ 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"
110110+ exit 1
111111+ fi
112112+113113+ - name: ⬇️ Checkout
114114+ uses: actions/checkout@v4
115115+ with:
116116+ ref: ${{ steps.pr-info.outputs.head-sha }}
117117+118118+ - name: 🔧 Setup Node
119119+ uses: actions/setup-node@v4
120120+ with:
121121+ node-version-file: .nvmrc
122122+ cache: yarn
123123+124124+ - name: Install dependencies
125125+ run: yarn install --frozen-lockfile
126126+127127+ - name: Lint check
128128+ run: yarn lint
129129+130130+ - name: Lint lockfile
131131+ run: yarn lockfile-lint
132132+133133+ - name: 🔤 Compile translations
134134+ run: yarn intl:build 2>&1 | tee i18n.log
135135+136136+ - name: Check for i18n compilation errors
137137+ 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
138138+139139+ - name: Type check
140140+ run: yarn typecheck
141141+142142+ - name: 🔨 Setup EAS
143143+ uses: expo/expo-github-action@v8
144144+ with:
145145+ expo-version: latest
146146+ eas-version: latest
147147+ token: ${{ secrets.EXPO_TOKEN }}
148148+149149+ - name: ⛏️ Setup Expo
150150+ run: yarn global add eas-cli-local-build-plugin
151151+152152+ - name: 🪛 Setup jq
153153+ uses: dcarbone/install-jq-action@v2
154154+155155+ - name: ✏️ Write environment variables
156156+ run: |
157157+ export json='${{ secrets.GOOGLE_SERVICES_TOKEN }}'
158158+ echo "${{ secrets.ENV_TOKEN }}" > .env
159159+ echo "EXPO_PUBLIC_BUNDLE_IDENTIFIER=$(git rev-parse --short HEAD)" >> .env
160160+ echo "EXPO_PUBLIC_BUNDLE_DATE=$(date -u +"%y%m%d%H")" >> .env
161161+ echo "BITDRIFT_API_KEY=${{ secrets.BITDRIFT_API_KEY }}" >> .env
162162+ echo "$json" > google-services.json
163163+164164+ - name: Setup Sentry vars for build-time injection
165165+ id: sentry
166166+ run: |
167167+ echo "SENTRY_DIST=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
168168+ echo "SENTRY_RELEASE=$(jq -r '.version' package.json)" >> $GITHUB_OUTPUT
169169+170170+ - name: 🏗️ Create Bundle
171171+ run: SENTRY_DIST=${{ steps.sentry.outputs.SENTRY_DIST }} SENTRY_RELEASE=${{ steps.sentry.outputs.SENTRY_RELEASE }} SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }} SENTRY_DSN=${{ secrets.SENTRY_DSN }} EXPO_PUBLIC_ENV="testflight" yarn export
172172+173173+ - name: 📦 Package Bundle and 🚀 Deploy
174174+ run: yarn use-build-number bash scripts/bundleUpdate.sh
175175+ env:
176176+ DENIS_API_KEY: ${{ secrets.DENIS_API_KEY }}
177177+ CHANNEL_NAME: pull-request-${{ github.event.issue.number }}
178178+ RUNTIME_VERSION:
179179+180180+ - name: 💬 Drop a comment
181181+ uses: marocchino/sticky-pull-request-comment@v2
182182+ with:
183183+ header: pull-request-eas-build-${{ steps.pr-info.outputs.head-sha }}
184184+ number: ${{ github.event.issue.number }}
185185+ message: |
186186+ Your requested OTA deployment was successful! You may now apply it by opening the deep link below in your browser:
187187+188188+ `bluesky://intent/apply-ota?channel=pull-request-${{ github.event.issue.number }}`
189189+ ---
190190+ *Generated by [PR labeler](https://github.com/expo/expo/actions/workflows/pr-labeler.yml) 🤖*
191191+192192+193193+ - name: 💬 Drop a comment
194194+ uses: marocchino/sticky-pull-request-comment@v2
195195+ if: failure()
196196+ with:
197197+ header: pull-request-eas-build-${{ steps.pr-info.outputs.head-sha }}
198198+ number: ${{ github.event.issue.number }}
199199+ message: |
200200+ Your requested OTA deployment was unsuccessful. See action logs for more details.
201201+ ---
202202+ *Generated by [PR labeler](https://github.com/expo/expo/actions/workflows/pr-labeler.yml) 🤖*
···77 text: string,
88 cursorPos: number,
99): FoundMention | undefined {
1010- let re = /(^|\s)@([a-z0-9.]*)/gi
1010+ let re = /(^|\s)@([a-z0-9.-]*)/gi
1111 let match
1212 while ((match = re.exec(text))) {
1313 const spaceOffset = match[1].length