Skip to content

Main

Main #3

Workflow file for this run

name: Main
on:
push:
branches:
- main
- stable
- release/*
- trigger-ci-*
pull_request:
types:
- opened
- reopened
- synchronize
branches-ignore:
- stable
merge_group:
schedule:
# Run the full suite "overnight," once every hour from 2:00am UTC until 5:59am UTC.
# This helps with "Top 10 failed tests on the metamask-extension repository main branch,"
# especially the Monday morning list, which is otherwise usually a fake empty.
- cron: '0 2-6 * * *'
concurrency:
group: ${{ github.workflow }}-${{ github.ref == 'refs/heads/main' && github.sha || github.ref }}
cancel-in-progress: ${{ !(contains(github.ref, 'refs/heads/main') || contains(github.ref, 'refs/heads/stable')) }}
env:
# For a `pull_request` event, the branch is `github.head_ref``.
# For a `push` event, the branch is `github.ref_name`.
BRANCH: ${{ github.head_ref || github.ref_name }}
# For a `pull_request` event, the fork is `github.event.pull_request.head.repo.fork`.
# For a `push` event, the fork is `github.event.repository.fork`.
IS_FORK: ${{ github.event.pull_request.head.repo.fork || github.event.repository.fork }}
# For a `pull_request` event, the head commit hash is `github.event.pull_request.head.sha`.
# For a `push` event, the head commit hash is `github.sha`.
HEAD_COMMIT_HASH: ${{ github.event.pull_request.head.sha || github.sha }}
permissions:
contents: write # required for releases
id-token: write # required for s3 uploads
jobs:
get-requirements:
name: Get workflow and job requirements
uses: ./.github/workflows/get-requirements.yml
locales-changed-only:
name: Locales changed only checks
needs:
- get-requirements
if: ${{ needs.get-requirements.outputs.needs-locales == 'true' }}
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout and setup environment
uses: MetaMask/action-checkout-and-setup@v3
with:
is-high-risk-environment: false
skip-allow-scripts: true
- name: lint:prettier (for json,md,mdx,yml files)
run: yarn lint:prettier
- name: Verify locales
run: yarn verify-locales --quiet
prep-deps:
name: Prepare dependencies
if: ${{ needs.get-requirements.outputs.skip-everything != 'true' }}
runs-on: ubuntu-latest
needs:
- get-requirements
timeout-minutes: 30
steps:
- name: Checkout and setup environment
uses: MetaMask/action-checkout-and-setup@v3
id: checkout-and-setup
with:
is-high-risk-environment: false
cache-node-modules: true
skip-allow-scripts: true
# Need to cache `.metamask` folder for the anvil binary
- name: Cache .metamask folder
if: ${{ steps.checkout-and-setup.outputs.node-modules-cache-hit != 'true' }}
uses: actions/cache/save@v5
with:
path: .metamask
key: .metamask-${{ hashFiles('yarn.lock') }}
lint-workflows:
name: Lint workflows
if: ${{ needs.get-requirements.outputs.skip-everything != 'true' }}
needs:
- get-requirements
uses: MetaMask/github-tools/.github/workflows/lint-workflows.yml@v1
test-lint:
name: Test lint
if: ${{ needs.get-requirements.outputs.needs-lint == 'true' }}
needs:
- prep-deps
- get-requirements
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout and setup environment
uses: MetaMask/action-checkout-and-setup@v3
with:
is-high-risk-environment: false
skip-allow-scripts: true
- name: Lint
run: yarn lint
- name: Verify locales
run: yarn verify-locales --quiet
- name: Check circular dependencies
run: yarn circular-deps:check
repository-health-checks:
needs:
- get-requirements
- prep-deps
if: ${{ needs.get-requirements.outputs.skip-everything != 'true' }}
uses: ./.github/workflows/repository-health-checks.yml
test-storybook:
name: Test storybook
needs:
- get-requirements
- prep-deps
if: ${{ needs.get-requirements.outputs.skip-everything != 'true' }}
uses: ./.github/workflows/test-storybook.yml
validate-lavamoat-policies:
needs:
- get-requirements
- prep-deps
if: ${{ needs.get-requirements.outputs.skip-everything != 'true' }}
uses: ./.github/workflows/validate-lavamoat-policies.yml
build-dist-browserify:
needs:
- get-requirements
if: ${{ needs.get-requirements.outputs.skip-everything != 'true' }}
uses: ./.github/workflows/run-build.yml
with:
build-name: build-dist-browserify
build-command: ${{ (github.head_ref || github.ref_name) == 'stable' && 'yarn build prod' || 'yarn build dist' }}
builds-from-run: ${{ needs.get-requirements.outputs.builds-from-run }}
secrets: inherit
build-dist-mv2-browserify:
needs:
- get-requirements
if: ${{ needs.get-requirements.outputs.skip-everything != 'true' }}
uses: ./.github/workflows/run-build.yml
with:
build-name: build-dist-mv2-browserify
build-command: ${{ (github.head_ref || github.ref_name) == 'stable' && 'yarn build prod' || 'yarn build dist' }}
mozilla-lint: true
enable-mv3: false
builds-from-run: ${{ needs.get-requirements.outputs.builds-from-run }}
secrets: inherit
build-beta-browserify:
needs:
- get-requirements
if: ${{ needs.get-requirements.outputs.skip-everything != 'true' }}
uses: ./.github/workflows/run-build.yml
with:
build-name: build-beta-browserify
build-command: yarn build --build-type beta dist
builds-from-run: ${{ needs.get-requirements.outputs.builds-from-run }}
secrets: inherit
build-beta-mv2-browserify:
needs:
- get-requirements
if: ${{ needs.get-requirements.outputs.skip-everything != 'true' }}
uses: ./.github/workflows/run-build.yml
with:
build-name: build-beta-mv2-browserify
build-command: yarn build --build-type beta dist
mozilla-lint: false # Disabled as it is failing for some reason
enable-mv3: false
builds-from-run: ${{ needs.get-requirements.outputs.builds-from-run }}
secrets: inherit
build-flask-browserify:
needs:
- get-requirements
if: ${{ needs.get-requirements.outputs.skip-everything != 'true' }}
uses: ./.github/workflows/run-build.yml
with:
build-name: build-flask-browserify
build-command: ${{ (github.head_ref || github.ref_name) == 'stable' && 'yarn build --build-type flask prod' || 'yarn build --build-type flask dist' }}
builds-from-run: ${{ needs.get-requirements.outputs.builds-from-run }}
secrets: inherit
build-flask-mv2-browserify:
needs:
- get-requirements
if: ${{ needs.get-requirements.outputs.skip-everything != 'true' }}
uses: ./.github/workflows/run-build.yml
with:
build-name: build-flask-mv2-browserify
build-command: ${{ (github.head_ref || github.ref_name) == 'stable' && 'yarn build --build-type flask prod' || 'yarn build --build-type flask dist' }}
mozilla-lint: true
enable-mv3: false
builds-from-run: ${{ needs.get-requirements.outputs.builds-from-run }}
secrets: inherit
build-test-browserify:
needs:
- get-requirements
if: ${{ needs.get-requirements.outputs.skip-everything != 'true' }}
uses: ./.github/workflows/run-build.yml
with:
build-name: build-test-browserify
build-command: yarn build:test
builds-from-run: ${{ needs.get-requirements.outputs.builds-from-run }}
secrets: inherit
build-test-mv2-browserify:
needs:
- get-requirements
if: ${{ needs.get-requirements.outputs.skip-everything != 'true' }}
uses: ./.github/workflows/run-build.yml
with:
build-name: build-test-mv2-browserify
build-command: yarn build:test:mv2
mozilla-lint: false # Disabled as it is failing for some reason
enable-mv3: false
builds-from-run: ${{ needs.get-requirements.outputs.builds-from-run }}
secrets: inherit
build-test-flask-browserify:
needs:
- get-requirements
if: ${{ needs.get-requirements.outputs.skip-everything != 'true' }}
uses: ./.github/workflows/run-build.yml
with:
build-name: build-test-flask-browserify
build-command: yarn build:test:flask
builds-from-run: ${{ needs.get-requirements.outputs.builds-from-run }}
secrets: inherit
build-test-flask-mv2-browserify:
needs:
- get-requirements
if: ${{ needs.get-requirements.outputs.skip-everything != 'true' }}
uses: ./.github/workflows/run-build.yml
with:
build-name: build-test-flask-mv2-browserify
build-command: yarn build:test:flask:mv2
mozilla-lint: false # Disabled as it is failing for some reason
enable-mv3: false
builds-from-run: ${{ needs.get-requirements.outputs.builds-from-run }}
secrets: inherit
build-test-webpack:
needs:
- get-requirements
if: ${{ needs.get-requirements.outputs.skip-everything != 'true' }}
uses: ./.github/workflows/run-build.yml
with:
build-name: build-test-webpack
build-command: yarn build:test:webpack
validate-source-maps: false # Disabled as webpack outputs are not supported by validate-source-maps
builds-from-run: ${{ needs.get-requirements.outputs.builds-from-run }}
secrets: inherit
build-test-mv2-webpack:
needs:
- get-requirements
if: ${{ needs.get-requirements.outputs.skip-everything != 'true' }}
uses: ./.github/workflows/run-build.yml
with:
build-name: build-test-mv2-webpack
build-command: yarn build:test:webpack:mv2
validate-source-maps: false # Disabled as webpack outputs are not supported by validate-source-maps
builds-from-run: ${{ needs.get-requirements.outputs.builds-from-run }}
secrets: inherit
run-benchmarks:
if: ${{ needs.get-requirements.outputs.needs-benchmarks == 'true' }}
uses: ./.github/workflows/run-benchmarks.yml
needs:
- get-requirements
- prep-deps
- build-test-browserify
- build-test-mv2-browserify
- build-test-webpack
- build-test-mv2-webpack
with:
builds-from-run: ${{ needs.get-requirements.outputs.builds-from-run }}
secrets:
INFURA_PROJECT_ID: ${{ secrets.INFURA_PROJECT_ID }}
TEST_SRP_2: ${{ secrets.TEST_SRP_2 }}
run-tests:
name: Run tests
needs:
- get-requirements
- prep-deps
if: ${{ needs.get-requirements.outputs.needs-unit-and-integration == 'true' }}
uses: ./.github/workflows/run-tests.yml
sonarcloud:
name: SonarCloud
needs:
- run-tests
if: >-
${{
!cancelled() &&
(github.event_name == 'pull_request' || (github.event_name == 'push' && github.ref_name == 'main')) &&
needs.run-tests.result == 'success' &&
!(github.event.pull_request.head.repo.fork || github.event.repository.fork)
}}
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Download coverage artifact
uses: actions/download-artifact@v7
with:
name: lcov.info
path: coverage
- name: SonarCloud Scan
# This is SonarSource/sonarqube-scan-action@v7.0.0
uses: SonarSource/sonarqube-scan-action@a31c9398be7ace6bbfaf30c0bd5d415f843d45e9
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
bundle-size:
needs:
- get-requirements
- build-dist-browserify
runs-on: ubuntu-latest
timeout-minutes: 30
env:
EXTENSION_BUNDLESIZE_STATS_TOKEN: ${{ secrets.EXTENSION_BUNDLESIZE_STATS_TOKEN }}
SELENIUM_BROWSER: chrome
steps:
- name: Checkout and setup environment
uses: MetaMask/action-checkout-and-setup@v3
with:
is-high-risk-environment: false
skip-allow-scripts: true
- name: Download artifact 'build-dist-browserify'
uses: actions/download-artifact@v7
with:
name: build-dist-browserify
github-token: ${{ secrets.GITHUB_TOKEN }} # This is required when downloading artifacts from a different repository or from a different workflow run.
run-id: ${{ needs.get-requirements.outputs.builds-from-run }} # Download from whatever run the get-requirements job said.
- name: Measure bundle size
run: yarn tsx test/e2e/mv3-perf-stats/bundle-size.ts --out test-artifacts/chrome
- name: Record bundle size at commit
if: ${{ env.BRANCH == 'main' && env.IS_FORK == 'false'}}
run: ./.github/scripts/bundle-stats-commit.sh
- name: Upload 'bundle-size' to S3
if: ${{ vars.AWS_REGION && vars.AWS_IAM_ROLE && vars.AWS_S3_BUCKET }}
uses: MetaMask/github-tools/.github/actions/upload-s3@v1
with:
aws-region: ${{ vars.AWS_REGION }}
role-to-assume: ${{ vars.AWS_IAM_ROLE }}
s3-bucket: ${{ vars.AWS_S3_BUCKET }}/${{ github.event.repository.name }}/${{ github.run_id }}/bundle-size
path: test-artifacts/chrome
page-load-benchmark:
needs:
- get-requirements
- build-test-browserify
if: ${{ needs.get-requirements.outputs.needs-benchmarks == 'true' }}
uses: ./.github/workflows/page-load-benchmark.yml
secrets:
EXTENSION_BENCHMARK_STATS_TOKEN: ${{ secrets.EXTENSION_BENCHMARK_STATS_TOKEN }}
with:
browser-loads: 10
page-loads: 10
builds-from-run: ${{ needs.get-requirements.outputs.builds-from-run }}
prep-e2e:
needs:
- get-requirements
- prep-deps
if: ${{ needs.get-requirements.outputs.needs-e2e == 'true' }}
uses: ./.github/workflows/prep-e2e.yml
e2e-chrome:
needs:
- get-requirements
- prep-e2e
- build-test-browserify
- build-test-webpack
- build-dist-browserify
- build-test-flask-browserify
uses: ./.github/workflows/e2e-chrome.yml
# Without this `if`, when builds-from-run is activated, the build jobs are considered skipped, and the downstream E2E tests won't run
if: ${{ !cancelled() && needs.get-requirements.outputs.needs-e2e == 'true' && !contains(needs.*.result, 'failure') }}
with:
builds-from-run: ${{ needs.get-requirements.outputs.builds-from-run }}
secrets: inherit
e2e-firefox:
needs:
- get-requirements
- prep-e2e
- build-dist-mv2-browserify
- build-test-mv2-browserify
- build-test-mv2-webpack
- build-test-flask-mv2-browserify
uses: ./.github/workflows/e2e-firefox.yml
# Without this `if`, when builds-from-run is activated, the build jobs are considered skipped, and the downstream E2E tests won't run
if: ${{ !cancelled() && needs.get-requirements.outputs.needs-e2e == 'true' && !contains(needs.*.result, 'failure') }}
with:
builds-from-run: ${{ needs.get-requirements.outputs.builds-from-run }}
secrets:
INFURA_PROJECT_ID: ${{ secrets.INFURA_PROJECT_ID }}
build-storybook:
name: Build storybook
if: ${{ needs.get-requirements.outputs.skip-everything != 'true' }}
needs:
- get-requirements
uses: ./.github/workflows/build-storybook.yml
secrets:
STORYBOOK_TOKEN: ${{ secrets.STORYBOOK_TOKEN }}
build-ts-migration-dashboard:
name: Build ts migration dashboard
if: ${{ github.event_name != 'merge_group' && needs.get-requirements.outputs.skip-everything != 'true' }}
needs:
- get-requirements
uses: ./.github/workflows/build-ts-migration-dashboard.yml
secrets:
TS_MIGRATION_DASHBOARD_TOKEN: ${{ secrets.TS_MIGRATION_DASHBOARD_TOKEN }}
build-source-map-explorer:
needs:
- get-requirements
- prep-deps
- build-dist-browserify
if: ${{ needs.get-requirements.outputs.skip-everything != 'true' && github.event_name != 'merge_group' }}
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout and setup environment
uses: MetaMask/action-checkout-and-setup@v3
with:
is-high-risk-environment: false
skip-allow-scripts: true
- name: Download artifact 'build-dist-browserify'
uses: actions/download-artifact@v7
with:
name: build-dist-browserify
github-token: ${{ secrets.GITHUB_TOKEN }} # This is required when downloading artifacts from a different repository or from a different workflow run.
run-id: ${{ needs.get-requirements.outputs.builds-from-run }} # Download from whatever run the get-requirements job said.
- run: ./development/source-map-explorer.sh
- name: Upload 'source-map-explorer' to S3
if: ${{ vars.AWS_REGION && vars.AWS_IAM_ROLE && vars.AWS_S3_BUCKET }}
uses: MetaMask/github-tools/.github/actions/upload-s3@v1
with:
aws-region: ${{ vars.AWS_REGION }}
role-to-assume: ${{ vars.AWS_IAM_ROLE }}
s3-bucket: ${{ vars.AWS_S3_BUCKET }}/${{ github.event.repository.name }}/${{ github.run_id }}/source-map-explorer
path: build-artifacts/source-map-explorer
build-lavamoat-viz:
needs:
- get-requirements
- prep-deps
- build-dist-browserify
if: ${{ needs.get-requirements.outputs.skip-everything != 'true' }}
runs-on: ubuntu-latest
timeout-minutes: 30
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
INFURA_PROJECT_ID: ${{ secrets.INFURA_PROJECT_ID }}
GOOGLE_PROD_CLIENT_ID: 00000000000
APPLE_PROD_CLIENT_ID: 00000000000
GOOGLE_BETA_CLIENT_ID: 00000000000
APPLE_BETA_CLIENT_ID: 00000000000
GOOGLE_EXPERIMENTAL_CLIENT_ID: 00000000000
APPLE_EXPERIMENTAL_CLIENT_ID: 00000000000
GOOGLE_FLASK_CLIENT_ID: 00000000000
APPLE_FLASK_CLIENT_ID: 00000000000
outputs:
lavamoat-policy-changed: ${{ steps.lavamoat-policy-changed.outputs.lavamoat-policy-changed }}
steps:
- name: Checkout and setup environment
uses: MetaMask/action-checkout-and-setup@v3
with:
is-high-risk-environment: false
skip-allow-scripts: true
- name: Download changed-files artifact
if: ${{ env.BRANCH != 'main' }}
id: download-changed-files
continue-on-error: true
uses: actions/download-artifact@v7
with:
name: changed-files
path: ./changed-files/
# if the changed-files artifact does not exist, we get the diff
- run: yarn tsx .github/scripts/git-diff-default-branch.ts
if: ${{ steps.download-changed-files.outcome == 'failure' }}
- name: See if lavamoat policy files have changed
id: lavamoat-policy-changed
run: |
# if 'changed-files/changed-files.json' exists, check if it contains any files named policy.json or policy-override.json
if [ -f "changed-files/changed-files.json" ]; then
if grep -q -e 'policy.json' -e 'policy-override.json' changed-files/changed-files.json; then
echo "Lavamoat policy file changes detected."
echo "lavamoat-policy-changed=true" >> "$GITHUB_OUTPUT"
else
echo "No Lavamoat policy file changes detected."
echo "lavamoat-policy-changed=false" >> "$GITHUB_OUTPUT"
fi
else
echo "Cannot find 'changed-files.json', assuming that Lavamoat policy files have changed."
echo "lavamoat-policy-changed=true" >> "$GITHUB_OUTPUT"
fi
- name: Download artifact 'build-dist-browserify'
if: ${{ steps.lavamoat-policy-changed.outputs.lavamoat-policy-changed == 'true' }}
uses: actions/download-artifact@v7
with:
name: build-dist-browserify
github-token: ${{ secrets.GITHUB_TOKEN }} # This is required when downloading artifacts from a different repository or from a different workflow run.
run-id: ${{ needs.get-requirements.outputs.builds-from-run }} # Download from whatever run the get-requirements job said.
- run: ./.github/scripts/create-lavamoat-viz.sh
if: ${{ steps.lavamoat-policy-changed.outputs.lavamoat-policy-changed == 'true' }}
- name: Upload 'build-viz' to S3
if: ${{ steps.lavamoat-policy-changed.outputs.lavamoat-policy-changed == 'true' && vars.AWS_REGION && vars.AWS_IAM_ROLE && vars.AWS_S3_BUCKET }}
uses: MetaMask/github-tools/.github/actions/upload-s3@v1
with:
aws-region: ${{ vars.AWS_REGION }}
role-to-assume: ${{ vars.AWS_IAM_ROLE }}
s3-bucket: ${{ vars.AWS_S3_BUCKET }}/${{ github.event.repository.name }}/${{ github.run_id }}/lavamoat-viz
path: build-artifacts/build-viz
publish-prerelease:
name: Publish prerelease
# publish-prerelease when releases are enabled.
#
# This job is sequenced after *all* jobs in `needs`, including benchmarks.
#
# Requirements:
# - For most jobs: result must be `success` or `skipped` (supports the builds-from-run shortcut).
# - For benchmark jobs: result can be anything (failure does not block prerelease),
if: >-
${{
!cancelled() &&
needs.get-requirements.outputs.needs-releases == 'true' &&
contains(fromJson('["success","skipped"]'), needs.build-dist-browserify.result) &&
contains(fromJson('["success","skipped"]'), needs.build-dist-mv2-browserify.result) &&
contains(fromJson('["success","skipped"]'), needs.build-beta-browserify.result) &&
contains(fromJson('["success","skipped"]'), needs.build-beta-mv2-browserify.result) &&
contains(fromJson('["success","skipped"]'), needs.build-flask-browserify.result) &&
contains(fromJson('["success","skipped"]'), needs.build-flask-mv2-browserify.result) &&
contains(fromJson('["success","skipped"]'), needs.build-test-browserify.result) &&
contains(fromJson('["success","skipped"]'), needs.build-test-mv2-browserify.result) &&
contains(fromJson('["success","skipped"]'), needs.build-test-flask-browserify.result) &&
contains(fromJson('["success","skipped"]'), needs.build-test-flask-mv2-browserify.result) &&
contains(fromJson('["success","skipped"]'), needs.bundle-size.result) &&
contains(fromJson('["success","skipped"]'), needs.build-storybook.result) &&
contains(fromJson('["success","skipped"]'), needs.build-ts-migration-dashboard.result) &&
contains(fromJson('["success","skipped"]'), needs.build-source-map-explorer.result) &&
contains(fromJson('["success","skipped"]'), needs.build-lavamoat-viz.result)
}}
needs:
- get-requirements
- build-dist-browserify
- build-dist-mv2-browserify
- build-beta-browserify
- build-beta-mv2-browserify
- build-flask-browserify
- build-flask-mv2-browserify
- build-test-browserify
- build-test-mv2-browserify
- build-test-flask-browserify
- build-test-flask-mv2-browserify
- run-benchmarks
- page-load-benchmark
- bundle-size
- build-storybook
- build-ts-migration-dashboard
- build-source-map-explorer
- build-lavamoat-viz
uses: ./.github/workflows/publish-prerelease.yml
with:
lavamoat-policy-changed: ${{ needs.build-lavamoat-viz.outputs.lavamoat-policy-changed == 'true' }}
post-new-builds: ${{ needs.get-requirements.outputs.builds-from-run == github.run_id }}
secrets: inherit
trigger-regression-validation:
name: Trigger Regression Validation
# Only run for release branches, not forks
if: ${{ (startsWith(github.head_ref || github.ref_name, 'release/') && !(github.event.pull_request.head.repo.fork || github.event.repository.fork)) }}
needs:
- build-dist-browserify
runs-on: ubuntu-latest
timeout-minutes: 5
environment: release-branch
steps:
- name: Trigger regression validation in external repo
env:
DISPATCH_TOKEN: ${{ secrets.METAMASK_REGRESSION_TRIGGER_TEST }}
RUN_ID: ${{ github.run_id }}
run: |
# Extract version from branch name (e.g., release/12.5.0 -> 12.5.0)
# Use BRANCH env var which correctly handles both push and pull_request events
VERSION="${BRANCH#release/}"
echo "Triggering regression validation..."
echo "Run ID: $RUN_ID"
echo "Branch: $BRANCH"
echo "Version: $VERSION"
echo "Commit SHA: $HEAD_COMMIT_HASH"
curl -X POST \
-H "Accept: application/vnd.github.v3+json" \
-H "Authorization: token $DISPATCH_TOKEN" \
https://api.github.com/repos/MetaMask/extension-regression-validation-poc/dispatches \
-d '{
"event_type": "release_pr_updated",
"client_payload": {
"run_id": "'"$RUN_ID"'",
"version": "'"$VERSION"'",
"branch": "'"$BRANCH"'",
"commit_sha": "'"$HEAD_COMMIT_HASH"'"
}
}'
echo "Regression validation triggered successfully"
all-jobs-pass:
name: All jobs pass
if: ${{ !cancelled() }}
runs-on: ubuntu-latest
timeout-minutes: 2
# We list every job we want to validate in `needs`, because `needs` only contains results for jobs explicitly
# named here. A failing job can cause downstream jobs to be `skipped`, which can hide the true failure unless
# the upstream job is also included.
#
# For instance, if prep-e2e fails, e2e-chrome and e2e-firefox are skipped, so we need the direct result of prep-e2e.
#
# Jobs intentionally excluded:
# - Publish jobs (not required for CI pass)
# - Jobs that depend on all-jobs-pass (e.g., log-merge-group-failure) cannot be included here
needs:
- get-requirements
- locales-changed-only
- prep-deps
- lint-workflows
- test-lint
- repository-health-checks
- test-storybook
- validate-lavamoat-policies
- build-dist-browserify
- build-dist-mv2-browserify
- build-beta-browserify
- build-beta-mv2-browserify
- build-flask-browserify
- build-flask-mv2-browserify
- build-test-browserify
- build-test-mv2-browserify
- build-test-flask-browserify
- build-test-flask-mv2-browserify
- build-test-webpack
- build-test-mv2-webpack
- run-benchmarks
- run-tests
- bundle-size
- page-load-benchmark
- prep-e2e
- e2e-chrome
- e2e-firefox
- build-storybook
- build-ts-migration-dashboard
- build-source-map-explorer
- build-lavamoat-viz
- trigger-regression-validation
steps:
- name: Check that all jobs have passed
env:
NEEDS_JSON: ${{ toJson(needs) }} # This is required for the the job_result lookup and the job_id loop
BUILDS_FROM_RUN: ${{ needs.get-requirements.outputs.builds-from-run }}
RUN_ID: ${{ github.run_id }}
run: |
# Function to ensure a job's result is either 'success' or 'skipped'
requireJobSuccessOrSkipped() {
local job_id="$1"
local job_result="$2"
if [[ -z "$job_result" ]]; then
echo "Could not determine result for job: $job_id"
exit 1
fi
if [[ "$job_result" != "skipped" && "$job_result" != "success" ]]; then
echo "$job_id did not succeed (result: $job_result)"
exit 1
fi
}
# Loop through each job in the needs array to ensure it succeeded or was skipped
while IFS=$'\t' read -r job_id job_result; do
# job_result is effectively `needs[$job_id].result`
requireJobSuccessOrSkipped "$job_id" "$job_result"
done < <(
jq -r 'to_entries[] | [.key, (.value.result // "")] | @tsv' <<<"$NEEDS_JSON"
)
# # Check if the builds-from-run output is the current run ID
if [[ "$BUILDS_FROM_RUN" != "$RUN_ID" ]]; then
echo "Builds were used from a different GHA run: $BUILDS_FROM_RUN"
echo "Right now you can use this feature to test and iterate faster, but to merge a PR, you have to disable it."
exit 1
fi
echo "All required jobs either passed or were skipped"
- name: Log merge group failure
if: ${{ github.event_name == 'merge_group' && failure() && !github.event.repository.fork }}
uses: MetaMask/github-tools/.github/actions/log-merge-group-failure@v1
with:
google-application-credentials: ${{ secrets.GOOGLE_APPLICATION_CREDENTIALS }}
google-service-account: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }}
spreadsheet-id: ${{ secrets.GOOGLE_MERGE_QUEUE_SPREADSHEET_ID }}
sheet-name: ${{ secrets.GOOGLE_MERGE_QUEUE_SHEET_NAME }}
publish-release:
name: Publish release
if: ${{ !cancelled() && needs.all-jobs-pass.result == 'success' && github.event_name == 'push' && github.ref_name == 'stable' && needs.get-requirements.outputs.needs-releases == 'true' }}
needs:
- get-requirements
- all-jobs-pass
uses: ./.github/workflows/publish-release.yml
secrets: inherit