From e3c4ed436cd8a399c6ac136bc321c526edee2afd Mon Sep 17 00:00:00 2001 From: Joonas Kerttula Date: Fri, 18 Sep 2026 14:47:28 +0300 Subject: [PATCH 1/4] ci: update GitHub Actions to latest versions and improve CI workflow --- .github/actions/setup/action.yml | 4 +- .github/workflows/ci.yml | 118 ++++++++++++++++++++------- .github/workflows/license-check.yaml | 14 +++- .github/workflows/publish.yml | 12 ++- .github/workflows/release-please.yml | 2 +- AGENTS.md | 7 +- 6 files changed, 115 insertions(+), 42 deletions(-) diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml index 793d043d..71dd77d9 100644 --- a/.github/actions/setup/action.yml +++ b/.github/actions/setup/action.yml @@ -19,13 +19,13 @@ runs: using: composite steps: - name: Setup Node.js - uses: actions/setup-node@3235b876344d2a9aa001b8d1453c930bba69e610 + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version-file: .nvmrc - name: Cache dependencies id: yarn-cache - uses: actions/cache@6f8efc29b200d32929f49075959781ed54ec270c + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: | **/node_modules diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ca823f6a..79ac23d7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,12 +32,60 @@ on: workflow_call: jobs: + changes: + runs-on: ubuntu-latest + timeout-minutes: 10 + outputs: + android: ${{ steps.filter.outputs.android }} + ios: ${{ steps.filter.outputs.ios }} + steps: + - name: Checkout + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + # Full history, so the merge base with the target branch is reachable. + fetch-depth: 0 + + - name: Classify changed files + id: filter + env: + EVENT_NAME: ${{ github.event_name }} + BASE_REF: ${{ github.base_ref }} + run: | + android=true + ios=true + + if [[ "$EVENT_NAME" == "pull_request" ]]; then + changed=$(git diff --name-only "origin/$BASE_REF...HEAD") + echo "Changed files:" + echo "$changed" + + if [[ -n "$changed" ]]; then + android=false + ios=false + while IFS= read -r file; do + case "$file" in + android/*|example/android/*) android=true ;; + ios/*|example/ios/*|*.podspec|example/Gemfile|example/Gemfile.lock) ios=true ;; + # Shared sources and root-level files reach both platforms. + *) android=true; ios=true ;; + esac + done <<< "$changed" + fi + fi + + echo "Build Android: $android, build iOS: $ios" + echo "android=$android" >> "$GITHUB_OUTPUT" + echo "ios=$ios" >> "$GITHUB_OUTPUT" + lint: runs-on: ubuntu-latest timeout-minutes: 30 steps: - name: Checkout - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false - name: Setup uses: ./.github/actions/setup @@ -53,7 +101,9 @@ jobs: timeout-minutes: 30 steps: - name: Checkout - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false - name: Install clang-format run: sudo apt-get install clang-format @@ -66,10 +116,12 @@ jobs: timeout-minutes: 30 steps: - name: Checkout - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false - name: Install JDK - uses: actions/setup-java@e9fbacdec3bb3b6036605a3e6f7995d66773a8c6 + uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1 with: distribution: 'zulu' java-version: '17' @@ -104,28 +156,29 @@ jobs: run: | find . -name "*.kt" -not -path "*/build/*" | xargs java -jar $HOME/ktfmt/ktfmt.jar --google-style --dry-run --set-exit-if-changed - test: - runs-on: ubuntu-latest - timeout-minutes: 30 - steps: - - name: Placeholder Test Step - run: echo "No tests to run yet" && true - # TODO: build test orchestration for Android and iOS and run detox tests on both platforms. - # - name: Checkout - # uses: actions/checkout@v4 - - # - name: Setup - # uses: ./.github/actions/setup - - # - name: Run unit tests - # run: yarn test --maxWorkers=2 --coverage + # There is no test orchestration for Android and iOS yet, and a job that only + # echoes still claims a runner. Restore this once Detox runs on both platforms. + # test: + # runs-on: ubuntu-latest + # timeout-minutes: 30 + # steps: + # - name: Checkout + # uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + # with: + # persist-credentials: false + # - name: Setup + # uses: ./.github/actions/setup + # - name: Run unit tests + # run: yarn test --maxWorkers=2 --coverage build-library: runs-on: ubuntu-latest timeout-minutes: 30 steps: - name: Checkout - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false - name: Setup uses: ./.github/actions/setup @@ -134,19 +187,23 @@ jobs: run: yarn prepare build-android: + needs: changes + if: needs.changes.outputs.android == 'true' runs-on: ubuntu-latest timeout-minutes: 30 env: TURBO_CACHE_DIR: .turbo/android steps: - name: Checkout - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false - name: Setup uses: ./.github/actions/setup - name: Cache turborepo for Android - uses: actions/cache@6f8efc29b200d32929f49075959781ed54ec270c + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: ${{ env.TURBO_CACHE_DIR }} key: ${{ runner.os }}-turborepo-android-${{ hashFiles('yarn.lock') }} @@ -163,7 +220,7 @@ jobs: - name: Install JDK if: env.turbo_cache_hit != 1 - uses: actions/setup-java@e9fbacdec3bb3b6036605a3e6f7995d66773a8c6 + uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1 with: distribution: 'zulu' java-version: '17' @@ -176,7 +233,7 @@ jobs: - name: Cache Gradle if: env.turbo_cache_hit != 1 - uses: actions/cache@6f8efc29b200d32929f49075959781ed54ec270c + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: | ~/.gradle/wrapper @@ -193,7 +250,8 @@ jobs: yarn turbo run build:android --cache-dir="${{ env.TURBO_CACHE_DIR }}" build-ios: - if: github.actor != 'dependabot[bot]' + needs: changes + if: needs.changes.outputs.ios == 'true' && github.actor != 'dependabot[bot]' runs-on: labels: macos-26-xlarge timeout-minutes: 45 @@ -208,11 +266,13 @@ jobs: echo "TOOLCHAINS=com.apple.dt.toolchain.XcodeDefault" >> $GITHUB_ENV - name: Checkout - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false - name: Setup uses: ./.github/actions/setup - + - name: Select XCode 26.5 run: sudo xcode-select -s '/Applications/Xcode_26.5.0.app/Contents/Developer' @@ -222,7 +282,7 @@ jobs: pod --version - name: Cache turborepo for iOS - uses: actions/cache@6f8efc29b200d32929f49075959781ed54ec270c + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: ${{ env.TURBO_CACHE_DIR }} key: ${{ runner.os }}-turborepo-ios-${{ hashFiles('yarn.lock') }} @@ -242,7 +302,7 @@ jobs: - name: Cache cocoapods if: env.turbo_cache_hit != 1 id: cocoapods-cache - uses: actions/cache@6f8efc29b200d32929f49075959781ed54ec270c + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: | **/ios/Pods diff --git a/.github/workflows/license-check.yaml b/.github/workflows/license-check.yaml index cc359be6..ead7159b 100644 --- a/.github/workflows/license-check.yaml +++ b/.github/workflows/license-check.yaml @@ -13,6 +13,10 @@ # limitations under the License. name: Check license headers + +permissions: + contents: read + on: pull_request: push: @@ -24,8 +28,14 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 30 steps: - - uses: actions/checkout@v4 - - uses: actions/setup-go@v5 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 + with: + go-version: 'stable' + # The repo has no Go module, so there is nothing to key a module cache on. + cache: false - name: Install addlicense run: go install github.com/google/addlicense@latest - name: Check license header diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 7573b297..e90a40af 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -15,6 +15,9 @@ # A workflow that publishes the library to CocoaPods name: Publish +permissions: + contents: read + on: workflow_call: # called when release-please steps.release.outputs.release_created workflow_dispatch: # manually trigger if previous runs failed @@ -32,20 +35,21 @@ jobs: needs: build-and-test steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false - name: Setup Node for Dependency Installation - uses: actions/setup-node@v4 + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: 20 - cache: npm - name: Install Dependencies run: npm install # Now configure node with the registry used for publishing - name: Setup Node for Publishing - uses: actions/setup-node@v4 + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: 20 registry-url: 'https://wombat-dressing-room.appspot.com/' diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index 4f81b36e..4a35b6d6 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -43,7 +43,7 @@ jobs: steps: - id: release name: Release Please - uses: googleapis/release-please-action@v4 + uses: googleapis/release-please-action@45996ed1f6d02564a971a2fa1b5860e934307cf7 # v5.0.0 with: token: ${{ secrets.SYNCED_GITHUB_TOKEN_REPO }} diff --git a/AGENTS.md b/AGENTS.md index 8d833aab..0d2bdb86 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -238,10 +238,9 @@ layer before finishing: - Documentation-only changes: validate referenced paths, commands, and diff whitespace; native builds are not necessary. -Do not treat a green CI test job as evidence of runtime coverage: the current -`.github/workflows/ci.yml` test job is a placeholder. There is no root `yarn test` -script. The example has a Jest script, but it is not a substitute for the Detox -build-and-test flow. +CI does not run tests: `.github/workflows/ci.yml` has no test job, and there is +no root `yarn test` script. The example has a Jest script, but it is not a +substitute for the Detox build-and-test flow. ### Detox integration tests From 851bddda9a79f63d0bb941395ce433f20019e77e Mon Sep 17 00:00:00 2001 From: Joonas Kerttula Date: Fri, 18 Sep 2026 14:58:49 +0300 Subject: [PATCH 2/4] ci: address zizmor findings --- .github/workflows/publish.yml | 4 ++++ .github/workflows/release-please.yml | 14 ++++++++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index e90a40af..4fe7d899 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -20,6 +20,10 @@ permissions: on: workflow_call: # called when release-please steps.release.outputs.release_created + secrets: + NPM_WOMBOT_TOKEN: + description: Token for publishing to the npm registry. + required: true workflow_dispatch: # manually trigger if previous runs failed concurrency: diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index 4a35b6d6..133c792b 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -25,19 +25,22 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true -permissions: - contents: write - pull-requests: write +permissions: {} name: Release Please jobs: build-and-test: + permissions: + contents: read uses: ./.github/workflows/ci.yml release-please: runs-on: ubuntu-latest needs: build-and-test + permissions: + contents: write + pull-requests: write outputs: release_ready: ${{ steps.release.outputs.release_created }} steps: @@ -50,5 +53,8 @@ jobs: publish: needs: release-please if: ${{ needs.release-please.outputs.release_ready }} + permissions: + contents: read uses: ./.github/workflows/publish.yml - secrets: inherit + secrets: + NPM_WOMBOT_TOKEN: ${{ secrets.NPM_WOMBOT_TOKEN }} From e51624736ef7f5a75fd8ce89aeea1a26c5a8ac35 Mon Sep 17 00:00:00 2001 From: Joonas Kerttula Date: Fri, 18 Sep 2026 15:05:11 +0300 Subject: [PATCH 3/4] ci: add zizmor ignore comment for npm publish --- .github/workflows/publish.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 4fe7d899..a245ad62 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -59,7 +59,9 @@ jobs: registry-url: 'https://wombat-dressing-room.appspot.com/' - name: Publish - # npm publish will trigger the build via the prepack hook - run: npm publish + # npm publish will trigger the build via the prepack hook. + # Publishing goes through Wombat Dressing Room, which enforces 2FA on a + # bot account, so npm's OIDC trusted publishing does not apply here. + run: npm publish # zizmor: ignore[use-trusted-publishing] env: NODE_AUTH_TOKEN: ${{ secrets.NPM_WOMBOT_TOKEN }} From 1b90edaad43dbff66fd797470914aaec9efaa882 Mon Sep 17 00:00:00 2001 From: Joonas Kerttula Date: Mon, 21 Sep 2026 12:25:03 +0300 Subject: [PATCH 4/4] ci: add back the mandatory test step --- .github/workflows/ci.yml | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 79ac23d7..6d0a67d3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -156,20 +156,15 @@ jobs: run: | find . -name "*.kt" -not -path "*/build/*" | xargs java -jar $HOME/ktfmt/ktfmt.jar --google-style --dry-run --set-exit-if-changed - # There is no test orchestration for Android and iOS yet, and a job that only - # echoes still claims a runner. Restore this once Detox runs on both platforms. - # test: - # runs-on: ubuntu-latest - # timeout-minutes: 30 - # steps: - # - name: Checkout - # uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - # with: - # persist-credentials: false - # - name: Setup - # uses: ./.github/actions/setup - # - name: Run unit tests - # run: yarn test --maxWorkers=2 --coverage + # Required check on the googlemaps organization, so the job has to report a + # status. There is no test orchestration for Android and iOS yet; replace the + # placeholder step once Detox runs on both platforms. + test: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - name: Placeholder test step + run: echo "No tests to run yet" build-library: runs-on: ubuntu-latest