Skip to content

Commit

Permalink
ci: Migrate metamaskbot PR comment (#29373)
Browse files Browse the repository at this point in the history
## **Description**

Migrate the `metamaskbot` PR comment from CircleCI to GitHub Actions.
CircleCI is still used for artifact storage for linked artifacts.

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/29373?quickstart=1)

## **Related issues**

Relates to #28572

These changes were extracted from #29256

## **Manual testing steps**

* Test that all links in the `metamaskbot` comment work correctly,
except those that are already broken. Links already broken on `main`
include:
  * Some build links (fixed in #29403 ):
    - Beta builds
    - Firefox test build, and Firefox flask-test build
  * MV3 performance stats reports (fixed in #29408 ):
    * mv3: Background Module Init Stats (link works, page is broken)
    * mv3: UI Init Stats (link works, page is broken)
    * mv3: Module Load Stats (link works, page is broken)
  * Coverage report (fixed by #29410)
  * mv3 bundle size stats (fixed by #29486)

## **Screenshots/Recordings**

N/A

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
  • Loading branch information
Gudahtt authored Jan 9, 2025
1 parent 2d443ff commit 87c524e
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 44 deletions.
8 changes: 0 additions & 8 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1331,14 +1331,6 @@ jobs:
- store_artifacts:
path: development/ts-migration-dashboard/build/final
destination: ts-migration-dashboard
- run:
name: Set branch parent commit env var
command: |
echo "export PARENT_COMMIT=$(git merge-base origin/HEAD HEAD)" >> $BASH_ENV
source $BASH_ENV
- run:
name: build:announce
command: ./development/metamaskbot-build-announce.js

job-publish-release:
executor: node-browsers-small
Expand Down
9 changes: 9 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,15 @@ jobs:
name: Wait for CircleCI workflow status
uses: ./.github/workflows/wait-for-circleci-workflow-status.yml

publish-prerelease:
name: Publish prerelease
if: ${{ github.event_name == 'pull_request' }}
needs:
- wait-for-circleci-workflow-status
uses: ./.github/workflows/publish-prerelease.yml
secrets:
PR_COMMENT_TOKEN: ${{ secrets.PR_COMMENT_TOKEN }}

all-jobs-completed:
name: All jobs completed
runs-on: ubuntu-latest
Expand Down
72 changes: 72 additions & 0 deletions .github/workflows/publish-prerelease.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
name: Publish prerelease

on:
workflow_call:
secrets:
PR_COMMENT_TOKEN:
required: true

jobs:
publish-prerelease:
name: Publish prerelease
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0 # This is needed to get merge base to calculate bundle size diff

- name: Setup environment
uses: metamask/github-tools/.github/actions/setup-environment@main

- name: Get merge base commit hash
id: get-merge-base
env:
BASE_REF: ${{ github.event.pull_request.base.ref }}
run: |
merge_base="$(git merge-base "origin/${BASE_REF}" HEAD)"
echo "Merge base is '${merge_base}'"
echo "MERGE_BASE=${merge_base}" >> "$GITHUB_OUTPUT"
- name: Get CircleCI job details
id: get-circleci-job-details
env:
REPOSITORY: ${{ github.repository }}
BRANCH: ${{ github.head_ref }}
HEAD_COMMIT_HASH: ${{ github.event.pull_request.head.sha }}
run: |
pipeline_id=$(curl --silent "https://circleci.com/api/v2/project/gh/$OWNER/$REPOSITORY/pipeline?branch=$BRANCH" | jq -r ".items | map(select(.vcs.revision == \"${HEAD_COMMIT_HASH}\" )) | first | .id")
workflow_id=$(curl --silent "https://circleci.com/api/v2/pipeline/$pipeline_id/workflow" | jq -r ".items[0].id")
job_details=$(curl --silent "https://circleci.com/api/v2/workflow/$workflow_id/job" | jq -r '.items[] | select(.name == "job-publish-prerelease")')
build_num=$(echo "$job_details" | jq -r '.job_number')
echo 'CIRCLE_BUILD_NUM='"$build_num" >> "$GITHUB_OUTPUT"
job_id=$(echo "$job_details" | jq -r '.id')
echo 'CIRCLE_WORKFLOW_JOB_ID='"$job_id" >> "$GITHUB_OUTPUT"
echo "Getting artifacts from pipeline '${pipeline_id}', workflow '${workflow_id}', build number '${build_num}', job ID '${job_id}'"
- name: Get CircleCI job artifacts
env:
CIRCLE_WORKFLOW_JOB_ID: ${{ steps.get-circleci-job-details.outputs.CIRCLE_WORKFLOW_JOB_ID }}
run: |
mkdir -p "test-artifacts/chrome/benchmark"
curl --silent --location "https://output.circle-artifacts.com/output/job/${CIRCLE_WORKFLOW_JOB_ID}/artifacts/0/test-artifacts/chrome/benchmark/pageload.json" > "test-artifacts/chrome/benchmark/pageload.json"
bundle_size=$(curl --silent --location "https://output.circle-artifacts.com/output/job/${CIRCLE_WORKFLOW_JOB_ID}/artifacts/0/test-artifacts/chrome/bundle_size.json")
mkdir -p "test-artifacts/chrome"
echo "${bundle_size}" > "test-artifacts/chrome/bundle_size.json"
stories=$(curl --silent --location "https://output.circle-artifacts.com/output/job/${CIRCLE_WORKFLOW_JOB_ID}/artifacts/0/storybook/stories.json")
mkdir "storybook-build"
echo "${stories}" > "storybook-build/stories.json"
- name: Publish prerelease
env:
PR_COMMENT_TOKEN: ${{ secrets.PR_COMMENT_TOKEN }}
PR_NUMBER: ${{ github.event.pull_request.number }}
HEAD_COMMIT_HASH: ${{ github.event.pull_request.head.sha }}
MERGE_BASE_COMMIT_HASH: ${{ steps.get-merge-base.outputs.MERGE_BASE }}
CIRCLE_BUILD_NUM: ${{ steps.get-circleci-job-details.outputs.CIRCLE_BUILD_NUM }}
CIRCLE_WORKFLOW_JOB_ID: ${{ steps.get-circleci-job-details.outputs.CIRCLE_WORKFLOW_JOB_ID }}
run: ./development/metamaskbot-build-announce.js
2 changes: 1 addition & 1 deletion development/highlights/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ async function getHighlights({ artifactBase }) {
// here we assume the PR base branch ("target") is `main` in lieu of doing
// a query against the github api which requires an access token
// see https://discuss.circleci.com/t/how-to-retrieve-a-pull-requests-base-branch-name-github/36911
const changedFiles = await getChangedFiles({ target: 'main' });
const changedFiles = await getChangedFiles({ target: 'origin/main' });
console.log(`detected changed files vs main:`);
for (const filename of changedFiles) {
console.log(` ${filename}`);
Expand Down
81 changes: 46 additions & 35 deletions development/metamaskbot-build-announce.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ const path = require('path');
// Fetch is part of node js in future versions, thus triggering no-shadow
// eslint-disable-next-line no-shadow
const fetch = require('node-fetch');
const glob = require('fast-glob');
const VERSION = require('../package.json').version;
const { getHighlights } = require('./highlights');

Expand Down Expand Up @@ -38,29 +37,41 @@ function getPercentageChange(from, to) {
return parseFloat(((to - from) / Math.abs(from)) * 100).toFixed(2);
}

/**
* Check whether an artifact exists,
*
* @param {string} url - The URL of the artifact to check.
* @returns True if the artifact exists, false if it doesn't
*/
async function artifactExists(url) {
// Using a regular GET request here rather than HEAD because for some reason CircleCI always
// returns 404 for HEAD requests.
const response = await fetch(url);
return response.ok;
}

async function start() {
const {
GITHUB_COMMENT_TOKEN,
CIRCLE_PULL_REQUEST,
CIRCLE_SHA1,
PR_COMMENT_TOKEN,
PR_NUMBER,
HEAD_COMMIT_HASH,
MERGE_BASE_COMMIT_HASH,
CIRCLE_BUILD_NUM,
CIRCLE_WORKFLOW_JOB_ID,
PARENT_COMMIT,
} = process.env;

console.log('CIRCLE_PULL_REQUEST', CIRCLE_PULL_REQUEST);
console.log('CIRCLE_SHA1', CIRCLE_SHA1);
console.log('PR_NUMBER', PR_NUMBER);
console.log('HEAD_COMMIT_HASH', HEAD_COMMIT_HASH);
console.log('MERGE_BASE_COMMIT_HASH', MERGE_BASE_COMMIT_HASH);
console.log('CIRCLE_BUILD_NUM', CIRCLE_BUILD_NUM);
console.log('CIRCLE_WORKFLOW_JOB_ID', CIRCLE_WORKFLOW_JOB_ID);
console.log('PARENT_COMMIT', PARENT_COMMIT);

if (!CIRCLE_PULL_REQUEST) {
console.warn(`No pull request detected for commit "${CIRCLE_SHA1}"`);
if (!PR_NUMBER) {
console.warn(`No pull request detected for commit "${HEAD_COMMIT_HASH}"`);
return;
}

const CIRCLE_PR_NUMBER = CIRCLE_PULL_REQUEST.split('/').pop();
const SHORT_SHA1 = CIRCLE_SHA1.slice(0, 7);
const SHORT_SHA1 = HEAD_COMMIT_HASH.slice(0, 7);
const BUILD_LINK_BASE = `https://output.circle-artifacts.com/output/job/${CIRCLE_WORKFLOW_JOB_ID}/artifacts/0`;
// build the github comment content

Expand Down Expand Up @@ -96,30 +107,30 @@ async function start() {

// links to bundle browser builds
const bundles = {};
const fileType = '.html';
const sourceMapRoot = '/build-artifacts/source-map-explorer/';
const bundleFiles = await glob(`.${sourceMapRoot}*${fileType}`);

bundleFiles.forEach((bundleFile) => {
const fileName = bundleFile.split(sourceMapRoot)[1];
const bundleName = fileName.split(fileType)[0];
const url = `${BUILD_LINK_BASE}${sourceMapRoot}${fileName}`;
let fileRoot = bundleName;
let fileIndex = bundleName.match(/-[0-9]{1,}$/u)?.index;

if (fileIndex) {
fileRoot = bundleName.slice(0, fileIndex);
fileIndex = bundleName.slice(fileIndex + 1, bundleName.length);
}

const link = `<a href="${url}">${fileIndex || fileRoot}</a>`;
const fileRoots = [
'background',
'common',
'ui',
'content-script',
'offscreen',
];

if (fileRoot in bundles) {
for (const fileRoot of fileRoots) {
bundles[fileRoot] = [];
let fileIndex = 0;
let url = `${BUILD_LINK_BASE}${sourceMapRoot}${fileRoot}-${fileIndex}.html`;
console.log(`Verifying ${url}`);
while (await artifactExists(url)) {
const link = `<a href="${url}">${fileIndex}</a>`;
bundles[fileRoot].push(link);
} else {
bundles[fileRoot] = [link];

fileIndex += 1;
url = `${BUILD_LINK_BASE}${sourceMapRoot}${fileRoot}-${fileIndex}.html`;
console.log(`Verifying ${url}`);
}
});
console.log(`Not found: ${url}`);
}

const bundleMarkup = `<ul>${Object.keys(bundles)
.map((key) => `<li>${key}: ${bundles[key].join(', ')}</li>`)
Expand Down Expand Up @@ -295,7 +306,7 @@ async function start() {
};

const devSizes = Object.keys(prSizes).reduce((sizes, part) => {
sizes[part] = devBundleSizeStats[PARENT_COMMIT][part] || 0;
sizes[part] = devBundleSizeStats[MERGE_BASE_COMMIT_HASH][part] || 0;
return sizes;
}, {});

Expand Down Expand Up @@ -346,7 +357,7 @@ async function start() {
}

const JSON_PAYLOAD = JSON.stringify({ body: commentBody });
const POST_COMMENT_URI = `https://api.github.com/repos/metamask/metamask-extension/issues/${CIRCLE_PR_NUMBER}/comments`;
const POST_COMMENT_URI = `https://api.github.com/repos/metamask/metamask-extension/issues/${PR_NUMBER}/comments`;
console.log(`Announcement:\n${commentBody}`);
console.log(`Posting to: ${POST_COMMENT_URI}`);

Expand All @@ -355,7 +366,7 @@ async function start() {
body: JSON_PAYLOAD,
headers: {
'User-Agent': 'metamaskbot',
Authorization: `token ${GITHUB_COMMENT_TOKEN}`,
Authorization: `token ${PR_COMMENT_TOKEN}`,
},
});
if (!response.ok) {
Expand Down

0 comments on commit 87c524e

Please sign in to comment.