From d50e53e4ad0c7965665798d3387ccdc414c2b445 Mon Sep 17 00:00:00 2001 From: Millian Lamiaux Date: Sun, 19 Jul 2026 16:50:36 +0200 Subject: [PATCH] =?UTF-8?q?fix(ci):=20pr-iphone-deploy=20=E2=80=94=20cache?= =?UTF-8?q?,=20secrets,=20LGTM=20regex,=20concurrency,=20squash?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 10 fixes to .github/workflows/pr-iphone-deploy.yml: Cache & build hygiene: - Stop deleting build/spm-cache (was wiped by 'rm -rf build/'); clean only build/derived. RevenueCat (~1.1 GiB) is finally actually preserved. - Stop nuking ~/Library/Caches/com.apple.dt.Xcode (slows every next build). - Drop '|| true' on brew install — fail loudly if brew is down. - Bump build-deploy timeout 20m → 30m for cold builds. Secrets: - New step writes Config/Secrets.xcconfig from Gitea secrets (SUPABASE_URL, SUPABASE_ANON_KEY, REVENUECAT_API_KEY, POSTHOG_API_KEY) before xcodegen. Preflight fails loud if a required secret is missing. Heredoc body at column 0 (xcconfig keys are whitespace-sensitive). LGTM/KO handling: - Regex now matches anywhere in body with word boundary: \bLGTM\b / \bKO\b. 'Tested, LGTM!' counts; 'KOM' / 'LGTMX' / 'OK' do not. - Re-fetch ALL comments each poll (not since_id) to catch edits. - Squash-merge ({"Do":"squash"}) instead of merge commit. Workflow structure: - Add concurrency block (per-PR, cancel-in-progress) — prevents double-merge and stacked pipelines on successive pushes. - Remove no-op 'permissions:' block (all mutations go via Gitea API with PR_API_TOKEN, native GITHUB_TOKEN is never used). --- .github/workflows/pr-iphone-deploy.yml | 80 +++++++++++++++++++------- 1 file changed, 60 insertions(+), 20 deletions(-) diff --git a/.github/workflows/pr-iphone-deploy.yml b/.github/workflows/pr-iphone-deploy.yml index d7b6b42..9ed691e 100644 --- a/.github/workflows/pr-iphone-deploy.yml +++ b/.github/workflows/pr-iphone-deploy.yml @@ -9,16 +9,21 @@ on: branches: [main] types: [opened, synchronize, reopened] -permissions: - contents: write - pull-requests: write +# Every mutation (comments, merge) goes through the Gitea API with PR_API_TOKEN, +# never the runner's native GITHUB_TOKEN — so a `permissions:` block would be +# a no-op here. Intentionally omitted. +concurrency: + # Per-PR grouping: superseded pushes cancel the previous pipeline, different + # PRs still run in parallel. Prevents double-merges and wasted runner time. + group: pr-iphone-deploy-${{ github.event.pull_request.number }} + cancel-in-progress: true jobs: build-deploy: name: Build & Deploy to iPhone (WiFi/USB) runs-on: macos - timeout-minutes: 20 + timeout-minutes: 30 steps: - name: Checkout @@ -42,9 +47,11 @@ jobs: # Act runner caches rm -rf ~/.cache/act/*/hostexecutor/tabatago-swift/build 2>/dev/null || true - # SPM caches are KEPT between runs — RevenueCat is 1.10 GiB and takes + # SPM cache is KEPT between runs — RevenueCat is ~1.10 GiB and takes # 5+ minutes to clone; re-cloning on every CI run would waste time - # and cause random failures on the act_runner sandbox. + # and cause random failures on the act_runner sandbox. It lives at + # build/spm-cache (see -clonedSourcePackagesDirPath in the Build step) + # so NEVER `rm -rf build/` — only delete build/derived. # Xcode DerivedData — suppression COMPLÈTE (le bundle ID a changé, # l'ancien dossier TabataGo-* peut être ignoré par le nouveau build) @@ -52,10 +59,12 @@ jobs: # Module cache Xcode — des .pcm stale peuvent segfault le linker rm -rf ~/Library/Developer/Xcode/DerivedData/ModuleCache.noindex 2>/dev/null || true - rm -rf ~/Library/Caches/com.apple.dt.Xcode + # NOTE: do NOT `rm -rf ~/Library/Caches/com.apple.dt.Xcode` — that is the + # shared global cache; wiping it slows every subsequent build. - # Build artifacts locaux (utilisés par le step "Build app") - rm -rf build/ + # Build artifacts locaux — sparing build/spm-cache (see above). + rm -rf build/derived + rm -rf build/*.log 2>/dev/null || true rm -rf .build rm -rf tabatago-swift/.build rm -rf tabatago-swift/TabataGo.xcodeproj @@ -65,11 +74,40 @@ jobs: find . -name "Package.resolved" -delete 2>/dev/null || true find . -name ".package.resolved" -delete 2>/dev/null || true - echo "✅ Caches nettoyés" + echo "✅ Caches nettoyés (SPM cache préservé)" - name: Install tools (xcodegen, node, ios-deploy) run: | - brew install xcodegen node ios-deploy || true + # No `|| true` — if brew is down, fail loudly here instead of producing + # confusing "command not found" errors in the next steps. + brew install xcodegen node ios-deploy + + - name: Write Secrets.xcconfig from Gitea secrets + env: + SUPABASE_URL: ${{ secrets.SUPABASE_URL }} + SUPABASE_ANON_KEY: ${{ secrets.SUPABASE_ANON_KEY }} + REVENUECAT_API_KEY: ${{ secrets.REVENUECAT_API_KEY }} + POSTHOG_API_KEY: ${{ secrets.POSTHOG_API_KEY }} + run: | + # Preflight: fail loudly if a secret is missing, rather than producing + # an .app that silently can't reach Supabase/RevenueCat at runtime. + for v in SUPABASE_URL SUPABASE_ANON_KEY REVENUECAT_API_KEY; do + val="$(printenv "$v")" + if [ -z "$val" ]; then + echo "❌ Secret missing: $v. Add it to Gitea repo secrets." + exit 1 + fi + done + # POSTHOG_API_KEY may legitimately be empty (PostHog not yet wired). + # NOTE: heredoc body MUST start at column 0 — xcconfig keys are + # whitespace-sensitive, leading spaces would break the build setting. + cat > tabatago-swift/Config/Secrets.xcconfig </dev/null || echo 0) + # Re-fetch ALL comments each cycle (not since_id) so we also catch + # edits — e.g. a reviewer changing "KO" → "LGTM". Negligible cost for + # PRs with <50 comments. while [ $TRIES -lt $MAX ]; do sleep 30 TRIES=$((TRIES + 1)) COMMENTS=$(curl -s -H "Authorization: token ${GT_TOKEN}" \ - "${API}/issues/${PR}/comments?since_id=${LAST_ID}") + "${API}/issues/${PR}/comments?limit=50&page=1") - if echo "$COMMENTS" | grep -qi '"body": *"LGTM"'; then - echo "✅ LGTM reçu ! Merge..." + # Match LGTM/KO anywhere in the body (with a word boundary so "KOM" + # or "LGTMX" don't trigger). Case-insensitive. + if echo "$COMMENTS" | grep -qiE '"body":[[:space:]]*"[^"]*\bLGTM\b'; then + echo "✅ LGTM reçu ! Squash-merge..." curl -s -X POST \ -H "Authorization: token ${GT_TOKEN}" \ -H "Content-Type: application/json" \ - -d "{\"Do\":\"merge\"}" \ + -d "{\"Do\":\"squash\"}" \ "${API}/pulls/${PR}/merge" - echo "✅ Mergée." + echo "✅ Mergée (squash)." exit 0 fi - if echo "$COMMENTS" | grep -qi '"body": *"KO"'; then + if echo "$COMMENTS" | grep -qiE '"body":[[:space:]]*"[^"]*\bKO\b'; then echo "❌ KO reçu. Bloquée." exit 1 fi