Repository navigation
feat(mcp): one scheduling tool set for agents #568
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Mobile Fingerprint Check | |
| # Detects whether a PR changes the native fingerprint — i.e. whether merging | |
| # it would leave main un-OTA-able until a new store build ships. Native-change | |
| # PRs get the "📱 Native Change" label (applied by mobile-fingerprint-label.yml, | |
| # which runs from main so fork PRs get it too) so they can be held and merged as a | |
| # batch right before the next store submission, keeping main OTA-able for | |
| # everything else in between. (Once one native PR merges, every later merge | |
| # inherits the drifted fingerprint and loses OTA reach too — that is why the | |
| # signal has to fire before merge, not after.) | |
| # | |
| # The check is advisory: it always passes, the label is the signal. Both | |
| # fingerprints are computed in this one job (same OS, same corepack-pinned | |
| # pnpm), so the comparison is self-consistent; no EXPO_TOKEN needed. | |
| on: | |
| pull_request: | |
| # Run even when a rebase or base change removes every native input from the | |
| # diff, so the label can be cleared without installing Expo dependencies. | |
| types: [opened, synchronize, reopened, edited] | |
| concurrency: | |
| group: mobile-fingerprint-check-${{ github.event.pull_request.number }} | |
| cancel-in-progress: true | |
| jobs: | |
| fingerprint: | |
| name: Native fingerprint diff | |
| # The jayleaton/t3code fork has no Blacksmith runners; it uses the GitHub-hosted image. | |
| runs-on: ${{ github.repository == 'jayleaton/t3code' && 'ubuntu-24.04' || 'blacksmith-8vcpu-ubuntu-2404' }} | |
| permissions: | |
| contents: read | |
| env: | |
| APP_VARIANT: production | |
| NODE_OPTIONS: --max-old-space-size=8192 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| with: | |
| # The merge ref can advance after the event is queued. Pin its commit | |
| # and compare against its first parent, rather than the event's base. | |
| ref: ${{ github.sha }} | |
| fetch-depth: 2 | |
| - id: changes | |
| name: Detect native fingerprint inputs | |
| run: | | |
| base_sha=$(git rev-parse HEAD^1) | |
| echo "base_sha=$base_sha" >> "$GITHUB_OUTPUT" | |
| paths=$(git diff --no-renames --name-only "$base_sha" HEAD -- \ | |
| apps/mobile/ packages/client-runtime/ packages/contracts/ packages/shared/ \ | |
| assets/ scripts/ patches/ package.json pnpm-lock.yaml pnpm-workspace.yaml \ | |
| .github/workflows/mobile-fingerprint-check.yml) | |
| if [[ -n "$paths" ]]; then | |
| echo "relevant=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "relevant=false" >> "$GITHUB_OUTPUT" | |
| echo "No native fingerprint inputs changed; clearing any stale native change label." >> "$GITHUB_STEP_SUMMARY" | |
| fi | |
| - name: Setup Vite+ | |
| if: steps.changes.outputs.relevant == 'true' | |
| uses: voidzero-dev/setup-vp@v1 | |
| with: | |
| node-version-file: package.json | |
| cache: true | |
| run-install: | | |
| args: | |
| - --filter=@t3tools/mobile... | |
| - name: Expose pnpm | |
| if: steps.changes.outputs.relevant == 'true' | |
| run: | | |
| pnpm_version="$(node --print "require('./package.json').packageManager.split('@').pop()")" | |
| vp_pnpm_bin="$HOME/.vite-plus/package_manager/pnpm/$pnpm_version/pnpm/bin" | |
| echo "$vp_pnpm_bin" >> "$GITHUB_PATH" | |
| "$vp_pnpm_bin/pnpm" --version | |
| - name: Fingerprint merge result | |
| if: steps.changes.outputs.relevant == 'true' | |
| working-directory: apps/mobile | |
| run: | | |
| mkdir -p "$RUNNER_TEMP/fp/head" "$RUNNER_TEMP/fp/base" | |
| for platform in ios android; do | |
| npx expo-updates fingerprint:generate --platform "$platform" > "$RUNNER_TEMP/fp/head/$platform.json" | |
| done | |
| - name: Fingerprint base | |
| if: steps.changes.outputs.relevant == 'true' | |
| env: | |
| BASE_SHA: ${{ steps.changes.outputs.base_sha }} | |
| run: | | |
| git checkout --quiet "$BASE_SHA" | |
| # Re-sync node_modules to the base commit's lockfile before | |
| # fingerprinting — a dep-changing PR must not fingerprint the base | |
| # against head's installed packages. | |
| pnpm install --filter=@t3tools/mobile... | |
| cd apps/mobile | |
| for platform in ios android; do | |
| npx expo-updates fingerprint:generate --platform "$platform" > "$RUNNER_TEMP/fp/base/$platform.json" | |
| done | |
| - id: compare | |
| name: Compare fingerprints | |
| if: steps.changes.outputs.relevant == 'true' | |
| run: | | |
| changed="" | |
| { | |
| echo "## Native fingerprint diff" | |
| echo | |
| for platform in ios android; do | |
| head_hash="$(jq -r .hash "$RUNNER_TEMP/fp/head/$platform.json")" | |
| base_hash="$(jq -r .hash "$RUNNER_TEMP/fp/base/$platform.json")" | |
| if [ "$head_hash" = "$base_hash" ]; then | |
| echo "- ✅ **$platform**: unchanged (\`$head_hash\`) — OTA-compatible" | |
| continue | |
| fi | |
| changed="$changed $platform" | |
| echo "- 📱 **$platform**: \`$base_hash\` → \`$head_hash\` — merging requires a new native build before OTAs work again" | |
| jq -r -n \ | |
| --slurpfile h "$RUNNER_TEMP/fp/head/$platform.json" \ | |
| --slurpfile b "$RUNNER_TEMP/fp/base/$platform.json" ' | |
| ($b[0].sources | map({ (.filePath // .id): .hash }) | add // {}) as $bm | |
| | $h[0].sources[] | |
| | select($bm[(.filePath // .id)] != .hash) | |
| | " - \(.type): `\(.filePath // .id)`"' | |
| done | |
| } >> "$GITHUB_STEP_SUMMARY" | |
| echo "changed_platforms=${changed# }" >> "$GITHUB_OUTPUT" | |
| # mobile-fingerprint-label.yml reads this from main with a write token | |
| # and syncs the label; this job's token is read-only for fork PRs. | |
| - name: Record changed platforms | |
| env: | |
| CHANGED_PLATFORMS: ${{ steps.compare.outputs.changed_platforms }} | |
| run: | | |
| mkdir -p "$RUNNER_TEMP/fingerprint-result" | |
| printf '%s\n' "$CHANGED_PLATFORMS" > "$RUNNER_TEMP/fingerprint-result/changed-platforms" | |
| - name: Upload changed platforms | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: fingerprint-result | |
| path: ${{ runner.temp }}/fingerprint-result | |
| if-no-files-found: error | |
| retention-days: 1 |