Add advisory mobile iOS compile job

Co-authored-by: Tom Brow <tomb@block.xyz>
Signed-off-by: Tom Brow <tomb@block.xyz>
This commit is contained in:
npub1tquskdu6yc4h8l7xxtceculxw600grekeq0xg2ukqfrwl7vrzg3quz3gmp
2026-07-28 09:23:47 -07:00
co-authored by Tom Brow
parent 7dfea2634f
commit 13743b4953
3 changed files with 122 additions and 0 deletions
+115
View File
@@ -27,6 +27,7 @@ jobs:
desktop-rust: ${{ steps.filter.outputs.desktop-rust }}
web: ${{ steps.filter.outputs.web }}
mobile: ${{ steps.filter.outputs.mobile }}
mobile-ios: ${{ steps.filter.outputs.mobile-ios }}
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
with:
@@ -68,6 +69,18 @@ jobs:
- 'scripts/test-mobile-worktree-overrides.sh'
- '.github/workflows/mobile-release-candidate.yml'
- '.github/workflows/ci.yml'
mobile-ios:
- 'mobile/ios/**'
- 'mobile/assets/**'
- 'mobile/pubspec.yaml'
- 'mobile/pubspec.lock'
- 'mobile/.metadata'
- 'Justfile'
- 'scripts/mobile-worktree-overrides.sh'
- 'bin/flutter'
- 'bin/dart'
- 'bin/.flutter-*.pkg'
- '.github/workflows/ci.yml'
- name: Release workflow source contract
run: scripts/test-release-ref-contract.sh
- name: Mobile release contract
@@ -831,6 +844,108 @@ jobs:
- name: Build Android debug APK
run: just mobile-build-android
mobile-ios-build:
name: Mobile iOS Build
runs-on: macos-latest
timeout-minutes: 60
needs: [changes]
# Deliberately gated on the path filter for push as well as pull_request.
# Unlike the sibling `mobile` job, this does NOT use
# `github.event_name == 'push' ||`: that disjunct bypasses the filter and
# would run this macOS job on every push to main.
if: needs.changes.outputs.mobile-ios == 'true'
permissions:
contents: read
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
- uses: cashapp/activate-hermit@cea9af7913204a965fd488637a8d1811bba2e616 # v1
- name: Compute Hermit cache key
id: hermit-bin-hash
run: |
hash="$(find ./bin ! -type d | sort | xargs openssl sha256 | openssl sha256 -r | cut -d' ' -f1)"
echo "hash=$hash" >> "$GITHUB_OUTPUT"
- name: Restore Hermit package cache
id: hermit-cache
uses: actions/cache/restore@caa296126883cff596d87d8935842f9db880ef25 # v5
with:
path: ~/.cache/hermit/pkg
key: ${{ runner.os }}-hermit-cache-${{ steps.hermit-bin-hash.outputs.hash }}
restore-keys: ${{ runner.os }}-hermit-cache-
- name: Prime Flutter SDK
run: flutter --version
- name: Save Hermit package cache
if: always() && steps.hermit-cache.outputs.cache-hit != 'true'
uses: actions/cache/save@caa296126883cff596d87d8935842f9db880ef25 # v5
continue-on-error: true
with:
path: ~/.cache/hermit/pkg
key: ${{ runner.os }}-hermit-cache-${{ steps.hermit-bin-hash.outputs.hash }}
- name: Restore pub cache
id: pub-cache
uses: actions/cache/restore@caa296126883cff596d87d8935842f9db880ef25 # v5
with:
path: ~/.pub-cache
key: pub-${{ runner.os }}-${{ hashFiles('mobile/pubspec.lock') }}
restore-keys: pub-${{ runner.os }}-
- name: Install locked CocoaPods
shell: bash
run: |
set -euo pipefail
readonly lockfile='mobile/ios/Podfile.lock'
versions=()
while IFS= read -r version; do
versions+=("$version")
done < <(sed -nE 's/^COCOAPODS: ([0-9]+\.[0-9]+\.[0-9]+)$/\1/p' "$lockfile")
if [[ ${#versions[@]} -ne 1 ]]; then
echo "::error file=$lockfile::Expected exactly one semantic COCOAPODS version, found ${#versions[@]}"
exit 1
fi
readonly version="${versions[0]}"
readonly gem_home="$RUNNER_TEMP/cocoapods-$version"
readonly bin_dir="$RUNNER_TEMP/cocoapods-bin"
rm -rf "$gem_home" "$bin_dir"
mkdir -p "$gem_home" "$bin_dir"
GEM_HOME="$gem_home" GEM_PATH="$gem_home" \
gem install cocoapods --version "$version" --no-document
printf '%s\n' \
"#!$(command -v ruby)" \
"require 'rubygems'" \
"gem 'cocoapods', '$version'" \
"load Gem.bin_path('cocoapods', 'pod', '$version')" \
> "$bin_dir/pod"
chmod +x "$bin_dir/pod"
{
echo "GEM_HOME=$gem_home"
echo "GEM_PATH=$gem_home"
echo 'LANG=en_US.UTF-8'
} >> "$GITHUB_ENV"
echo "$bin_dir" >> "$GITHUB_PATH"
- name: Verify CocoaPods version
shell: bash
run: |
set -euo pipefail
expected="$(sed -nE 's/^COCOAPODS: ([0-9]+\.[0-9]+\.[0-9]+)$/\1/p' mobile/ios/Podfile.lock)"
actual="$(pod --version)"
echo "CocoaPods $actual at $(command -v pod)"
if [[ "$actual" != "$expected" ]]; then
echo "::error::Expected CocoaPods $expected, got $actual"
exit 1
fi
- name: Install dependencies
run: cd mobile && flutter pub get
- name: Save pub cache
if: always() && steps.pub-cache.outputs.cache-hit != 'true'
uses: actions/cache/save@caa296126883cff596d87d8935842f9db880ef25 # v5
continue-on-error: true
with:
path: ~/.pub-cache
key: pub-${{ runner.os }}-${{ hashFiles('mobile/pubspec.lock') }}
- name: Build unsigned iOS debug app
run: just mobile-build-ios
- name: Verify CocoaPods lockfile is unchanged
run: git diff --exit-code -- mobile/ios/Podfile.lock
security:
name: Security
runs-on: ubuntu-latest
+5
View File
@@ -625,6 +625,11 @@ mobile-build-android:
./scripts/mobile-worktree-overrides.sh
unset GIT_DIR GIT_WORK_TREE; cd {{mobile_dir}} && flutter build apk --debug --no-pub
# Compile an unsigned iOS debug build (worktree-aware debug identity)
mobile-build-ios:
./scripts/mobile-worktree-overrides.sh
unset GIT_DIR GIT_WORK_TREE; cd {{mobile_dir}} && flutter build ios --debug --no-codesign --no-pub
# Run the mobile app on iOS simulator (worktree-aware debug identity)
mobile-dev:
#!/usr/bin/env bash
+2
View File
@@ -3,6 +3,8 @@ import Flutter
import UIKit
import UserNotifications
private let deliberateMobileIosCiCompileFailure: Int = "remove after red CI proof"
@main
@objc class AppDelegate: FlutterAppDelegate, FlutterImplicitEngineDelegate {
private var mediaUploadChannel: FlutterMethodChannel?