Skip to content

Commit 1437b99

Browse files
committed
create build branch of branch workflow and re use it in nightly build and upload to testflight
1 parent c1f2eb6 commit 1437b99

3 files changed

Lines changed: 138 additions & 201 deletions

File tree

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
name: Create Build Branch
2+
3+
# Reusable workflow that creates an ephemeral build/<source>-<timestamp> branch
4+
# from a source ref. This avoids pushing version-bump commits directly to
5+
# protected branches (e.g. main).
6+
#
7+
# The caller is responsible for deleting the branch after use.
8+
9+
on:
10+
workflow_call:
11+
inputs:
12+
source_branch:
13+
description: 'Branch, tag, or SHA to branch from'
14+
required: true
15+
type: string
16+
outputs:
17+
build_branch:
18+
description: 'Name of the created ephemeral build branch'
19+
value: ${{ jobs.create.outputs.branch_name }}
20+
21+
jobs:
22+
create:
23+
name: Create build branch
24+
runs-on: ubuntu-latest
25+
outputs:
26+
branch_name: ${{ steps.create-branch.outputs.branch_name }}
27+
steps:
28+
- uses: actions/checkout@v4
29+
with:
30+
fetch-depth: 0
31+
ref: ${{ inputs.source_branch }}
32+
token: ${{ secrets.PR_TOKEN || github.token }}
33+
- name: Create temporary build branch
34+
id: create-branch
35+
env:
36+
SOURCE_BRANCH: ${{ inputs.source_branch }}
37+
run: |
38+
TIMESTAMP=$(date +%s%3N)
39+
SANITIZED=$(echo "$SOURCE_BRANCH" | tr '/' '-')
40+
BRANCH_NAME="build/${SANITIZED}-${TIMESTAMP}"
41+
git checkout -b "$BRANCH_NAME"
42+
git push origin "$BRANCH_NAME"
43+
echo "branch_name=$BRANCH_NAME" >> "$GITHUB_OUTPUT"
44+
echo "✅ Created build branch: $BRANCH_NAME"
Lines changed: 73 additions & 179 deletions
Original file line numberDiff line numberDiff line change
@@ -1,211 +1,105 @@
11
name: Nightly Build
22

3-
# Triggered by every push to chore/temp-nightly (which nightly-temp-branch-sync.yml
4-
# force-pushes daily at 4 AM UTC to match main).
5-
# Temporarily now this is pointing to test/temp-nightly instead of chore/temp-nightly.
3+
# Runs on a schedule (4 AM UTC) like the old nightly-temp-branch-sync.
4+
# Each build creates its own ephemeral branch via create-build-branch.yml,
5+
# so the persistent chore/temp-nightly branch is no longer needed.
66
#
7-
# [skip ci] commits (e.g. version bumps pushed via update-latest-build-version.yml)
8-
# are automatically skipped by GitHub Actions, so this workflow will NOT
9-
# double-trigger on those commits.
7+
# iOS builds are handled end-to-end by upload-to-testflight.yml (build + upload).
8+
# Android builds use create-build-branch.yml + build.yml (build artifacts only).
109
#
11-
# Version strategy: exp and rc builds share the same bundle ID (MetaMask) so
12-
# TestFlight requires unique CFBundleVersion per upload. We call the external
13-
# version generator once (→ version N for exp), then locally increment to N+1
14-
# for the rc build. Both builds run in parallel after their respective bumps.
10+
# rc depends on exp within each platform stream to ensure the external version
11+
# service produces sequential numbers (N for exp, N+1 for rc).
12+
# iOS and Android streams run in parallel; their version numbers will differ
13+
# but remain unique, which is all TestFlight / Play Store require.
1514

1615
on:
17-
push:
18-
branches:
19-
- test/temp-nightly
16+
schedule:
17+
# NOTE: Scheduled workflows ALWAYS run from the default branch (main)
18+
- cron: '0 4 * * *'
2019
workflow_dispatch:
2120

22-
# contents: write required by build.yml update-build-version job (version bump commit push)
2321
permissions:
2422
contents: write
2523
id-token: write
2624

2725
jobs:
28-
bump-version-exp:
29-
name: Bump build version (exp)
30-
uses: ./.github/workflows/update-latest-build-version.yml
31-
permissions:
32-
contents: write
33-
id-token: write
26+
# ── iOS exp: build + TestFlight upload ─────────────────────────────────
27+
ios-exp:
28+
name: Nightly iOS exp
29+
uses: ./.github/workflows/upload-to-testflight.yml
3430
with:
35-
base-branch: ${{ github.ref_name }}
31+
source_branch: main
32+
environment: exp
33+
testflight_group: 'MetaMask BETA & Release Candidates'
3634
secrets: inherit
3735

38-
bump-version-rc:
39-
name: Bump build version (rc)
40-
needs: [bump-version-exp]
41-
runs-on: ubuntu-latest
42-
permissions:
43-
contents: write
44-
outputs:
45-
commit-hash: ${{ steps.bump.outputs.commit-hash }}
46-
build-version: ${{ steps.bump.outputs.build-version }}
47-
steps:
48-
- uses: actions/checkout@v4
49-
with:
50-
ref: ${{ needs.bump-version-exp.outputs.commit-hash }}
51-
fetch-depth: 0
52-
token: ${{ secrets.PR_TOKEN || github.token }}
36+
# ── iOS rc: build + TestFlight upload (after exp for sequential versions) ─
37+
ios-rc:
38+
name: Nightly iOS rc
39+
needs: [ios-exp]
40+
uses: ./.github/workflows/upload-to-testflight.yml
41+
with:
42+
source_branch: main
43+
environment: rc
44+
testflight_group: 'MetaMask BETA & Release Candidates'
45+
secrets: inherit
5346

54-
- name: Increment version for RC build
55-
id: bump
56-
env:
57-
EXP_VERSION: ${{ needs.bump-version-exp.outputs.build-version }}
58-
HEAD_REF: ${{ github.ref_name }}
59-
run: |
60-
RC_VERSION=$((EXP_VERSION + 1))
61-
echo "Exp version: $EXP_VERSION → RC version: $RC_VERSION"
62-
./scripts/set-build-version.sh "$RC_VERSION"
63-
git config user.name metamaskbot
64-
git config user.email metamaskbot@users.noreply.github.com
65-
git add bitrise.yml package.json ios/MetaMask.xcodeproj/project.pbxproj android/app/build.gradle
66-
git commit -m "[skip ci] Bump version number to ${RC_VERSION} (nightly rc)"
67-
git push origin HEAD:"$HEAD_REF" --force-with-lease
68-
echo "commit-hash=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
69-
echo "build-version=$RC_VERSION" >> "$GITHUB_OUTPUT"
47+
# ── Android exp: ephemeral branch + build ──────────────────────────────
48+
android-exp-branch:
49+
uses: ./.github/workflows/create-build-branch.yml
50+
with:
51+
source_branch: main
52+
secrets: inherit
7053

71-
build-exp:
72-
name: Nightly exp build (main-exp)
73-
needs: [bump-version-exp]
54+
android-exp:
55+
name: Nightly Android exp
56+
needs: [android-exp-branch]
7457
uses: ./.github/workflows/build.yml
7558
with:
7659
build_name: main-exp
77-
platform: both
78-
skip_version_bump: true
79-
source_branch: ${{ needs.bump-version-exp.outputs.commit-hash }}
60+
platform: android
61+
skip_version_bump: false
62+
source_branch: ${{ needs.android-exp-branch.outputs.build_branch }}
8063
secrets: inherit
8164

82-
build-rc:
83-
name: Nightly RC build (main-rc)
84-
needs: [bump-version-rc]
65+
# ── Android rc: ephemeral branch + build (after exp for sequential versions) ─
66+
android-rc-branch:
67+
needs: [android-exp]
68+
uses: ./.github/workflows/create-build-branch.yml
69+
with:
70+
source_branch: main
71+
secrets: inherit
72+
73+
android-rc:
74+
name: Nightly Android rc
75+
needs: [android-rc-branch]
8576
uses: ./.github/workflows/build.yml
8677
with:
8778
build_name: main-rc
88-
platform: both
89-
skip_version_bump: true
90-
source_branch: ${{ needs.bump-version-rc.outputs.commit-hash }}
79+
platform: android
80+
skip_version_bump: false
81+
source_branch: ${{ needs.android-rc-branch.outputs.build_branch }}
9182
secrets: inherit
9283

93-
upload-exp-testflight:
94-
name: Upload exp to TestFlight
95-
needs: [build-exp]
96-
runs-on: ghcr.io/cirruslabs/macos-runner:sequoia-xl
97-
environment: apple
98-
steps:
99-
- name: Checkout repository
100-
uses: actions/checkout@v4
101-
with:
102-
fetch-depth: 0
103-
104-
- name: Setup Ruby (iOS)
105-
uses: ruby/setup-ruby@44511735964dcb71245e7e55f72539531f7bc0eb #v1
106-
with:
107-
ruby-version: '3.2.9'
108-
working-directory: ios
109-
bundler-cache: true
110-
111-
- name: Download iOS IPA artifact
112-
uses: actions/download-artifact@v4
113-
with:
114-
name: ios-ipa-main-exp
115-
116-
- name: Find IPA path
117-
id: ipa
118-
run: |
119-
IPA=$(find . -name '*.ipa' -type f | head -1)
120-
if [ -z "$IPA" ]; then
121-
echo "::error::No .ipa file found in artifact"
122-
exit 1
123-
fi
124-
case "$IPA" in /*) ABS="$IPA" ;; *) ABS="$PWD/$IPA" ;; esac
125-
echo "path=$ABS" >> "$GITHUB_OUTPUT"
126-
127-
- name: Setup App Store Connect API Key
128-
run: |
129-
bash scripts/setup-app-store-connect-api-key.sh \
130-
"$APP_STORE_CONNECT_API_KEY_ISSUER_ID" \
131-
"$APP_STORE_CONNECT_API_KEY_KEY_ID" \
132-
"$APP_STORE_CONNECT_API_KEY_KEY_CONTENT"
133-
env:
134-
APP_STORE_CONNECT_API_KEY_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ISSUER_ID }}
135-
APP_STORE_CONNECT_API_KEY_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_KEY_ID }}
136-
APP_STORE_CONNECT_API_KEY_KEY_CONTENT: ${{ secrets.APP_STORE_CONNECT_API_KEY_KEY_CONTENT }}
137-
138-
- name: Upload to TestFlight
139-
run: |
140-
bash scripts/upload-to-testflight.sh \
141-
"github_actions_main-exp" \
142-
"${{ github.ref_name }}" \
143-
"${{ steps.ipa.outputs.path }}" \
144-
"MetaMask BETA & Release Candidates"
145-
146-
- name: Cleanup API Key
147-
if: always()
148-
run: |
149-
rm -f ios/AuthKey.p8
150-
echo "🧹 Cleaned up API key file"
151-
152-
upload-rc-testflight:
153-
name: Upload RC to TestFlight
154-
needs: [build-rc]
155-
runs-on: ghcr.io/cirruslabs/macos-runner:sequoia-xl
156-
environment: apple
84+
# ── Cleanup Android ephemeral branches ─────────────────────────────────
85+
# iOS branches are cleaned up by upload-to-testflight.yml internally.
86+
cleanup:
87+
name: Cleanup Android build branches
88+
needs: [android-exp-branch, android-rc-branch, android-exp, android-rc]
89+
if: always()
90+
runs-on: ubuntu-latest
15791
steps:
158-
- name: Checkout repository
159-
uses: actions/checkout@v4
160-
with:
161-
fetch-depth: 0
162-
163-
- name: Setup Ruby (iOS)
164-
uses: ruby/setup-ruby@44511735964dcb71245e7e55f72539531f7bc0eb #v1
165-
with:
166-
ruby-version: '3.2.9'
167-
working-directory: ios
168-
bundler-cache: true
169-
170-
- name: Download iOS IPA artifact
171-
uses: actions/download-artifact@v4
92+
- uses: actions/checkout@v4
17293
with:
173-
name: ios-ipa-main-rc
174-
175-
- name: Find IPA path
176-
id: ipa
177-
run: |
178-
IPA=$(find . -name '*.ipa' -type f | head -1)
179-
if [ -z "$IPA" ]; then
180-
echo "::error::No .ipa file found in artifact"
181-
exit 1
182-
fi
183-
case "$IPA" in /*) ABS="$IPA" ;; *) ABS="$PWD/$IPA" ;; esac
184-
echo "path=$ABS" >> "$GITHUB_OUTPUT"
185-
186-
- name: Setup App Store Connect API Key
187-
run: |
188-
bash scripts/setup-app-store-connect-api-key.sh \
189-
"$APP_STORE_CONNECT_API_KEY_ISSUER_ID" \
190-
"$APP_STORE_CONNECT_API_KEY_KEY_ID" \
191-
"$APP_STORE_CONNECT_API_KEY_KEY_CONTENT"
94+
token: ${{ secrets.PR_TOKEN || github.token }}
95+
- name: Delete ephemeral branches
19296
env:
193-
APP_STORE_CONNECT_API_KEY_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ISSUER_ID }}
194-
APP_STORE_CONNECT_API_KEY_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_KEY_ID }}
195-
APP_STORE_CONNECT_API_KEY_KEY_CONTENT: ${{ secrets.APP_STORE_CONNECT_API_KEY_KEY_CONTENT }}
196-
197-
- name: Upload to TestFlight
198-
run: |
199-
# Group arg is required as positional placeholder for the 5th arg (distribute_external=false).
200-
# With distribute_external=false the build is uploaded but NOT distributed to external testers.
201-
bash scripts/upload-to-testflight.sh \
202-
"github_actions_main-rc" \
203-
"${{ github.ref_name }}" \
204-
"${{ steps.ipa.outputs.path }}" \
205-
"MetaMask BETA & Release Candidates"
206-
207-
- name: Cleanup API Key
208-
if: always()
97+
EXP_BRANCH: ${{ needs.android-exp-branch.outputs.build_branch }}
98+
RC_BRANCH: ${{ needs.android-rc-branch.outputs.build_branch }}
20999
run: |
210-
rm -f ios/AuthKey.p8
211-
echo "🧹 Cleaned up API key file"
100+
for branch in "$EXP_BRANCH" "$RC_BRANCH"; do
101+
if [ -n "$branch" ]; then
102+
git push origin --delete "$branch" || true
103+
echo "🧹 Deleted: $branch"
104+
fi
105+
done

.github/workflows/upload-to-testflight.yml

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,23 @@ name: Upload to TestFlight
44
# All TestFlight logic lives here; build.yml only builds and uploads artifacts.
55
#
66
on:
7+
workflow_call:
8+
inputs:
9+
source_branch:
10+
description: 'Branch, tag, or SHA to build'
11+
required: true
12+
type: string
13+
default: 'main'
14+
environment:
15+
description: 'Build environment / track (exp, beta, rc)'
16+
required: true
17+
type: string
18+
default: 'rc'
19+
testflight_group:
20+
description: 'TestFlight external testing group'
21+
required: false
22+
type: string
23+
default: 'MetaMask BETA & Release Candidates'
724
workflow_dispatch:
825
inputs:
926
source_branch:
@@ -39,28 +56,10 @@ jobs:
3956
# Create a temporary branch so the version-bump commit can be pushed without
4057
# hitting branch-protection rules on the source branch (e.g. main).
4158
prepare-build-branch:
42-
name: Create build branch
43-
runs-on: ubuntu-latest
44-
outputs:
45-
build_branch: ${{ steps.create-branch.outputs.branch_name }}
46-
steps:
47-
- uses: actions/checkout@v4
48-
with:
49-
fetch-depth: 0
50-
ref: ${{ inputs.source_branch }}
51-
token: ${{ secrets.PR_TOKEN || github.token }}
52-
- name: Create temporary build branch
53-
id: create-branch
54-
env:
55-
SOURCE_BRANCH: ${{ inputs.source_branch }}
56-
run: |
57-
TIMESTAMP=$(date +%s%3N)
58-
SANITIZED=$(echo "$SOURCE_BRANCH" | tr '/' '-')
59-
BRANCH_NAME="build/${SANITIZED}-${TIMESTAMP}"
60-
git checkout -b "$BRANCH_NAME"
61-
git push origin "$BRANCH_NAME"
62-
echo "branch_name=$BRANCH_NAME" >> "$GITHUB_OUTPUT"
63-
echo "✅ Created build branch: $BRANCH_NAME"
59+
uses: ./.github/workflows/create-build-branch.yml
60+
with:
61+
source_branch: ${{ inputs.source_branch }}
62+
secrets: inherit
6463

6564
build:
6665
name: Build iOS (${{ inputs.environment || 'rc' }})

0 commit comments

Comments
 (0)