From 7c26eb9a241a11087c51a1d6dfa34dd66c56c8b1 Mon Sep 17 00:00:00 2001 From: Adrian Castro <22133246+castdrian@users.noreply.github.com> Date: Sat, 1 Aug 2026 23:43:07 +0200 Subject: [PATCH 1/8] ci(ios): gate hosted build on iOS changes --- .github/workflows/ci.yml | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 37e30ec4..ab2444c9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,8 +10,6 @@ name: ci # The T3 content tier asserts Pokemon Red facts; scripts/test.sh detects # data/generated/ is absent and skips it rather than failing. # -# Runs alongside release.yml, which is untouched by this file. - on: push: # Integration branch + release branch. PRs already run via pull_request @@ -25,6 +23,42 @@ concurrency: cancel-in-progress: true jobs: + ios-changes: + name: detect iOS changes + runs-on: ubuntu-latest + outputs: + changed: ${{ steps.paths.outputs.changed }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - id: paths + env: + BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.before }} + HEAD_SHA: ${{ github.sha }} + run: | + if [ -z "$BASE_SHA" ] || [ "$BASE_SHA" = "0000000000000000000000000000000000000000" ]; then + echo "changed=true" >> "$GITHUB_OUTPUT" + exit 0 + fi + if git diff --name-only "$BASE_SHA" "$HEAD_SHA" | grep -Eq '^(mobile/ios/|scripts/build_ios\.sh$|\.github/workflows/(ci|release)\.yml$)'; then + echo "changed=true" >> "$GITHUB_OUTPUT" + else + echo "changed=false" >> "$GITHUB_OUTPUT" + fi + + ios-build: + name: iOS build + needs: ios-changes + if: needs.ios-changes.outputs.changed == 'true' + runs-on: macos-latest + steps: + - uses: actions/checkout@v4 + - name: install xcbeautify + run: brew list xcbeautify >/dev/null 2>&1 || brew install xcbeautify + - name: build iOS simulator app + run: scripts/build_ios.sh --fetch --release + headless: name: headless suites (no ROM) runs-on: ubuntu-latest From 5f89def2ceb4dbcbc76b2637e4702f001a27c308 Mon Sep 17 00:00:00 2001 From: Adrian Castro <22133246+castdrian@users.noreply.github.com> Date: Sat, 1 Aug 2026 23:43:08 +0200 Subject: [PATCH 2/8] ci: select hosted runners for forks --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ab2444c9..de8fad26 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -51,7 +51,7 @@ jobs: name: iOS build needs: ios-changes if: needs.ios-changes.outputs.changed == 'true' - runs-on: macos-latest + runs-on: ${{ fromJSON(github.repository == 'bryanthaboi/gen1recomp' && '["self-hosted", "macOS"]' || '"macos-latest"') }} steps: - uses: actions/checkout@v4 - name: install xcbeautify diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5ca8c37e..fb1b313f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -42,7 +42,7 @@ concurrency: jobs: release: - runs-on: [self-hosted, macOS] + runs-on: ${{ fromJSON(github.repository == 'bryanthaboi/gen1recomp' && '["self-hosted", "macOS"]' || '"macos-latest"') }} steps: # The self-hosted runner lives under the machine owner's home From 5f75cfd691628567698f91cf5b5a28e31b199815 Mon Sep 17 00:00:00 2001 From: Adrian Castro <22133246+castdrian@users.noreply.github.com> Date: Sat, 1 Aug 2026 23:43:11 +0200 Subject: [PATCH 3/8] ci: verify release builds on fork runners --- .github/workflows/release.yml | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fb1b313f..efddc626 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -127,6 +127,7 @@ jobs: echo "tag=$tag" >> "$GITHUB_OUTPUT" - name: Import signing certificate into a temporary keychain + if: github.repository == 'bryanthaboi/gen1recomp' run: | set -euo pipefail KEYCHAIN_PATH="$RUNNER_TEMP/pokemon-signing.keychain-db" @@ -182,13 +183,17 @@ jobs: brew list xcbeautify >/dev/null 2>&1 || brew install xcbeautify - name: Build iOS + env: + CANONICAL_REPOSITORY: ${{ github.repository == 'bryanthaboi/gen1recomp' }} run: | set -euo pipefail - # Device Release IPA; signs with the Apple Development identity on - # the runner (auto team detection). Users on other Apple IDs still - # re-sign or build via docs/ios-install.md. - scripts/build_ios.sh --fetch --device --release \ - --version "${{ steps.ver.outputs.version }}" + if [ "$CANONICAL_REPOSITORY" = true ]; then + scripts/build_ios.sh --fetch --device --release \ + --version "${{ steps.ver.outputs.version }}" + else + scripts/build_ios.sh --fetch --release \ + --version "${{ steps.ver.outputs.version }}" + fi - name: Build Anbernic RG34XXSP port run: | @@ -198,6 +203,7 @@ jobs: ./build-rg34xxsp.sh --version "${{ steps.ver.outputs.version }}" - name: Notarize & staple macOS app + if: github.repository == 'bryanthaboi/gen1recomp' run: | set -euo pipefail ci_dir="${POKEMON_CI_DIR:-$HOME/.config/pokemon-ci}" @@ -232,6 +238,7 @@ jobs: echo "Notarized + stapled ✓" - name: Stage release assets + if: github.repository == 'bryanthaboi/gen1recomp' id: assets run: | set -euo pipefail @@ -271,6 +278,7 @@ jobs: cat "$outdir/sha256sums.txt" - name: Publish GitHub Release + if: github.repository == 'bryanthaboi/gen1recomp' env: GH_TOKEN: ${{ github.token }} run: | @@ -376,6 +384,6 @@ jobs: echo "Published release $tag" - name: Clean up signing keychain - if: always() + if: ${{ always() && github.repository == 'bryanthaboi/gen1recomp' }} run: | security delete-keychain "$RUNNER_TEMP/pokemon-signing.keychain-db" 2>/dev/null || true From 1b8b3ad538361c82c72c123c90a5222310d55d02 Mon Sep 17 00:00:00 2001 From: Adrian Castro <22133246+castdrian@users.noreply.github.com> Date: Sat, 1 Aug 2026 23:43:11 +0200 Subject: [PATCH 4/8] ci(ios): build device release on canonical repo --- .github/workflows/ci.yml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index de8fad26..cabc9ca4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,8 +56,15 @@ jobs: - uses: actions/checkout@v4 - name: install xcbeautify run: brew list xcbeautify >/dev/null 2>&1 || brew install xcbeautify - - name: build iOS simulator app - run: scripts/build_ios.sh --fetch --release + - name: build iOS release + env: + CANONICAL_REPOSITORY: ${{ github.repository == 'bryanthaboi/gen1recomp' }} + run: | + if [ "$CANONICAL_REPOSITORY" = true ]; then + scripts/build_ios.sh --fetch --device --release + else + scripts/build_ios.sh --fetch --release + fi headless: name: headless suites (no ROM) From 00d13d3c35bdc7a32eac0e17035615c7b2fc95e4 Mon Sep 17 00:00:00 2001 From: Adrian Castro <22133246+castdrian@users.noreply.github.com> Date: Sat, 1 Aug 2026 23:43:12 +0200 Subject: [PATCH 5/8] ci(ios): comment release artifacts on pull requests --- .github/workflows/ci.yml | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cabc9ca4..598c4dbc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,6 +22,10 @@ concurrency: group: ci-${{ github.ref }} cancel-in-progress: true +permissions: + contents: read + pull-requests: write + jobs: ios-changes: name: detect iOS changes @@ -52,6 +56,8 @@ jobs: needs: ios-changes if: needs.ios-changes.outputs.changed == 'true' runs-on: ${{ fromJSON(github.repository == 'bryanthaboi/gen1recomp' && '["self-hosted", "macOS"]' || '"macos-latest"') }} + outputs: + ipa_url: ${{ steps.upload-ipa.outputs.artifact-url }} steps: - uses: actions/checkout@v4 - name: install xcbeautify @@ -65,6 +71,33 @@ jobs: else scripts/build_ios.sh --fetch --release fi + - name: upload iOS release artifact + id: upload-ipa + if: github.repository == 'bryanthaboi/gen1recomp' + uses: actions/upload-artifact@v4 + with: + name: gen1recomp-ios-ipa + path: dist/ios/gen1recomp.ipa + if-no-files-found: error + retention-days: 7 + + ios-build-comment: + name: iOS artifact comment + needs: ios-build + if: github.event_name == 'pull_request' && github.repository == 'bryanthaboi/gen1recomp' && needs.ios-build.result == 'success' + runs-on: ubuntu-latest + steps: + - name: comment iOS artifact + uses: thollander/actions-comment-pull-request@v3 + with: + message: | + #### iOS Release IPA + + - [Download gen1recomp.ipa](${{ needs.ios-build.outputs.ipa_url }}) + + Automatically generated. [View workflow run](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) + comment-tag: ios-build-result + github-token: ${{ secrets.GITHUB_TOKEN }} headless: name: headless suites (no ROM) From 2e46954fe0d80a265235145ee247003482131b1a Mon Sep 17 00:00:00 2001 From: Adrian Castro <22133246+castdrian@users.noreply.github.com> Date: Sat, 1 Aug 2026 23:56:04 +0200 Subject: [PATCH 6/8] ci(ios): use release signing in verification --- .github/workflows/ci.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 598c4dbc..44eeba01 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -60,6 +60,25 @@ jobs: ipa_url: ${{ steps.upload-ipa.outputs.artifact-url }} steps: - uses: actions/checkout@v4 + - name: import signing certificate + if: github.repository == 'bryanthaboi/gen1recomp' + run: | + keychain_path="$RUNNER_TEMP/gen1recomp-ci-signing.keychain-db" + ci_dir="${POKEMON_CI_DIR:-$HOME/.config/pokemon-ci}" + p12="$ci_dir/signing.p12" + passfile="$ci_dir/signing.pass" + [ -f "$p12" ] && [ -f "$passfile" ] || exit 1 + p12pw="$(cat "$passfile")" + kcpw="$(openssl rand -base64 24)" + echo "::add-mask::$kcpw" + security delete-keychain "$keychain_path" 2>/dev/null || true + security create-keychain -p "$kcpw" "$keychain_path" + security set-keychain-settings "$keychain_path" + security unlock-keychain -p "$kcpw" "$keychain_path" + security import "$p12" -P "$p12pw" -k "$keychain_path" -T /usr/bin/codesign -T /usr/bin/security + security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$kcpw" "$keychain_path" >/dev/null + existing="$(security list-keychains -d user | sed -e 's/^[[:space:]]*//' -e 's/"//g')" + security list-keychains -d user -s "$keychain_path" $existing - name: install xcbeautify run: brew list xcbeautify >/dev/null 2>&1 || brew install xcbeautify - name: build iOS release @@ -80,6 +99,9 @@ jobs: path: dist/ios/gen1recomp.ipa if-no-files-found: error retention-days: 7 + - name: clean up signing keychain + if: ${{ always() && github.repository == 'bryanthaboi/gen1recomp' }} + run: security delete-keychain "$RUNNER_TEMP/gen1recomp-ci-signing.keychain-db" 2>/dev/null || true ios-build-comment: name: iOS artifact comment From fe16b3259ca5845c48c1d96312cfe38dc66accba Mon Sep 17 00:00:00 2001 From: Adrian Castro <22133246+castdrian@users.noreply.github.com> Date: Sun, 2 Aug 2026 00:01:53 +0200 Subject: [PATCH 7/8] ci(ios): comment artifacts after pull request builds --- .github/workflows/ci.yml | 19 ---------- .github/workflows/ios-artifact-comment.yml | 43 ++++++++++++++++++++++ 2 files changed, 43 insertions(+), 19 deletions(-) create mode 100644 .github/workflows/ios-artifact-comment.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 44eeba01..66600641 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,7 +24,6 @@ concurrency: permissions: contents: read - pull-requests: write jobs: ios-changes: @@ -103,24 +102,6 @@ jobs: if: ${{ always() && github.repository == 'bryanthaboi/gen1recomp' }} run: security delete-keychain "$RUNNER_TEMP/gen1recomp-ci-signing.keychain-db" 2>/dev/null || true - ios-build-comment: - name: iOS artifact comment - needs: ios-build - if: github.event_name == 'pull_request' && github.repository == 'bryanthaboi/gen1recomp' && needs.ios-build.result == 'success' - runs-on: ubuntu-latest - steps: - - name: comment iOS artifact - uses: thollander/actions-comment-pull-request@v3 - with: - message: | - #### iOS Release IPA - - - [Download gen1recomp.ipa](${{ needs.ios-build.outputs.ipa_url }}) - - Automatically generated. [View workflow run](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) - comment-tag: ios-build-result - github-token: ${{ secrets.GITHUB_TOKEN }} - headless: name: headless suites (no ROM) runs-on: ubuntu-latest diff --git a/.github/workflows/ios-artifact-comment.yml b/.github/workflows/ios-artifact-comment.yml new file mode 100644 index 00000000..7a3fe8b7 --- /dev/null +++ b/.github/workflows/ios-artifact-comment.yml @@ -0,0 +1,43 @@ +name: iOS artifact comment + +on: + workflow_run: + workflows: [ci] + types: [completed] + +permissions: + contents: read + pull-requests: write + +jobs: + comment: + if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success' + runs-on: ubuntu-latest + steps: + - id: artifact + env: + GH_TOKEN: ${{ github.token }} + RUN_ID: ${{ github.event.workflow_run.id }} + HEAD_BRANCH: ${{ github.event.workflow_run.head_branch }} + HEAD_REPOSITORY: ${{ github.event.workflow_run.head_repository.full_name }} + run: | + artifact_id="$(gh api "repos/$GITHUB_REPOSITORY/actions/runs/$RUN_ID/artifacts" --jq '.artifacts[] | select(.name == "gen1recomp-ios-ipa") | .id')" + [ -n "$artifact_id" ] || exit 0 + head_owner="${HEAD_REPOSITORY%%/*}" + pr_number="$(gh api "repos/$GITHUB_REPOSITORY/pulls?state=open&head=$head_owner:$HEAD_BRANCH" --jq '.[0].number // empty')" + [ -n "$pr_number" ] || exit 0 + echo "artifact_url=https://github.com/$GITHUB_REPOSITORY/actions/runs/$RUN_ID/artifacts/$artifact_id" >> "$GITHUB_OUTPUT" + echo "pr_number=$pr_number" >> "$GITHUB_OUTPUT" + - name: comment iOS artifact + if: steps.artifact.outputs.pr_number != '' + uses: thollander/actions-comment-pull-request@v3 + with: + message: | + #### iOS Release IPA + + - [Download gen1recomp.ipa](${{ steps.artifact.outputs.artifact_url }}) + + Automatically generated. [View workflow run](https://github.com/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }}) + pr-number: ${{ steps.artifact.outputs.pr_number }} + comment-tag: ios-build-result + github-token: ${{ github.token }} From 1a2b23a066697255efa403a5b520b6e2db7e45a6 Mon Sep 17 00:00:00 2001 From: Adrian Castro <22133246+castdrian@users.noreply.github.com> Date: Sun, 2 Aug 2026 00:26:48 +0200 Subject: [PATCH 8/8] ci: configure dependabot for actions --- .github/dependabot.yml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..ca79ca5b --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: github-actions + directory: / + schedule: + interval: weekly