Replace nightly build with a nightly changelog post

Native nightly builds are redundant now that changes ship over the air,
so the nightly workflow no longer builds anything. It now only posts the
list of commits since the previous post to the QA team's Slack channel,
and posts nothing when there are no new commits. The commit marker
artifact keeps its name so the first run continues from the last nightly.

The OTA workflow's fallback native iOS build is assigned to the "QA Team"
TestFlight group so testers still get native builds when one is needed.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0157o74F6wX3aTghhc7DLbzd
This commit is contained in:
Claude
2026-09-06 19:12:55 +00:00
parent 4af3f47d56
commit 08d7946c49
3 changed files with 112 additions and 138 deletions
-5
View File
@@ -33,11 +33,6 @@ on:
type: string
description: TestFlight group to assign the build to after submitting ("none" to skip)
default: none
changelog:
type: string
description: TestFlight "What to Test" notes (only applied when a group is selected)
required: false
default: ''
runner:
type: string
description: Runner for the build job (defaults to macos-26-xlarge)
@@ -54,8 +54,6 @@ jobs:
# A version bump forces a native build even if the fingerprint is unchanged
changes-detected: ${{ steps.fingerprint.outputs.includes-changes ||
steps.version.outputs.version-changed }}
# Changelog since the last native testflight build, for TestFlight notes and Slack
notes: ${{ steps.notes.outputs.notes }}
steps:
- name: 🔑 Check for EXPO_TOKEN
@@ -179,57 +177,6 @@ jobs:
retention-days: 1
if-no-files-found: error
# Native builds go out to the QA Team TestFlight group, so generate a changelog of
# what changed since the last native testflight build. That build's commit SHA is
# stored as a "testflight-native-build-commit" artifact, advanced by recordBaseline
# only after both native builds succeed, so a failed run's commits roll into the
# next successful build's notes rather than being silently dropped.
- name: 📝 Generate release notes
id: notes
if: ${{ steps.fingerprint.outputs.includes-changes ||
steps.version.outputs.version-changed }}
env:
GH_TOKEN: ${{ github.token }}
REPOSITORY_ID: ${{ github.repository_id }}
run: |
prev=""
url=$(gh api \
"repos/${GITHUB_REPOSITORY}/actions/artifacts?name=testflight-native-build-commit&per_page=100" \
--jq "[.artifacts[] | select(
.expired == false and
.workflow_run.head_branch == \"main\" and
.workflow_run.head_repository_id == (\$ENV.REPOSITORY_ID | tonumber)
)] | max_by(.created_at) | .archive_download_url" \
2>/dev/null || true)
if [ -n "$url" ] && [ "$url" != "null" ]; then
if curl -sSL -H "Authorization: Bearer $GH_TOKEN" -o marker.zip "$url" \
&& unzip -o -q marker.zip; then
prev=$(tr -d '[:space:]' < testflight-native-build-commit.txt 2>/dev/null || true)
fi
rm -f marker.zip testflight-native-build-commit.txt
fi
if [ -n "$prev" ] && git cat-file -e "${prev}^{commit}" 2>/dev/null; then
echo "Generating notes since previous native build: $prev"
range="${prev}..HEAD"
else
echo "No reachable previous native build commit; falling back to last 30 commits."
range="HEAD~30..HEAD"
fi
notes=$(git log --no-merges --pretty=format:'- %s' "$range" 2>/dev/null | head -n 50)
if [ -z "$notes" ]; then
notes="No new commits since the last native build."
fi
# Cap the whole changelog: TestFlight "What to Test" allows 4000 characters and
# this also keeps the Slack message a reasonable size. head -c caps the combined
# stream; cut -c would only cap each line independently.
notes=$(printf '%s' "$notes" | head -c 3900)
{
echo "notes<<NOTES_EOF"
echo "$notes"
echo "NOTES_EOF"
} >> "$GITHUB_OUTPUT"
- name: 🔤 Compile translations
uses: ./.github/actions/compile-i18n
@@ -319,7 +266,6 @@ jobs:
with:
profile: testflight
testFlightGroup: "QA Team"
changelog: ${{ needs.bundleDeploy.outputs.notes }}
# OTA rebuilds don't need the xlarge builder used for releases
runner: macos-26
# Pass only the secrets the reusable workflow declares, rather than `secrets: inherit`,
@@ -370,68 +316,6 @@ jobs:
ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }}
ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }}
# Native builds go out to the QA team. NIGHTLY_BUILDS_SLACK_WEBHOOK posts to their
# channel (the name predates the removal of the nightly build workflow).
notifyIOS:
name: Notify Slack of iOS build
needs: [bundleDeploy, buildIfNecessaryIOS]
runs-on: ubuntu-latest
steps:
- name: 📝 Build Slack payload
id: payload
env:
NOTES: ${{ needs.bundleDeploy.outputs.notes }}
VERSION: ${{ needs.buildIfNecessaryIOS.outputs.package-version }}
BUILD_NUMBER: ${{ needs.buildIfNecessaryIOS.outputs.build-number }}
run: |
text="*New iOS build available in TestFlight (QA Team)*
Version ${VERSION} (${BUILD_NUMBER})
${NOTES}"
payload=$(jq -n --arg text "$text" '{text: $text}')
{
echo "payload<<PAYLOAD_EOF"
echo "$payload"
echo "PAYLOAD_EOF"
} >> "$GITHUB_OUTPUT"
- name: 🔔 Notify Slack
uses: slackapi/slack-github-action@dcb1066f776dd043e64d0e8ba94ca15cc7e1875d # v4.0.0
with:
webhook: ${{ secrets.NIGHTLY_BUILDS_SLACK_WEBHOOK }}
webhook-type: incoming-webhook
payload: ${{ steps.payload.outputs.payload }}
notifyAndroid:
name: Notify Slack of Android build
needs: [bundleDeploy, buildIfNecessaryAndroid]
runs-on: ubuntu-latest
steps:
- name: 📝 Build Slack payload
id: payload
env:
NOTES: ${{ needs.bundleDeploy.outputs.notes }}
VERSION: ${{ needs.buildIfNecessaryAndroid.outputs.package-version }}
VERSION_CODE: ${{ needs.buildIfNecessaryAndroid.outputs.version-code }}
run: |
text="*New Android build available (Internal track)*
Version ${VERSION} (${VERSION_CODE})
${NOTES}"
payload=$(jq -n --arg text "$text" '{text: $text}')
{
echo "payload<<PAYLOAD_EOF"
echo "$payload"
echo "PAYLOAD_EOF"
} >> "$GITHUB_OUTPUT"
- name: 🔔 Notify Slack
uses: slackapi/slack-github-action@dcb1066f776dd043e64d0e8ba94ca15cc7e1875d # v4.0.0
with:
webhook: ${{ secrets.NIGHTLY_BUILDS_SLACK_WEBHOOK }}
webhook-type: incoming-webhook
payload: ${{ steps.payload.outputs.payload }}
# Advance the fingerprint baseline only after BOTH native builds have shipped
# the new native surface. This replaces the old actions/cache baseline, which
# only advanced on cache eviction and so silently froze - freezing meant every
@@ -476,20 +360,3 @@ jobs:
path: native-fingerprint.json
retention-days: 90
if-no-files-found: error
# The changelog marker only moves when native builds actually shipped; an OTA-only
# deploy must not advance it, or the next build's notes would miss those commits.
- name: ✏️ Write native build commit marker
if: ${{ needs.bundleDeploy.outputs.changes-detected == 'true' }}
env:
GITHUB_SHA: ${{ github.sha }}
run: echo "$GITHUB_SHA" > testflight-native-build-commit.txt
- name: 🚀 Record native build commit marker
if: ${{ needs.bundleDeploy.outputs.changes-detected == 'true' }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: testflight-native-build-commit
path: testflight-native-build-commit.txt
retention-days: 90
if-no-files-found: error
+112
View File
@@ -0,0 +1,112 @@
---
name: Nightly Changelog
on:
schedule:
- cron: "10 2 * * *" # run at 2:10 AM UTC, after the nightly i18n job
workflow_dispatch:
# Only reads the repo and its artifacts; posting to Slack uses the webhook secret
permissions:
contents: read
jobs:
changelog:
name: Post changelog to QA team
if: github.repository == 'bluesky-social/social-app'
runs-on: ubuntu-latest
permissions:
contents: read
actions: read
steps:
- name: ⬇️ Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
# The range covers commits since the previous post, whose commit SHA is stored as a
# "nightly-build-commit" artifact. The name is kept from the retired nightly build
# workflow so the first run of this one continues from where that left off. The
# marker is advanced at the end of the job, so a failed post's commits roll into the
# next successful one rather than being silently dropped.
- name: 📝 Generate changelog
id: notes
env:
GH_TOKEN: ${{ github.token }}
REPOSITORY_ID: ${{ github.repository_id }}
run: |
prev=""
url=$(gh api \
"repos/${GITHUB_REPOSITORY}/actions/artifacts?name=nightly-build-commit&per_page=100" \
--jq "[.artifacts[] | select(
.expired == false and
.workflow_run.head_repository_id == (\$ENV.REPOSITORY_ID | tonumber)
)] | max_by(.created_at) | .archive_download_url" \
2>/dev/null || true)
if [ -n "$url" ] && [ "$url" != "null" ]; then
if curl -sSL -H "Authorization: Bearer $GH_TOKEN" -o marker.zip "$url" \
&& unzip -o -q marker.zip; then
prev=$(tr -d '[:space:]' < nightly-build-commit.txt 2>/dev/null || true)
fi
rm -f marker.zip nightly-build-commit.txt
fi
if [ -n "$prev" ] && git cat-file -e "${prev}^{commit}" 2>/dev/null; then
echo "Generating changelog since previous post: $prev"
range_args=("${prev}..HEAD")
else
echo "No reachable previous marker; falling back to the last 24 hours."
range_args=(--since="24 hours ago" HEAD)
fi
notes=$(git log --no-merges --pretty=format:'- %s' "${range_args[@]}" | head -n 50)
if [ -z "$notes" ]; then
echo "No new commits; nothing to post."
echo "has-changes=false" >> "$GITHUB_OUTPUT"
exit 0
fi
# Cap the whole changelog to keep the Slack message a reasonable size.
# head -c caps the combined stream; cut -c would only cap each line independently.
notes=$(printf '%s' "$notes" | head -c 3900)
{
echo "has-changes=true"
echo "notes<<NOTES_EOF"
echo "$notes"
echo "NOTES_EOF"
} >> "$GITHUB_OUTPUT"
- name: 📝 Build Slack payload
id: payload
if: ${{ steps.notes.outputs.has-changes == 'true' }}
env:
NOTES: ${{ steps.notes.outputs.notes }}
run: |
text="*What changed on main since yesterday*
${NOTES}"
payload=$(jq -n --arg text "$text" '{text: $text}')
{
echo "payload<<PAYLOAD_EOF"
echo "$payload"
echo "PAYLOAD_EOF"
} >> "$GITHUB_OUTPUT"
- name: 🔔 Notify Slack
if: ${{ steps.notes.outputs.has-changes == 'true' }}
uses: slackapi/slack-github-action@dcb1066f776dd043e64d0e8ba94ca15cc7e1875d # v4.0.0
with:
webhook: ${{ secrets.NIGHTLY_BUILDS_SLACK_WEBHOOK }}
webhook-type: incoming-webhook
payload: ${{ steps.payload.outputs.payload }}
# Steps run in order, so a failed Slack post stops the job before the marker moves.
- name: ✏️ Write commit marker
env:
GITHUB_SHA: ${{ github.sha }}
run: echo "$GITHUB_SHA" > nightly-build-commit.txt
- name: 🚀 Upload commit marker
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: nightly-build-commit
path: nightly-build-commit.txt
retention-days: 90