diff --git a/.github/workflows/publish-preview.yml b/.github/workflows/publish-preview.yml index f591a0b894f..dbc39f6f5b2 100644 --- a/.github/workflows/publish-preview.yml +++ b/.github/workflows/publish-preview.yml @@ -5,103 +5,11 @@ on: types: created jobs: - is-fork-pull-request: - name: Determine whether this issue comment was on a pull request from a fork - if: ${{ github.event.issue.pull_request && startsWith(github.event.comment.body, '@metamaskbot publish-preview') }} - runs-on: ubuntu-latest - outputs: - IS_FORK: ${{ steps.is-fork.outputs.IS_FORK }} - steps: - - uses: actions/checkout@v5 - - name: Determine whether this PR is from a fork - id: is-fork - run: echo "IS_FORK=$(gh pr view --json isCrossRepository --jq '.isCrossRepository' "${PR_NUMBER}" )" >> "$GITHUB_OUTPUT" - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - PR_NUMBER: ${{ github.event.issue.number }} - - build-preview: - name: Build preview - needs: is-fork-pull-request - if: ${{ needs.is-fork-pull-request.outputs.IS_FORK == 'false' }} - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v5 - - name: Check out pull request - run: gh pr checkout "${PR_NUMBER}" - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - PR_NUMBER: ${{ github.event.issue.number }} - - name: Checkout and setup environment - uses: MetaMask/action-checkout-and-setup@v2 - with: - is-high-risk-environment: true - - name: Get commit SHA - id: commit-sha - run: echo "COMMIT_SHA=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT" - - run: yarn prepare-preview-builds @metamask-previews ${{ steps.commit-sha.outputs.COMMIT_SHA }} - - run: yarn build - - name: Upload build artifacts - uses: actions/upload-artifact@v6 - with: - name: preview-build-artifacts - include-hidden-files: true - retention-days: 4 - path: | - ./yarn.lock - ./package.json - ./packages/*/ - !./packages/*/node_modules/ - !./packages/*/src/ - !./packages/*/tests/ - !./packages/**/*.test.* - publish-preview: - name: Publish preview - needs: build-preview - permissions: - pull-requests: write - environment: default-branch - runs-on: ubuntu-latest - steps: - - name: Checkout and setup environment - uses: MetaMask/action-checkout-and-setup@v2 - with: - is-high-risk-environment: true - - name: Restore build artifacts - uses: actions/download-artifact@v7 - with: - name: preview-build-artifacts - # The artifact package.json files come from the PR branch. - # A malicious PR could inject lifecycle scripts (prepack/postpack) that - # execute during `yarn npm publish` with the NPM token in the environment - # (enableScripts: false does NOT prevent pack/publish lifecycle scripts). - # It could also override publishConfig.registry to exfiltrate the token. - - name: Validate artifact manifests - run: | - bad=0 - for f in packages/**/package.json; do - if jq -e '.scripts // {} | keys[] | select(test("^(pre|post)(pack|publish)"))' "$f" > /dev/null 2>&1; then - echo "::error::Forbidden lifecycle script in $f" - bad=1 - fi - reg=$(jq -r '.publishConfig.registry // ""' "$f") - if [[ -n "$reg" && "$reg" != "https://registry.npmjs.org/" ]]; then - echo "::error::Unexpected registry in $f: $reg" - bad=1 - fi - done - exit "$bad" - - name: Reconcile workspace state - run: yarn install --no-immutable - - name: Publish preview builds - run: yarn workspaces foreach --no-private --all exec yarn npm publish --tag preview - env: - YARN_NPM_AUTH_TOKEN: ${{ secrets.PUBLISH_PREVIEW_NPM_TOKEN }} - - name: Generate preview build message - run: yarn tsx scripts/generate-preview-build-message.ts - - name: Post build preview in comment - run: gh pr comment "${PR_NUMBER}" --body-file preview-build-message.txt - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - PR_NUMBER: ${{ github.event.issue.number }} + if: ${{ github.event.issue.pull_request && startsWith(github.event.comment.body, '@metamaskbot publish-preview') }} + uses: MetaMask/github-tools/.github/workflows/publish-preview.yml@prepare-preview-builds-action + with: + environment: default-branch + docs-url: 'https://github.com/MetaMask/core/blob/main/docs/processes/preview-builds.md' + secrets: + PUBLISH_PREVIEW_NPM_TOKEN: ${{ secrets.PUBLISH_PREVIEW_NPM_TOKEN }} diff --git a/package.json b/package.json index 4078304ca15..a281201bc41 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,6 @@ "lint:misc": "prettier --no-error-on-unmatched-pattern '**/*.json' '**/*.md' '**/*.yml' '!.yarnrc.yml' '!merged-packages/**' --ignore-path .gitignore", "lint:teams": "tsx scripts/lint-teams-json.ts", "prepack": "./scripts/prepack.sh", - "prepare-preview-builds": "./scripts/prepare-preview-builds.sh", "setup": "yarn install", "test": "yarn test:scripts --silent --collectCoverage=false --reporters=jest-silent-reporter && yarn test:packages", "test:clean": "yarn workspaces foreach --all --parallel --verbose run test:clean && yarn test", diff --git a/scripts/prepare-preview-builds.jq b/scripts/prepare-preview-builds.jq deleted file mode 100644 index a523e49fb8d..00000000000 --- a/scripts/prepare-preview-builds.jq +++ /dev/null @@ -1,9 +0,0 @@ -# The name is overwritten, causing the package to get published under a -# different NPM scope than non-preview builds. -.name |= sub("@metamask/"; "\($npm_scope)/") | - -# The prerelease version is overwritten, preserving the non-prerelease portion -# of the version. Technically we'd want to bump the non-prerelease portion as -# well if we wanted this to be SemVer-compliant, but it was simpler not to. -# This is just for testing, it doesn't need to strictly follow SemVer. -.version |= split("-")[0] + "-preview-\($hash)" diff --git a/scripts/prepare-preview-builds.sh b/scripts/prepare-preview-builds.sh deleted file mode 100755 index bae0c32070b..00000000000 --- a/scripts/prepare-preview-builds.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -# This script prepares a package to be published as a preview build -# to GitHub Packages. - -if [[ $# -eq 0 ]]; then - echo "Missing commit hash." - exit 1 -fi - -# We don't want to assume that preview builds will be published alongside -# "production" versions. There are security- and aesthetic-based advantages to -# keeping them separate. -npm_scope="$1" - -# We use the short commit hash as the prerelease version. This ensures each -# preview build is unique and can be linked to a specific commit. -shorthash="$2" - -prepare-preview-manifest() { - local manifest_file="$1" - - # jq does not support in-place modification of files, so a temporary file is - # used to store the result of the operation. The original file is then - # overwritten with the temporary file. - jq --raw-output --arg npm_scope "$npm_scope" --arg hash "$shorthash" --from-file scripts/prepare-preview-builds.jq "$manifest_file" > temp.json - mv temp.json "$manifest_file" -} - -# Add resolutions to the root manifest so that @metamask/* imports continue -# to resolve from the local workspace after packages are renamed to the -# preview scope. Without this, yarn resolves @metamask/* from the npm -# registry, which causes build failures when workspace packages contain -# type changes not yet published. -echo "Adding workspace resolutions to root manifest..." -resolutions="$(yarn workspaces list --no-private --json \ - | jq --slurp 'reduce .[] as $pkg ({}; .[$pkg.name] = "portal:./" + $pkg.location)')" -jq --argjson resolutions "$resolutions" '.resolutions = ((.resolutions // {}) + $resolutions)' package.json > temp.json -mv temp.json package.json - -echo "Preparing manifests..." -while IFS=$'\t' read -r location name; do - echo "- $name" - prepare-preview-manifest "$location/package.json" -done < <(yarn workspaces list --no-private --json | jq --slurp --raw-output 'map(select(.location != ".")) | map([.location, .name]) | map(@tsv) | .[]') - -echo "Installing dependencies..." -yarn install --no-immutable