mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-10-17 05:41:29 +02:00
The runtime sudo rewrite step hung 51m waiting for a password the runner can't enter. The Mac mini's /etc/hosts already points git.such.software at 127.0.0.1, and the host-mode act_runner inherits it directly, so no runtime modification is needed. Replace the rewrite with a passive grep assertion that fails fast with instructions if the entry is missing. Add a diagnostic step before the upload that prints ACTIONS_RUNTIME_URL, ACTIONS_RESULTS_URL, GITHUB_SERVER_URL + probes each with curl -kIv. The last run never reached the upload step, so we still don't know whether upload-artifact targets git.such.software (uses our hosts override) or a different address injected by act_runner.
333 lines
14 KiB
YAML
333 lines
14 KiB
YAML
name: Hash Bags iOS Simulator build
|
|
|
|
# Phase 1 of iOS CI: validate the Mac runner end-to-end by producing an
|
|
# unsigned simulator .app. Drop the resulting Runner.app into the iOS
|
|
# Simulator on any Apple Silicon Mac to verify the app actually compiles
|
|
# and launches.
|
|
#
|
|
# Phase 2 (separate workflow): full TestFlight pipeline with signing.
|
|
|
|
on:
|
|
# Manual-only for now. Trigger via Actions → "Hash Bags iOS Simulator
|
|
# build" → Run workflow when you want a build.
|
|
workflow_dispatch:
|
|
|
|
# Cancel in-flight runs when a newer commit lands on the same branch — so a
|
|
# burst of commits doesn't pile up N copies of the same long build.
|
|
concurrency:
|
|
group: ios-sim-${{ github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
defaults:
|
|
run:
|
|
shell: bash
|
|
|
|
jobs:
|
|
build:
|
|
runs-on: macos-latest
|
|
env:
|
|
APP_IOS_TYPE: cakewallet
|
|
BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
|
|
# CocoaPods refuses to operate when LANG is ASCII-8BIT (default for the
|
|
# Gitea runner shell). Force UTF-8 globally so `pod install` succeeds.
|
|
LANG: en_US.UTF-8
|
|
LC_ALL: en_US.UTF-8
|
|
# If you added an /etc/hosts entry on the Mac mini that points
|
|
# git.such.software at NPM's LAN IP (so the runner hits NPM's
|
|
# Let's Encrypt cert instead of Gitea's internal self-signed),
|
|
# this env var can be removed. Left in as a belt-and-suspenders
|
|
# fallback — has no effect if certs already verify.
|
|
NODE_TLS_REJECT_UNAUTHORIZED: '0'
|
|
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 1
|
|
|
|
# Self-hosted Mac runner persists Flutter between runs. Only install if
|
|
# it's not already on PATH or version doesn't match.
|
|
- name: Check Flutter 3.32.0
|
|
id: flutter_check
|
|
run: |
|
|
if command -v flutter >/dev/null && flutter --version 2>/dev/null | grep -q "3\.32\.0"; then
|
|
echo "installed=true" >> "$GITHUB_OUTPUT"
|
|
flutter --version
|
|
else
|
|
echo "installed=false" >> "$GITHUB_OUTPUT"
|
|
fi
|
|
|
|
- name: Install Flutter 3.32.0 (if missing)
|
|
if: steps.flutter_check.outputs.installed != 'true'
|
|
uses: subosito/flutter-action@v2
|
|
with:
|
|
flutter-version: '3.32.0'
|
|
channel: stable
|
|
cache: true
|
|
|
|
- name: Install CocoaPods (if missing)
|
|
run: |
|
|
if command -v pod >/dev/null; then
|
|
pod --version
|
|
exit 0
|
|
fi
|
|
if command -v brew >/dev/null; then
|
|
brew install cocoapods
|
|
else
|
|
export GEM_HOME="$HOME/.gem"
|
|
export PATH="$GEM_HOME/bin:$PATH"
|
|
echo "GEM_HOME=$HOME/.gem" >> "$GITHUB_ENV"
|
|
echo "$HOME/.gem/bin" >> "$GITHUB_PATH"
|
|
gem install --user-install cocoapods --no-document
|
|
fi
|
|
pod --version
|
|
|
|
- name: Install Rust + iOS targets (if missing)
|
|
run: |
|
|
if ! command -v rustup >/dev/null; then
|
|
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable --no-modify-path
|
|
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
|
|
export PATH="$HOME/.cargo/bin:$PATH"
|
|
fi
|
|
# Clean any partial downloads from a previously crashed install — those
|
|
# are the source of the 'could not rename .partial → final: No such
|
|
# file or directory' race that breaks parallel pod builds.
|
|
rm -rf "$HOME/.rustup/downloads"/*.partial 2>/dev/null || true
|
|
# Pre-install iOS targets serially so the pod build doesn't try to
|
|
# do it under concurrency.
|
|
rustup target add aarch64-apple-ios
|
|
rustup target add aarch64-apple-ios-sim
|
|
rustup target add x86_64-apple-ios
|
|
rustup show
|
|
|
|
- name: Install Go + gomobile (if missing)
|
|
run: |
|
|
if ! command -v go >/dev/null; then
|
|
if command -v brew >/dev/null; then
|
|
brew install go
|
|
else
|
|
echo "Go missing and brew not available"; exit 1
|
|
fi
|
|
fi
|
|
go version
|
|
# Ensure $(go env GOPATH)/bin is on PATH for subsequent steps.
|
|
GOPATH=$(go env GOPATH)
|
|
echo "$GOPATH/bin" >> "$GITHUB_PATH"
|
|
export PATH="$PATH:$GOPATH/bin"
|
|
# gomobile + gobind are needed by scripts/build_bitbox_flutter.sh
|
|
if ! command -v gomobile >/dev/null; then
|
|
go install golang.org/x/mobile/cmd/gomobile@latest
|
|
go install golang.org/x/mobile/cmd/gobind@latest
|
|
fi
|
|
which gomobile && gomobile version || true
|
|
|
|
- name: Show toolchain
|
|
run: |
|
|
set -x
|
|
flutter --version
|
|
xcodebuild -version
|
|
pod --version
|
|
uname -m
|
|
which curl unzip
|
|
|
|
# ---- External prebuilt deps (same as android/linux) ------------------
|
|
# macOS doesn't ship wget by default; using curl everywhere.
|
|
- name: Fetch prebuilt torch_dart
|
|
run: |
|
|
set -x -e
|
|
pushd scripts
|
|
rm -rf torch_dart torch_dart.tar.gz
|
|
curl -fsSL -o torch_dart.tar.gz https://github.com/MrCyjaneK/torch_dart/releases/download/v1.0.17/torch_dart-v1.0.17.tar.gz
|
|
mkdir torch_dart
|
|
tar -xzf torch_dart.tar.gz -C torch_dart
|
|
rm torch_dart.tar.gz
|
|
popd
|
|
|
|
- name: Fetch prebuilt reown_flutter
|
|
run: |
|
|
set -x -e
|
|
pushd scripts
|
|
rm -rf reown_flutter reown_flutter.tar.gz
|
|
curl -fsSL -o reown_flutter.tar.gz https://github.com/cake-tech/reown_flutter/releases/download/v0.0.4/reown_flutter-v0.0.4.tar.gz
|
|
mkdir reown_flutter
|
|
tar -xzf reown_flutter.tar.gz -C reown_flutter
|
|
rm reown_flutter.tar.gz
|
|
popd
|
|
|
|
- name: Clone BitBox Flutter (iOS — skip Android bindings)
|
|
run: |
|
|
# Pubspec has bitbox_flutter as a path: dep at scripts/bitbox_flutter,
|
|
# so the directory must exist for pub get. The bundled build_bindings.sh
|
|
# runs `gomobile bind -target=android` which needs the Android SDK we
|
|
# don't have on the Mac runner — and the resulting .aar is Android-only.
|
|
# iOS uses bitbox_flutter's native ios/Classes plugin, no .aar required.
|
|
set -x -e
|
|
pushd scripts
|
|
if [[ ! -d bitbox_flutter ]]; then
|
|
git clone https://github.com/konstantinullrich/bitbox_flutter
|
|
fi
|
|
cd bitbox_flutter
|
|
git fetch -a
|
|
git reset --hard
|
|
git checkout 5a6e6dd388ef64003f86094af80d5453518b601d
|
|
git reset --hard
|
|
popd
|
|
|
|
# ---- Native crypto cores (monero_c prebuilt bundle) ------------------
|
|
- name: Fetch prebuilt monero_c bundle
|
|
run: |
|
|
set -x -e
|
|
./scripts/prepare_moneroc.sh
|
|
MONERO_C_TAG=$(cd scripts/monero_c && git describe --tags)
|
|
mkdir -p "scripts/monero_c/release/$MONERO_C_TAG"
|
|
pushd "scripts/monero_c/release/$MONERO_C_TAG"
|
|
curl -fsSL -O https://github.com/MrCyjaneK/monero_c/releases/download/v0.18.4.6-RC1/release-bundle.zip
|
|
unzip -q release-bundle.zip
|
|
rm release-bundle.zip
|
|
echo "=== bundle contents (one level) ==="
|
|
ls
|
|
popd
|
|
|
|
- name: Inspect iOS targets available in monero_c bundle
|
|
run: |
|
|
set -x
|
|
MONERO_C_TAG=$(cd scripts/monero_c && git describe --tags)
|
|
BUNDLE_DIR="scripts/monero_c/release/$MONERO_C_TAG"
|
|
echo "=== bundle top-level ==="
|
|
ls "$BUNDLE_DIR" || true
|
|
echo "=== iOS-y subdirs ==="
|
|
find "$BUNDLE_DIR" -maxdepth 1 -type d \( -name '*ios*' -o -name '*apple*' \) 2>/dev/null
|
|
echo "=== sample contents of one apple-ios target ==="
|
|
for d in "$BUNDLE_DIR"/aarch64-apple-ios "$BUNDLE_DIR"/aarch64-apple-ios-simulator; do
|
|
[[ -d "$d" ]] && { echo "--- $d ---"; ls "$d"; }
|
|
done
|
|
|
|
- name: Build MoneroWallet + WowneroWallet XCFrameworks
|
|
run: |
|
|
set -x -e
|
|
pushd scripts/ios
|
|
bash ./gen_framework.sh
|
|
popd
|
|
ls -la ios/MoneroWallet.xcframework ios/WowneroWallet.xcframework
|
|
|
|
# ---- Configure: pubspec.yaml, Info.plist, GeneratedPluginRegistrant ---
|
|
- name: Run iOS configure (cakewallet profile)
|
|
run: |
|
|
set -x -e
|
|
pushd scripts/ios
|
|
source ./app_env.sh cakewallet
|
|
./app_config.sh
|
|
popd
|
|
|
|
# ---- Secrets ---------------------------------------------------------
|
|
- name: Generate per-module secrets.g.dart files (all empty defaults)
|
|
run: dart run tool/generate_new_secrets.dart
|
|
|
|
- name: Inject Trocador affiliate secrets
|
|
env:
|
|
TROCADOR_API_KEY: ${{ secrets.TROCADOR_API_KEY }}
|
|
TROCADOR_MONERO_API_KEY: ${{ secrets.TROCADOR_MONERO_API_KEY }}
|
|
TROCADOR_EXCHANGE_MARKUP: ${{ secrets.TROCADOR_EXCHANGE_MARKUP }}
|
|
run: |
|
|
# macOS sed needs '' after -i; Linux sed doesn't accept that. This
|
|
# workflow runs on macos only.
|
|
sed -i '' \
|
|
-e "s|const trocadorApiKey = '';|const trocadorApiKey = '${TROCADOR_API_KEY}';|" \
|
|
-e "s|const trocadorMoneroApiKey = '';|const trocadorMoneroApiKey = '${TROCADOR_MONERO_API_KEY}';|" \
|
|
-e "s|const trocadorExchangeMarkup = '';|const trocadorExchangeMarkup = '${TROCADOR_EXCHANGE_MARKUP:-1}';|" \
|
|
lib/.secrets.g.dart
|
|
grep '^const trocador' lib/.secrets.g.dart
|
|
|
|
# ---- Flutter init + codegen -----------------------------------------
|
|
- name: Initialize Flutter SDK (iOS precache)
|
|
run: |
|
|
flutter --version
|
|
flutter precache --ios --no-linux --no-android --no-macos --no-windows --no-fuchsia --no-web || true
|
|
|
|
- name: Build generated code (mobx + hive adapters)
|
|
run: bash model_generator.sh
|
|
|
|
- name: Generate localization
|
|
run: dart run tool/generate_localization.dart
|
|
|
|
- name: Compile SVG assets (res/pictures/*.svg → assets/new-ui/*.svg.vec)
|
|
run: ./compile_graphics.sh
|
|
|
|
# CocoaPods: the iOS Podfile installs Flutter plugin pods. Required
|
|
# before flutter build can link them.
|
|
- name: pod install
|
|
run: |
|
|
cd ios
|
|
pod install --repo-update
|
|
|
|
# ---- Build iOS Simulator app (no codesign) ---------------------------
|
|
- name: Build iOS Simulator app
|
|
run: |
|
|
set -x -e
|
|
flutter build ios --simulator --no-codesign \
|
|
--dart-define-from-file=env.json
|
|
ls -la build/ios/iphonesimulator/
|
|
|
|
- name: Zip Runner.app
|
|
run: |
|
|
cd build/ios/iphonesimulator
|
|
zip -r hash_wallet_ios_sim_${{ github.sha }}.zip Runner.app
|
|
|
|
# Confirm git.such.software resolves to a local target (the Mac itself).
|
|
# The runner inherits the Mac's /etc/hosts directly (host-mode act_runner),
|
|
# so the user should have:
|
|
# 127.0.0.1 git.such.software
|
|
# already in /etc/hosts. We only assert that here, don't modify (sudo
|
|
# without NOPASSWD prompts for a password the runner can't enter).
|
|
#
|
|
# macOS's `getent` doesn't exist and `nslookup` bypasses /etc/hosts.
|
|
# We grep /etc/hosts directly — that's what Node's getaddrinfo will
|
|
# actually consult.
|
|
- name: Verify Gitea hostname resolves locally
|
|
run: |
|
|
if grep -qE '^[[:space:]]*(127\.0\.0\.1|host\.docker\.internal|192\.168\.)[[:space:]]+git\.such\.software' /etc/hosts; then
|
|
echo "✓ /etc/hosts points git.such.software at a local target:"
|
|
grep git.such.software /etc/hosts
|
|
else
|
|
echo "✗ /etc/hosts is MISSING a local override for git.such.software."
|
|
echo " Node will resolve to the public IP and fail on NAT hairpin."
|
|
echo " Add (once, on the Mac mini):"
|
|
echo " sudo sh -c 'echo \"127.0.0.1 git.such.software\" >> /etc/hosts'"
|
|
exit 1
|
|
fi
|
|
|
|
# Diagnostic: print exactly where upload-artifact will try to send data.
|
|
# act_runner injects these env vars; their values tell us whether the
|
|
# upload targets git.such.software (uses our /etc/hosts override) or
|
|
# a LAN IP directly (override irrelevant). Also probe the URL with
|
|
# curl -k so we see the cert + reachability before the real upload.
|
|
- name: Diagnose Actions API endpoint
|
|
run: |
|
|
set +e
|
|
echo "=== Actions runtime env ==="
|
|
echo "ACTIONS_RUNTIME_URL=${ACTIONS_RUNTIME_URL:-<unset>}"
|
|
echo "ACTIONS_RESULTS_URL=${ACTIONS_RESULTS_URL:-<unset>}"
|
|
echo "ACTIONS_CACHE_URL=${ACTIONS_CACHE_URL:-<unset>}"
|
|
echo "GITHUB_SERVER_URL=${GITHUB_SERVER_URL:-<unset>}"
|
|
echo "GITHUB_API_URL=${GITHUB_API_URL:-<unset>}"
|
|
echo "NODE_TLS_REJECT_UNAUTHORIZED=${NODE_TLS_REJECT_UNAUTHORIZED:-<unset>}"
|
|
echo
|
|
# Probe each non-empty URL to see what Node will actually hit.
|
|
for var in ACTIONS_RUNTIME_URL ACTIONS_RESULTS_URL GITHUB_SERVER_URL; do
|
|
url="${!var}"
|
|
[ -z "$url" ] && continue
|
|
host=$(echo "$url" | sed -E 's|^https?://([^/:]+).*|\1|')
|
|
echo "--- $var → $url ---"
|
|
echo "DNS for $host:"
|
|
dscacheutil -q host -a name "$host" 2>/dev/null || nslookup "$host" 2>/dev/null || true
|
|
echo "HEAD probe (curl -kIv, 10s timeout):"
|
|
curl -kIv --max-time 10 "$url" 2>&1 | head -40 || true
|
|
echo
|
|
done
|
|
|
|
- name: Upload .app artifact
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: hash-wallet-ios-sim-${{ github.sha }}
|
|
path: build/ios/iphonesimulator/hash_wallet_ios_sim_*.zip
|
|
retention-days: 14
|