diff --git a/.github/workflows/ci-namespace-shadow.yml b/.github/workflows/ci-namespace-shadow.yml index b2e6dfab78b..38af88e32e2 100644 --- a/.github/workflows/ci-namespace-shadow.yml +++ b/.github/workflows/ci-namespace-shadow.yml @@ -8,9 +8,16 @@ name: CI (Namespace shadow) # token-exchange, and dispatch steps use continue-on-error so this job's own # check always concludes success even when the dispatch cannot run. # -# Shadow runs are iOS-only: ci.yml skips Android and Linux-only jobs when -# runner_provider is namespace (see the BITRISE/NAMESPACE-SHADOW markers there), -# mirroring the Bitrise shadow benchmark scope. +# A shadow run is composed of two independently-flagged pipelines inside ci.yml +# (see the BITRISE/NAMESPACE-SHADOW markers there): +# - iOS pipeline (build + E2E smoke on macOS runners): runs when +# NAMESPACE_SHADOW_AUTO_DISPATCH=true +# - Linux pipeline (lint/unit/scripts/etc. on namespace-profile-metamask-ci-linux, +# plus Android build + E2E smoke on namespace-profile-metamask-android-build): +# runs when NAMESPACE_SHADOW_LINUX_AUTO_DISPATCH=true +# Appium Android stays skipped on shadow runs (pinned to Cirrus until Namespace parity). +# With both flags false, a manual dispatch yields a near-empty ci.yml run (only +# provider-agnostic scaffolding like get_requirements / fingerprint / timings). # # Authentication: Token Exchange Service (same pattern as triage-forwarder.yml — # OIDC → POST /api/exchange/token). Prerequisites: @@ -18,8 +25,9 @@ name: CI (Namespace shadow) # - Rego policy mm-metamask-mobile-namespace-shadow-ci-token-exchange in # token-exchange-service (matches the OIDC `workflow_ref` claim). # -# Auto-dispatch gate: set repo Actions variable NAMESPACE_SHADOW_AUTO_DISPATCH=true -# to dispatch on PR/push. Default (unset/false) = manual workflow_dispatch only. +# Auto-dispatch gate: PR/push dispatch happens when NAMESPACE_SHADOW_AUTO_DISPATCH=true +# or NAMESPACE_SHADOW_LINUX_AUTO_DISPATCH=true (repo Actions variables). Default +# (both unset/false) = manual workflow_dispatch only. on: pull_request: types: [opened, synchronize, reopened, ready_for_review] @@ -44,10 +52,11 @@ jobs: name: "[shadow] Dispatch" runs-on: ubuntu-latest # Fork PRs use head.repo != github.repository — skip (no shadow, no token exchange). - # PR/push auto-dispatch requires NAMESPACE_SHADOW_AUTO_DISPATCH=true; workflow_dispatch always runs. + # PR/push auto-dispatch requires NAMESPACE_SHADOW_AUTO_DISPATCH=true (iOS pipeline) + # or NAMESPACE_SHADOW_LINUX_AUTO_DISPATCH=true (Linux pipeline); workflow_dispatch always runs. if: >- ${{ - (github.event_name == 'workflow_dispatch' || vars.NAMESPACE_SHADOW_AUTO_DISPATCH == 'true') && + (github.event_name == 'workflow_dispatch' || vars.NAMESPACE_SHADOW_AUTO_DISPATCH == 'true' || vars.NAMESPACE_SHADOW_LINUX_AUTO_DISPATCH == 'true') && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) }} steps: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f97656e62f4..41669bf04d7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -62,7 +62,8 @@ jobs: check-diff: name: Check diff runs-on: ${{ inputs.runner_provider == 'namespace' && 'namespace-profile-metamask-ios-build' || 'macos-latest' }} - if: ${{ needs.get_requirements.outputs.skip_everything != 'true' }} + # NAMESPACE-SHADOW: macOS job — runs on Namespace shadow only when NAMESPACE_SHADOW_AUTO_DISPATCH=true (iOS pipeline) + if: ${{ needs.get_requirements.outputs.skip_everything != 'true' && (inputs.runner_provider != 'namespace' || vars.NAMESPACE_SHADOW_AUTO_DISPATCH == 'true') }} needs: - get_requirements steps: @@ -170,8 +171,8 @@ jobs: dedupe: name: Dedupe runs-on: ${{ inputs.runner_provider == 'namespace' && 'namespace-profile-metamask-ci-linux' || 'ubuntu-latest' }} - # BITRISE/NAMESPACE-SHADOW: skip for iOS-only shadow benchmark (INFRA-3679) — revert to enable full pipeline - if: ${{ needs.get_requirements.outputs.skip_everything != 'true' && inputs.runner_provider != 'bitrise' && inputs.runner_provider != 'namespace' }} + # BITRISE/NAMESPACE-SHADOW: skipped on Bitrise shadow (iOS-only, INFRA-3679); Namespace shadow runs this Linux job only when NAMESPACE_SHADOW_LINUX_AUTO_DISPATCH=true + if: ${{ needs.get_requirements.outputs.skip_everything != 'true' && inputs.runner_provider != 'bitrise' && (inputs.runner_provider != 'namespace' || vars.NAMESPACE_SHADOW_LINUX_AUTO_DISPATCH == 'true') }} needs: - get_requirements steps: @@ -219,8 +220,8 @@ jobs: git-safe-dependencies: name: Run `@lavamoat/git-safe-dependencies` runs-on: ${{ inputs.runner_provider == 'namespace' && 'namespace-profile-metamask-ci-linux' || 'ubuntu-latest' }} - # BITRISE/NAMESPACE-SHADOW: skip for iOS-only shadow benchmark (INFRA-3679) — revert to enable full pipeline - if: ${{ needs.get_requirements.outputs.skip_everything != 'true' && inputs.runner_provider != 'bitrise' && inputs.runner_provider != 'namespace' }} + # BITRISE/NAMESPACE-SHADOW: skipped on Bitrise shadow (iOS-only, INFRA-3679); Namespace shadow runs this Linux job only when NAMESPACE_SHADOW_LINUX_AUTO_DISPATCH=true + if: ${{ needs.get_requirements.outputs.skip_everything != 'true' && inputs.runner_provider != 'bitrise' && (inputs.runner_provider != 'namespace' || vars.NAMESPACE_SHADOW_LINUX_AUTO_DISPATCH == 'true') }} needs: - get_requirements steps: @@ -261,8 +262,8 @@ jobs: scripts: name: Run `${{ matrix.scripts }}` runs-on: ${{ inputs.runner_provider == 'namespace' && 'namespace-profile-metamask-ci-linux' || 'ubuntu-latest' }} - # BITRISE/NAMESPACE-SHADOW: skip for iOS-only shadow benchmark (INFRA-3679) — revert to enable full pipeline - if: ${{ needs.get_requirements.outputs.skip_everything != 'true' && inputs.runner_provider != 'bitrise' && inputs.runner_provider != 'namespace' }} + # BITRISE/NAMESPACE-SHADOW: skipped on Bitrise shadow (iOS-only, INFRA-3679); Namespace shadow runs this Linux job only when NAMESPACE_SHADOW_LINUX_AUTO_DISPATCH=true + if: ${{ needs.get_requirements.outputs.skip_everything != 'true' && inputs.runner_provider != 'bitrise' && (inputs.runner_provider != 'namespace' || vars.NAMESPACE_SHADOW_LINUX_AUTO_DISPATCH == 'true') }} needs: - get_requirements strategy: @@ -321,8 +322,8 @@ jobs: js-bundle-size-check: name: JS bundle size check runs-on: ${{ inputs.runner_provider == 'namespace' && 'namespace-profile-metamask-ci-linux' || 'ubuntu-latest' }} - # BITRISE/NAMESPACE-SHADOW: skip for iOS-only shadow benchmark (INFRA-3679) — revert to enable full pipeline - if: ${{ needs.get_requirements.outputs.skip_everything != 'true' && inputs.runner_provider != 'bitrise' && inputs.runner_provider != 'namespace' }} + # BITRISE/NAMESPACE-SHADOW: skipped on Bitrise shadow (iOS-only, INFRA-3679); Namespace shadow runs this Linux job only when NAMESPACE_SHADOW_LINUX_AUTO_DISPATCH=true + if: ${{ needs.get_requirements.outputs.skip_everything != 'true' && inputs.runner_provider != 'bitrise' && (inputs.runner_provider != 'namespace' || vars.NAMESPACE_SHADOW_LINUX_AUTO_DISPATCH == 'true') }} needs: - get_requirements permissions: @@ -634,8 +635,8 @@ jobs: check-workflows: name: Check workflows runs-on: ${{ inputs.runner_provider == 'namespace' && 'namespace-profile-metamask-ci-linux' || 'ubuntu-latest' }} - # BITRISE/NAMESPACE-SHADOW: skip for iOS-only shadow benchmark (INFRA-3679) — revert to enable full pipeline - if: ${{ needs.get_requirements.outputs.skip_everything != 'true' && inputs.runner_provider != 'bitrise' && inputs.runner_provider != 'namespace' }} + # BITRISE/NAMESPACE-SHADOW: skipped on Bitrise shadow (iOS-only, INFRA-3679); Namespace shadow runs this Linux job only when NAMESPACE_SHADOW_LINUX_AUTO_DISPATCH=true + if: ${{ needs.get_requirements.outputs.skip_everything != 'true' && inputs.runner_provider != 'bitrise' && (inputs.runner_provider != 'namespace' || vars.NAMESPACE_SHADOW_LINUX_AUTO_DISPATCH == 'true') }} needs: - get_requirements steps: @@ -656,8 +657,8 @@ jobs: prepare-ci-js-deps: name: Prepare CI JS dependencies runs-on: ${{ inputs.runner_provider == 'namespace' && 'namespace-profile-metamask-ci-linux' || 'ubuntu-latest' }} - # BITRISE/NAMESPACE-SHADOW: skip for iOS-only shadow benchmark (INFRA-3679) — revert to enable full pipeline - if: ${{ needs.get_requirements.outputs.skip_everything != 'true' && inputs.runner_provider != 'bitrise' && inputs.runner_provider != 'namespace' }} + # BITRISE/NAMESPACE-SHADOW: skipped on Bitrise shadow (iOS-only, INFRA-3679); Namespace shadow runs this Linux job only when NAMESPACE_SHADOW_LINUX_AUTO_DISPATCH=true + if: ${{ needs.get_requirements.outputs.skip_everything != 'true' && inputs.runner_provider != 'bitrise' && (inputs.runner_provider != 'namespace' || vars.NAMESPACE_SHADOW_LINUX_AUTO_DISPATCH == 'true') }} needs: - get_requirements steps: @@ -683,8 +684,8 @@ jobs: unit-tests: name: Unit tests (${{ matrix.shard }}) runs-on: ${{ inputs.runner_provider == 'namespace' && 'namespace-profile-metamask-ci-linux' || 'ubuntu-latest' }} - # BITRISE/NAMESPACE-SHADOW: skip for iOS-only shadow benchmark (INFRA-3679) — revert to enable full pipeline - if: ${{ !cancelled() && needs.get_requirements.result == 'success' && needs.get_requirements.outputs.skip_everything != 'true' && inputs.runner_provider != 'bitrise' && inputs.runner_provider != 'namespace' }} + # BITRISE/NAMESPACE-SHADOW: skipped on Bitrise shadow (iOS-only, INFRA-3679); Namespace shadow runs this Linux job only when NAMESPACE_SHADOW_LINUX_AUTO_DISPATCH=true + if: ${{ !cancelled() && needs.get_requirements.result == 'success' && needs.get_requirements.outputs.skip_everything != 'true' && inputs.runner_provider != 'bitrise' && (inputs.runner_provider != 'namespace' || vars.NAMESPACE_SHADOW_LINUX_AUTO_DISPATCH == 'true') }} needs: - get_requirements - prepare-ci-js-deps @@ -764,7 +765,8 @@ jobs: - integration-tests # Wait for integration shards so coverage can merge into Sonar, but still run # when integration fails — missing integration artifacts are tolerated below. - if: ${{ always() && github.event_name != 'merge_group' && inputs.runner_provider != 'bitrise' && inputs.runner_provider != 'namespace' && !cancelled() && needs.prepare-ci-js-deps.result == 'success' && needs.unit-tests.result == 'success' && needs.component-view-tests.result == 'success' }} + # BITRISE/NAMESPACE-SHADOW: skipped on Bitrise shadow (iOS-only, INFRA-3679); Namespace shadow runs this Linux job only when NAMESPACE_SHADOW_LINUX_AUTO_DISPATCH=true + if: ${{ always() && github.event_name != 'merge_group' && inputs.runner_provider != 'bitrise' && (inputs.runner_provider != 'namespace' || vars.NAMESPACE_SHADOW_LINUX_AUTO_DISPATCH == 'true') && !cancelled() && needs.prepare-ci-js-deps.result == 'success' && needs.unit-tests.result == 'success' && needs.component-view-tests.result == 'success' }} steps: - uses: namespacelabs/nscloud-checkout-action@938f5d2d403d6224d9a0c0dc559b1dae09c2ede4 # v8.1.1 if: ${{ inputs.runner_provider == 'namespace' }} @@ -1032,8 +1034,8 @@ jobs: component-view-tests: name: Component view tests runs-on: ${{ inputs.runner_provider == 'namespace' && 'namespace-profile-metamask-ci-linux' || 'ubuntu-latest' }} - # BITRISE/NAMESPACE-SHADOW: skip for iOS-only shadow benchmark (INFRA-3679) — revert to enable full pipeline - if: ${{ !cancelled() && needs.get_requirements.result == 'success' && needs.get_requirements.outputs.skip_everything != 'true' && inputs.runner_provider != 'bitrise' && inputs.runner_provider != 'namespace' }} + # BITRISE/NAMESPACE-SHADOW: skipped on Bitrise shadow (iOS-only, INFRA-3679); Namespace shadow runs this Linux job only when NAMESPACE_SHADOW_LINUX_AUTO_DISPATCH=true + if: ${{ !cancelled() && needs.get_requirements.result == 'success' && needs.get_requirements.outputs.skip_everything != 'true' && inputs.runner_provider != 'bitrise' && (inputs.runner_provider != 'namespace' || vars.NAMESPACE_SHADOW_LINUX_AUTO_DISPATCH == 'true') }} needs: - get_requirements - prepare-ci-js-deps @@ -1099,7 +1101,8 @@ jobs: integration-tests: name: Integration tests runs-on: ${{ inputs.runner_provider == 'namespace' && 'namespace-profile-metamask-ci-linux' || 'ubuntu-latest' }} - if: ${{ !cancelled() && needs.get_requirements.result == 'success' && needs.get_requirements.outputs.skip_everything != 'true' }} + # BITRISE/NAMESPACE-SHADOW: skipped on Bitrise shadow (iOS-only, INFRA-3679); Namespace shadow runs this Linux job only when NAMESPACE_SHADOW_LINUX_AUTO_DISPATCH=true + if: ${{ !cancelled() && needs.get_requirements.result == 'success' && needs.get_requirements.outputs.skip_everything != 'true' && inputs.runner_provider != 'bitrise' && (inputs.runner_provider != 'namespace' || vars.NAMESPACE_SHADOW_LINUX_AUTO_DISPATCH == 'true') }} needs: - get_requirements - prepare-ci-js-deps @@ -1248,11 +1251,11 @@ jobs: build-android-apks: name: 'Build Android APKs' - # BITRISE/NAMESPACE-SHADOW: skip for iOS-only shadow benchmark (INFRA-3679) — revert to enable full pipeline + # BITRISE/NAMESPACE-SHADOW: skipped on Bitrise shadow (iOS-only, INFRA-3679); Namespace shadow runs this Linux-runner job only when NAMESPACE_SHADOW_LINUX_AUTO_DISPATCH=true if: >- ${{ inputs.runner_provider != 'bitrise' && - inputs.runner_provider != 'namespace' && + (inputs.runner_provider != 'namespace' || vars.NAMESPACE_SHADOW_LINUX_AUTO_DISPATCH == 'true') && !cancelled() && needs.get_requirements.outputs.android_e2e_needed == 'true' && !(fromJSON(needs.smart-e2e-selection.outputs.ai_confidence || '0') >= 85 && needs.smart-e2e-selection.outputs.ai_e2e_test_tags == '[]') @@ -1326,11 +1329,11 @@ jobs: e2e-smoke-tests-android: name: 'Android E2E Smoke Tests' - # BITRISE/NAMESPACE-SHADOW: skip for iOS-only shadow benchmark (INFRA-3679) — revert to enable full pipeline + # BITRISE/NAMESPACE-SHADOW: skipped on Bitrise shadow (iOS-only, INFRA-3679); Namespace shadow runs this Linux-runner job only when NAMESPACE_SHADOW_LINUX_AUTO_DISPATCH=true if: >- ${{ inputs.runner_provider != 'bitrise' && - inputs.runner_provider != 'namespace' && + (inputs.runner_provider != 'namespace' || vars.NAMESPACE_SHADOW_LINUX_AUTO_DISPATCH == 'true') && !cancelled() && needs.build-android-apks.result == 'success' && (needs.prepare-e2e-timings.result == 'success' || needs.prepare-e2e-timings.result == 'failure' || needs.prepare-e2e-timings.result == 'skipped') @@ -1352,9 +1355,12 @@ jobs: build-ios-apps: name: 'Build iOS Apps' + # NAMESPACE-SHADOW: iOS pipeline runs on Namespace shadow only when NAMESPACE_SHADOW_AUTO_DISPATCH=true + # (downstream iOS jobs cascade-skip via needs when this is skipped) if: >- ${{ !cancelled() && + (inputs.runner_provider != 'namespace' || vars.NAMESPACE_SHADOW_AUTO_DISPATCH == 'true') && needs.get_requirements.outputs.ios_e2e_needed == 'true' && !(fromJSON(needs.smart-e2e-selection.outputs.ai_confidence || '0') >= 85 && needs.smart-e2e-selection.outputs.ai_e2e_test_tags == '[]') }} @@ -1406,7 +1412,9 @@ jobs: appium-smoke-tests-android: name: 'Appium Smoke Tests (Android)' - # BITRISE/NAMESPACE-SHADOW: skip for iOS-only shadow benchmark (INFRA-3679) — revert to enable full pipeline + # BITRISE/NAMESPACE-SHADOW: always skipped on shadow runs. Appium Android is pinned to + # runner_provider=current (Cirrus) below until Namespace parity is ready, and it cannot + # download namespace-built APKs (they live in Namespace's artifact store, not GitHub's). if: >- ${{ inputs.runner_provider != 'bitrise' &&