--- name: Release on: # Publishing a release guarantees the release exists before production submissions begin. # The release job below only accepts numeric semver tags matching package.json. release: types: [published] # Key each parent run by tag so a newly published release cannot evict a different pending run. # The reusable platform workflows retain their own concurrency groups to serialize app builds. concurrency: group: release-${{ github.event.release.tag_name }} cancel-in-progress: false # Permissions are granted per job. The mobile build jobs only receive the secrets declared by # their reusable workflows rather than the repository's entire secret store. permissions: contents: read jobs: release: name: Validate release tag if: github.repository == 'bluesky-social/social-app' runs-on: ubuntu-latest outputs: version: ${{ steps.version.outputs.version }} steps: - name: ⬇️ Checkout release commit uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: 🔎 Validate release tag and version id: version env: RELEASE_TAG: ${{ github.ref_name }} run: | version=$(jq -r '.version' package.json) if ! [[ "$RELEASE_TAG" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then echo "::error::Release tag must be a semver version such as 1.130.0; found '$RELEASE_TAG'." exit 1 fi if [ "$RELEASE_TAG" != "$version" ]; then echo "::error file=package.json::Release tag is $RELEASE_TAG, but package.json is version $version." exit 1 fi echo "Releasing $version from $GITHUB_SHA" echo "version=$version" >> "$GITHUB_OUTPUT" ios: name: Production iOS Build needs: [release] uses: ./.github/workflows/build-submit-ios.yml with: profile: production testFlightGroup: "QA Team" secrets: EXPO_TOKEN: ${{ secrets.EXPO_TOKEN }} ENV_TOKEN: ${{ secrets.ENV_TOKEN }} SENTRY_DSN: ${{ secrets.SENTRY_DSN }} BITDRIFT_API_KEY: ${{ secrets.BITDRIFT_API_KEY }} EXPO_PUBLIC_GCP_PROJECT_ID: ${{ secrets.EXPO_PUBLIC_GCP_PROJECT_ID }} GOOGLE_SERVICES_TOKEN: ${{ secrets.GOOGLE_SERVICES_TOKEN }} SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }} ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }} ASC_KEY_P8_BASE64: ${{ secrets.ASC_KEY_P8_BASE64 }} SLACK_CLIENT_ALERT_WEBHOOK: ${{ secrets.SLACK_CLIENT_ALERT_WEBHOOK }} android: name: Production Android Build needs: [release] # The reusable workflow's APK attachment job needs this permission. The build and submit # jobs remain read-only through their own job/workflow permission declarations. permissions: contents: write uses: ./.github/workflows/build-submit-android.yml with: profile: production secrets: EXPO_TOKEN: ${{ secrets.EXPO_TOKEN }} ENV_TOKEN: ${{ secrets.ENV_TOKEN }} SENTRY_DSN: ${{ secrets.SENTRY_DSN }} BITDRIFT_API_KEY: ${{ secrets.BITDRIFT_API_KEY }} EXPO_PUBLIC_GCP_PROJECT_ID: ${{ secrets.EXPO_PUBLIC_GCP_PROJECT_ID }} GOOGLE_SERVICES_TOKEN: ${{ secrets.GOOGLE_SERVICES_TOKEN }} SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} SLACK_CLIENT_ALERT_WEBHOOK: ${{ secrets.SLACK_CLIENT_ALERT_WEBHOOK }} ANDROID_KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }} ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }} ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }} ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }} bump-version: name: Open next version PR needs: [release, ios, android] runs-on: ubuntu-latest permissions: contents: write pull-requests: write steps: # The builds can take long enough for main to advance. Base the bump on the latest main, # but verify its version is still the one that this workflow just released. - name: ⬇️ Checkout latest main uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: ref: main persist-credentials: false - name: 🧮 Compute next version id: version env: RELEASED: ${{ needs.release.outputs.version }} run: | current=$(jq -r '.version' package.json) if [ "$current" != "$RELEASED" ]; then echo "::error file=package.json::main is now version $current, but this workflow released $RELEASED. Refusing to overwrite a newer version." exit 1 fi next=$(echo "$RELEASED" | jq -R -r 'split(".") | "\(.[0]).\(.[1] | tonumber + 1).0"') echo "Bumping $RELEASED to $next" echo "next=$next" >> "$GITHUB_OUTPUT" echo "branch=bot/version-bump-$next" >> "$GITHUB_OUTPUT" - name: 🔁 Check for an existing version-bump PR id: dedup env: GH_TOKEN: ${{ github.token }} BRANCH: ${{ steps.version.outputs.branch }} run: | existing=$(gh pr list --state open --head "$BRANCH" --json url --jq '.[0].url // ""') if [ -n "$existing" ]; then echo "Version-bump PR already exists: $existing" echo "skip=true" >> "$GITHUB_OUTPUT" else echo "skip=false" >> "$GITHUB_OUTPUT" fi - name: ✏️ Bump version if: steps.dedup.outputs.skip == 'false' env: NEXT: ${{ steps.version.outputs.next }} run: | jq --indent 2 --arg version "$NEXT" '.version = $version' package.json > package.json.tmp mv package.json.tmp package.json changed=$(git diff --numstat package.json | awk '{print $1"+"$2}') if [ "$changed" != "1+1" ]; then echo "::error file=package.json::Expected the version bump to change exactly one line." git diff -- package.json exit 1 fi - name: 📤 Create branch and pull request if: steps.dedup.outputs.skip == 'false' env: GH_TOKEN: ${{ github.token }} BRANCH: ${{ steps.version.outputs.branch }} NEXT: ${{ steps.version.outputs.next }} RELEASED: ${{ needs.release.outputs.version }} run: | git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" git remote set-url origin "https://x-access-token:${GH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" # A previous attempt may have pushed this deterministic bot branch and then failed # before creating its PR. Fetch it so force-with-lease can replace only that known tip. git fetch origin "$BRANCH:refs/remotes/origin/$BRANCH" || true git checkout -B "$BRANCH" git add package.json git commit -m "bump version to $NEXT" git push --force-with-lease --set-upstream origin "$BRANCH" # This requires "Allow GitHub Actions to create and approve pull requests" in the # repository's Actions settings; no long-lived personal access token is needed. gh pr create \ --base main \ --head "$BRANCH" \ --title "Bump version to $NEXT" \ --body "Released $RELEASED. Bumps the app version to $NEXT for the next release cycle."