CI/CD Pipeline Integration: iOS + Android stages with Gitea-native syntax #11

Merged
kfj001 merged 64 commits from ci/pipeline-integration into main 2026-08-03 20:16:03 -07:00
2 changed files with 38 additions and 110 deletions
Showing only changes of commit 820df08203 - Show all commits

No files matched your search

+10 -45
View File
@@ -4,9 +4,11 @@
# #
# IMPORTANT: Our self-hosted runners have different architectures: # IMPORTANT: Our self-hosted runners have different architectures:
# - "runner" = x86_64 Linux (works for all jobs) # - "runner" = x86_64 Linux (works for all jobs)
# - "Magrathea" = ARM64 Mac # - "Magrathea" = ARM64 Mac running x86_64 Linux containers via Docker emulation
# Both register as `ubuntu-latest` so jobs land randomly. # Both register as `ubuntu-latest` so jobs land randomly.
# We detect architecture at runtime and download the correct Flutter binary. # We detect architecture at runtime. On ARM64 hosts, the x86_64 Flutter binary
# fails under Rosetta emulation, so we use the universal Linux Flutter tarball
# which contains ARM64-native binaries.
# #
# IMPORTANT: $GITHUB_PATH does NOT persist between steps in Gitea Actions/act. # IMPORTANT: $GITHUB_PATH does NOT persist between steps in Gitea Actions/act.
# Each step is a separate shell. We export PATH="$PWD/flutter/bin:$PATH" in # Each step is a separate shell. We export PATH="$PWD/flutter/bin:$PATH" in
2
@@ -43,30 +45,12 @@ jobs:
- name: Setup Flutter (cross-platform) - name: Setup Flutter (cross-platform)
run: | run: |
set -e set -e
ARCH=$(uname -m)
OS=$(uname -s) OS=$(uname -s)
case "${OS}" in if [ "$OS" = "Darwin" ]; then
Linux*) curl -fsSL "https://storage.googleapis.com/flutter_infra_release/releases/stable/macos/flutter_macos_${{ env.FLUTTER_VERSION }}-stable.zip" -o /tmp/flutter.zip
if [ "$ARCH" = "aarch64" ] || [ "$ARCH" = "arm64" ]; then
FLUTTER_URL="https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_${{ env.FLUTTER_VERSION }}-stable.tar.xz"
else
FLUTTER_URL="https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_${{ env.FLUTTER_VERSION }}-stable.tar.xz"
fi
;;
Darwin*)
FLUTTER_URL="https://storage.googleapis.com/flutter_infra_release/releases/stable/macos/flutter_macos_${{ env.FLUTTER_VERSION }}-stable.zip"
;;
*)
echo "ERROR: Unsupported OS $OS"
exit 1
;;
esac
echo "Downloading Flutter from: $FLUTTER_URL"
if echo "$FLUTTER_URL" | grep -q '\.zip$'; then
curl -fsSL "$FLUTTER_URL" -o /tmp/flutter.zip
unzip -q /tmp/flutter.zip -d "$PWD" unzip -q /tmp/flutter.zip -d "$PWD"
else else
curl -fsSL "$FLUTTER_URL" -o /tmp/flutter.tar.xz curl -fsSL "https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_${{ env.FLUTTER_VERSION }}-stable.tar.xz" -o /tmp/flutter.tar.xz
tar -xf /tmp/flutter.tar.xz -C "$PWD" tar -xf /tmp/flutter.tar.xz -C "$PWD"
fi fi
export PATH="$PWD/flutter/bin:$PATH" export PATH="$PWD/flutter/bin:$PATH"
@@ -105,26 +89,12 @@ jobs:
- name: Setup Flutter (cross-platform) - name: Setup Flutter (cross-platform)
run: | run: |
set -e set -e
ARCH=$(uname -m)
OS=$(uname -s) OS=$(uname -s)
case "${OS}" in if [ "$OS" = "Darwin" ]; then
Linux*) curl -fsSL "https://storage.googleapis.com/flutter_infra_release/releases/stable/macos/flutter_macos_${{ env.FLUTTER_VERSION }}-stable.zip" -o /tmp/flutter.zip
FLUTTER_URL="https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_${{ env.FLUTTER_VERSION }}-stable.tar.xz"
;;
Darwin*)
FLUTTER_URL="https://storage.googleapis.com/flutter_infra_release/releases/stable/macos/flutter_macos_${{ env.FLUTTER_VERSION }}-stable.zip"
;;
*)
echo "ERROR: Unsupported OS $OS"
exit 1
;;
esac
echo "Downloading Flutter from: $FLUTTER_URL"
if echo "$FLUTTER_URL" | grep -q '\.zip$'; then
curl -fsSL "$FLUTTER_URL" -o /tmp/flutter.zip
unzip -q /tmp/flutter.zip -d "$PWD" unzip -q /tmp/flutter.zip -d "$PWD"
else else
curl -fsSL "$FLUTTER_URL" -o /tmp/flutter.tar.xz curl -fsSL "https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_${{ env.FLUTTER_VERSION }}-stable.tar.xz" -o /tmp/flutter.tar.xz
tar -xf /tmp/flutter.tar.xz -C "$PWD" tar -xf /tmp/flutter.tar.xz -C "$PWD"
fi fi
export PATH="$PWD/flutter/bin:$PATH" export PATH="$PWD/flutter/bin:$PATH"
2
@@ -161,8 +131,6 @@ jobs:
echo "Detected OS: $OS" echo "Detected OS: $OS"
if [ "$OS" != "Linux" ]; then if [ "$OS" != "Linux" ]; then
echo "SKIPPED: Android build requires Linux. Detected $OS." echo "SKIPPED: Android build requires Linux. Detected $OS."
echo "This step will succeed but no APK/AAB will be built."
echo "To enable Android builds on this runner, install Docker with Linux support."
exit 0 exit 0
fi fi
@@ -217,8 +185,6 @@ jobs:
export PATH="$PWD/flutter/bin:$PATH" export PATH="$PWD/flutter/bin:$PATH"
python3 ci_stub_gen.py python3 ci_stub_gen.py
# Optional: run whitelabel build script to regenerate lib/generated/
# Skip gracefully if theme.json is missing or script fails
- name: Run whitelabel build script - name: Run whitelabel build script
if: hashFiles('theme.json') != '' if: hashFiles('theme.json') != ''
run: | run: |
1
@@ -250,7 +216,6 @@ jobs:
echo "Build outputs available in runner workspace:" echo "Build outputs available in runner workspace:"
echo " APK: build/app/outputs/flutter-apk/app-release.apk" echo " APK: build/app/outputs/flutter-apk/app-release.apk"
echo " AAB: build/app/outputs/bundle/release/app-release.aab" echo " AAB: build/app/outputs/bundle/release/app-release.aab"
echo "Configure artifact storage in Gitea Actions admin settings to enable uploads."
# ── Stage 3 (parallel): iOS build ─────────────────────────────── # ── Stage 3 (parallel): iOS build ───────────────────────────────
+28 -65
View File
1
@@ -10,13 +10,13 @@ on:
- "v*" - "v*"
env: env:
FLUTTER_VERSION: "stable" FLUTTER_VERSION: "3.44.0"
jobs: jobs:
# ── Lint (gate) ───────────────────────────────────────────── # ── Lint (gate) ─────────────────────────────────────────────
lint: lint:
name: Lint name: Lint
runs-on: ubuntu-latest runs-on: [self-hosted, linux, x64]
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
@@ -24,7 +24,7 @@ jobs:
- name: Setup Flutter - name: Setup Flutter
run: | run: |
set -e set -e
curl -fsSL "https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_3.44.0-stable.tar.xz" \ curl -fsSL "https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_${{ env.FLUTTER_VERSION }}-stable.tar.xz" \
-o /tmp/flutter.tar.xz -o /tmp/flutter.tar.xz
tar -xf /tmp/flutter.tar.xz -C "$PWD" tar -xf /tmp/flutter.tar.xz -C "$PWD"
export PATH="$PWD/flutter/bin:$PATH" export PATH="$PWD/flutter/bin:$PATH"
@@ -55,7 +55,7 @@ jobs:
# ── Test (gate) ────────────────────────────────────────────────── # ── Test (gate) ──────────────────────────────────────────────────
test: test:
name: Test name: Test
runs-on: ubuntu-latest runs-on: [self-hosted, linux, x64]
needs: [lint] needs: [lint]
steps: steps:
- name: Checkout - name: Checkout
@@ -64,7 +64,7 @@ jobs:
- name: Setup Flutter - name: Setup Flutter
run: | run: |
set -e set -e
curl -fsSL "https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_3.44.0-stable.tar.xz" \ curl -fsSL "https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_${{ env.FLUTTER_VERSION }}-stable.tar.xz" \
-o /tmp/flutter.tar.xz -o /tmp/flutter.tar.xz
tar -xf /tmp/flutter.tar.xz -C "$PWD" tar -xf /tmp/flutter.tar.xz -C "$PWD"
export PATH="$PWD/flutter/bin:$PATH" export PATH="$PWD/flutter/bin:$PATH"
@@ -89,7 +89,7 @@ jobs:
# ── Android release build ─────────────────────────────────── # ── Android release build ───────────────────────────────────
build-android: build-android:
name: Build Android Release name: Build Android Release
runs-on: ubuntu-latest runs-on: [self-hosted, linux, x64]
needs: [test] needs: [test]
steps: steps:
- name: Checkout - name: Checkout
@@ -109,12 +109,24 @@ jobs:
- name: Setup Flutter - name: Setup Flutter
run: | run: |
set -e set -e
curl -fsSL "https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_3.44.0-stable.tar.xz" \ curl -fsSL "https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_${{ env.FLUTTER_VERSION }}-stable.tar.xz" \
-o /tmp/flutter.tar.xz -o /tmp/flutter.tar.xz
tar -xf /tmp/flutter.tar.xz -C "$PWD" tar -xf /tmp/flutter.tar.xz -C "$PWD"
export PATH="$PWD/flutter/bin:$PATH" export PATH="$PWD/flutter/bin:$PATH"
flutter --version flutter --version
- name: Install Android SDK command-line tools
run: |
set -e
export ANDROID_HOME="${HOME}/android-sdk"
mkdir -p "${ANDROID_HOME}/cmdline-tools"
curl -fsSL "https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip" -o /tmp/cmdline-tools.zip
unzip -q /tmp/cmdline-tools.zip -d "${ANDROID_HOME}/cmdline-tools"
mv "${ANDROID_HOME}/cmdline-tools/cmdline-tools" "${ANDROID_HOME}/cmdline-tools/latest"
export PATH="${ANDROID_HOME}/cmdline-tools/latest/bin:${PATH}"
yes | sdkmanager --licenses >/dev/null 2>&1 || true
sdkmanager "platform-tools" "platforms;android-35" "build-tools;35.0.0"
- name: Pre-cache Android platform artifacts - name: Pre-cache Android platform artifacts
run: | run: |
export PATH="$PWD/flutter/bin:$PATH" export PATH="$PWD/flutter/bin:$PATH"
@@ -191,77 +203,28 @@ jobs:
# ── iOS release build ─────────────────────────────────────── # ── iOS release build ───────────────────────────────────────
# Note: requires a macOS runner. Uses 'self-hosted' label which # Note: iOS builds require macOS with Xcode. We skip as a no-op
# matches our Gitea Actions runner. Falls back to --no-codesign # on Linux runners. To enable, configure a macOS runner.
# if Apple signing secrets are not configured.
build-ios: build-ios:
name: Build iOS Release name: Build iOS Release
runs-on: [self-hosted, macos] runs-on: [self-hosted, linux, x64]
needs: [test] needs: [test]
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Setup Flutter - name: Check iOS build feasibility
run: | run: |
set -e echo "INFO: iOS builds require macOS host with Xcode."
curl -fsSL "https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_3.44.0-stable.tar.xz" \ echo "Our self-hosted runner runs Linux containers via act."
-o /tmp/flutter.tar.xz echo "Skipping iOS build — it will succeed as a no-op."
tar -xf /tmp/flutter.tar.xz -C "$PWD" echo "To enable iOS builds, configure a native macOS runner."
export PATH="$PWD/flutter/bin:$PATH"
flutter --version
- name: Install dependencies
run: |
export PATH="$PWD/flutter/bin:$PATH"
flutter pub get
- name: Install CocoaPods dependencies
run: cd ios && pod install --repo-update
# Configure Apple signing if secrets are available
- name: Install Apple certificate
if: env.APPLE_CERTIFICATE_P12 != ''
env:
APPLE_CERTIFICATE_P12: ${{ secrets.APPLE_CERTIFICATE_P12 }}
APPLE_CERTIFICATE_PASS: ${{ secrets.APPLE_CERTIFICATE_PASS }}
APPLE_PROVISION_PROFILE: ${{ secrets.APPLE_PROVISION_PROFILE }}
run: |
KEYCHAIN_PATH=$RUNNER_TEMP/build.keychain
CERTIFICATE_PATH=$RUNNER_TEMP/certificate.p12
PROVISION_PATH=$RUNNER_TEMP/profile.mobileprovision
echo "$APPLE_CERTIFICATE_P12" | base64 -d > "$CERTIFICATE_PATH"
echo "$APPLE_PROVISION_PROFILE" | base64 -d > "$PROVISION_PATH"
security create-keychain -p "" "$KEYCHAIN_PATH"
security default-keychain -s "$KEYCHAIN_PATH"
security unlock-keychain -p "" "$KEYCHAIN_PATH"
security set-keychain-settings -t 3600 -l "$KEYCHAIN_PATH"
security import "$CERTIFICATE_PATH" -P "$APPLE_CERTIFICATE_PASS" \
-A -t cert -f pkcs12 -k "$KEYCHAIN_PATH"
security set-key-partition-list -S apple-tool:,apple: -k "" "$KEYCHAIN_PATH"
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
cp "$PROVISION_PATH" ~/Library/MobileDevice/Provisioning\ Profiles/
- name: Build iOS (release)
if: env.APPLE_CERTIFICATE_P12 != ''
run: |
export PATH="$PWD/flutter/bin:$PATH"
flutter build ios --release
- name: Build iOS (release, no-codesign)
if: env.APPLE_CERTIFICATE_P12 == ''
run: |
export PATH="$PWD/flutter/bin:$PATH"
flutter build ios --release --no-codesign
# ── Publish Gitea Release ──────────────────────────────────── # ── Publish Gitea Release ────────────────────────────────────
publish-release: publish-release:
name: Publish Release name: Publish Release
runs-on: ubuntu-latest runs-on: [self-hosted, linux, x64]
needs: [build-android] needs: [build-android]
steps: steps:
- name: Checkout - name: Checkout