mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 01:47:00 +01:00
feat: github actions to automatically create and close bug report issue (#20391)
* feat(action): github action to create bug report issue at RC cut * feat(action): github action to close bug report issue once release is ready * fix(action): replace main by master * fix(action): create event does not support branch filter * fix(action): indentation * fix(action): actionlint erors * fix(action): actionlint erors 2 * fix(action): actionlint erors 3 * fix(action): replace npm by yarn for consistency
This commit is contained in:
parent
ca1ddeb59b
commit
23249b68b7
120
.github/scripts/close-release-bug-report-issue.ts
vendored
Normal file
120
.github/scripts/close-release-bug-report-issue.ts
vendored
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
import * as core from '@actions/core';
|
||||||
|
import { context, getOctokit } from '@actions/github';
|
||||||
|
import { GitHub } from '@actions/github/lib/utils';
|
||||||
|
|
||||||
|
main().catch((error: Error): void => {
|
||||||
|
console.error(error);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
async function main(): Promise<void> {
|
||||||
|
// "GITHUB_TOKEN" is an automatically generated, repository-specific access token provided by GitHub Actions.
|
||||||
|
// We can't use "GITHUB_TOKEN" here, as its permissions are scoped to the repository where the action is running.
|
||||||
|
// "GITHUB_TOKEN" does not have access to other repositories, even when they belong to the same organization.
|
||||||
|
// As we want to update bug report issues which are not located in the same repository,
|
||||||
|
// we need to create our own "BUG_REPORT_TOKEN" with "repo" permissions.
|
||||||
|
// Such a token allows to access other repositories of the MetaMask organisation.
|
||||||
|
const personalAccessToken = process.env.BUG_REPORT_TOKEN;
|
||||||
|
if (!personalAccessToken) {
|
||||||
|
core.setFailed('BUG_REPORT_TOKEN not found');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const repoOwner = context.repo.owner; // MetaMask
|
||||||
|
|
||||||
|
const bugReportRepo = process.env.BUG_REPORT_REPO;
|
||||||
|
if (!bugReportRepo) {
|
||||||
|
core.setFailed('BUG_REPORT_REPO not found');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract branch name from the context
|
||||||
|
const branchName: string = context.payload.pull_request?.head.ref || "";
|
||||||
|
|
||||||
|
// Extract semver version number from the branch name
|
||||||
|
const releaseVersionNumberMatch = branchName.match(/^Version-v(\d+\.\d+\.\d+)$/);
|
||||||
|
|
||||||
|
if (!releaseVersionNumberMatch) {
|
||||||
|
core.setFailed(`Failed to extract version number from branch name: ${branchName}`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const releaseVersionNumber = releaseVersionNumberMatch[1];
|
||||||
|
|
||||||
|
// Initialise octokit, required to call Github GraphQL API
|
||||||
|
const octokit: InstanceType<typeof GitHub> = getOctokit(personalAccessToken);
|
||||||
|
|
||||||
|
const bugReportIssue = await retrieveOpenBugReportIssue(octokit, repoOwner, bugReportRepo, releaseVersionNumber);
|
||||||
|
|
||||||
|
if (!bugReportIssue) {
|
||||||
|
throw new Error(`No open bug report issue was found for release ${releaseVersionNumber} on ${repoOwner}/${bugReportRepo} repo`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bugReportIssue.title?.toLocaleLowerCase() !== `v${releaseVersionNumber} Bug Report`.toLocaleLowerCase()) {
|
||||||
|
throw new Error(`Unexpected bug report title: "${bugReportIssue.title}" instead of "v${releaseVersionNumber} Bug Report"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`Closing bug report issue with title "${bugReportIssue.title}" and id: ${bugReportIssue.id}`);
|
||||||
|
|
||||||
|
await closeIssue(octokit, bugReportIssue.id);
|
||||||
|
|
||||||
|
console.log(`Issue with id: ${bugReportIssue.id} successfully closed`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function retrieves the issue titled "vx.y.z Bug Report" on a specific repo
|
||||||
|
async function retrieveOpenBugReportIssue(octokit: InstanceType<typeof GitHub>, repoOwner: string, repoName: string, releaseVersionNumber: string): Promise<{
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
} | undefined> {
|
||||||
|
|
||||||
|
const retrieveOpenBugReportIssueQuery = `
|
||||||
|
query RetrieveOpenBugReportIssue {
|
||||||
|
search(query: "repo:${repoOwner}/${repoName} type:issue is:open in:title v${releaseVersionNumber} Bug Report", type: ISSUE, first: 1) {
|
||||||
|
nodes {
|
||||||
|
... on Issue {
|
||||||
|
id
|
||||||
|
title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const retrieveOpenBugReportIssueQueryResult: {
|
||||||
|
search: {
|
||||||
|
nodes: {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
}[];
|
||||||
|
};
|
||||||
|
} = await octokit.graphql(retrieveOpenBugReportIssueQuery);
|
||||||
|
|
||||||
|
const bugReportIssues = retrieveOpenBugReportIssueQueryResult?.search?.nodes;
|
||||||
|
|
||||||
|
return bugReportIssues?.length > 0 ? bugReportIssues[0] : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This function closes a Github issue, based on its ID
|
||||||
|
async function closeIssue(octokit: InstanceType<typeof GitHub>, issueId: string): Promise<string> {
|
||||||
|
|
||||||
|
const closeIssueMutation = `
|
||||||
|
mutation CloseIssue($issueId: ID!) {
|
||||||
|
updateIssue(input: {id: $issueId, state: CLOSED}) {
|
||||||
|
clientMutationId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const closeIssueMutationResult: {
|
||||||
|
updateIssue: {
|
||||||
|
clientMutationId: string;
|
||||||
|
};
|
||||||
|
} = await octokit.graphql(closeIssueMutation, {
|
||||||
|
issueId,
|
||||||
|
});
|
||||||
|
|
||||||
|
const clientMutationId = closeIssueMutationResult?.updateIssue?.clientMutationId;
|
||||||
|
|
||||||
|
return clientMutationId;
|
||||||
|
}
|
2
.github/workflows/add-release-label.yml
vendored
2
.github/workflows/add-release-label.yml
vendored
@ -37,4 +37,4 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
RELEASE_LABEL_TOKEN: ${{ secrets.RELEASE_LABEL_TOKEN }}
|
RELEASE_LABEL_TOKEN: ${{ secrets.RELEASE_LABEL_TOKEN }}
|
||||||
NEXT_SEMVER_VERSION: ${{ env.NEXT_SEMVER_VERSION }}
|
NEXT_SEMVER_VERSION: ${{ env.NEXT_SEMVER_VERSION }}
|
||||||
run: npm run add-release-label-to-pr-and-linked-issues
|
run: yarn run add-release-label-to-pr-and-linked-issues
|
||||||
|
2
.github/workflows/check-pr-labels.yml
vendored
2
.github/workflows/check-pr-labels.yml
vendored
@ -35,4 +35,4 @@ jobs:
|
|||||||
id: check-pr-has-required-labels
|
id: check-pr-has-required-labels
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
run: npm run check-pr-has-required-labels
|
run: yarn run check-pr-has-required-labels
|
||||||
|
34
.github/workflows/close-bug-report.yml
vendored
Normal file
34
.github/workflows/close-bug-report.yml
vendored
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
name: Close release bug report issue when release branch gets merged
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
types:
|
||||||
|
- closed
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
close-bug-report:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: github.event.pull_request.merged == true && startsWith(github.event.pull_request.head.ref, 'Version-v')
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
fetch-depth: 1 # This retrieves only the latest commit.
|
||||||
|
|
||||||
|
- name: Set up Node.js
|
||||||
|
uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version-file: '.nvmrc'
|
||||||
|
cache: yarn
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: yarn --immutable
|
||||||
|
|
||||||
|
- name: Close release bug report issue
|
||||||
|
id: close-release-bug-report-issue
|
||||||
|
env:
|
||||||
|
BUG_REPORT_REPO: MetaMask-planning
|
||||||
|
BUG_REPORT_TOKEN: ${{ secrets.BUG_REPORT_TOKEN }}
|
||||||
|
run: yarn run close-release-bug-report-issue
|
47
.github/workflows/create-bug-report.yml
vendored
Normal file
47
.github/workflows/create-bug-report.yml
vendored
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
name: Create release bug report issue when release branch gets created
|
||||||
|
|
||||||
|
on: create
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
create-bug-report:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Extract version from branch name if release branch
|
||||||
|
id: extract_version
|
||||||
|
run: |
|
||||||
|
if [[ "$GITHUB_REF" == "refs/heads/Version-v"* ]]; then
|
||||||
|
version="${GITHUB_REF#refs/heads/Version-v}"
|
||||||
|
echo "New release branch($version), continue next steps"
|
||||||
|
echo "version=$version" >> "$GITHUB_ENV"
|
||||||
|
else
|
||||||
|
echo "Not a release branch, skip next steps"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Create bug report issue on planning repo
|
||||||
|
if: env.version
|
||||||
|
uses: octokit/request-action@v2.x
|
||||||
|
with:
|
||||||
|
route: POST /repos/MetaMask/MetaMask-planning/issues
|
||||||
|
owner: MetaMask
|
||||||
|
title: v${{ env.version }} Bug Report
|
||||||
|
body: |
|
||||||
|
This bug report was automatically created by a GitHub action upon the creation of release branch `Version-v${{ env.version }}` (release cut).
|
||||||
|
|
||||||
|
|
||||||
|
**Expected actions for release engineers:**
|
||||||
|
|
||||||
|
1. Convert this issue into a Zenhub epic and link all bugs identified during the release regression testing phase to this epic.
|
||||||
|
|
||||||
|
2. After completing the first regression run, move this epic to "Regression Completed" on the [Extension Release Regression board](https://app.zenhub.com/workspaces/extension-release-regression-6478c62d937eaa15e95c33c5/board?filterLogic=any&labels=release-${{ env.version }},release-task).
|
||||||
|
|
||||||
|
|
||||||
|
Note that once the release is prepared for store submission, meaning the `Version-v${{ env.version }}` branch merges into `master`, another GitHub action will automatically close this epic.
|
||||||
|
|
||||||
|
labels: |
|
||||||
|
[
|
||||||
|
"type-bug",
|
||||||
|
"regression-RC",
|
||||||
|
"release-${{ env.version }}"
|
||||||
|
]
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.BUG_REPORT_TOKEN }}
|
@ -98,6 +98,7 @@
|
|||||||
"validate-branch-name": "validate-branch-name",
|
"validate-branch-name": "validate-branch-name",
|
||||||
"add-release-label-to-pr-and-linked-issues": "ts-node ./.github/scripts/add-release-label-to-pr-and-linked-issues.ts",
|
"add-release-label-to-pr-and-linked-issues": "ts-node ./.github/scripts/add-release-label-to-pr-and-linked-issues.ts",
|
||||||
"check-pr-has-required-labels": "ts-node ./.github/scripts/check-pr-has-required-labels.ts",
|
"check-pr-has-required-labels": "ts-node ./.github/scripts/check-pr-has-required-labels.ts",
|
||||||
|
"close-release-bug-report-issue": "ts-node ./.github/scripts/close-release-bug-report-issue.ts",
|
||||||
"audit": "yarn npm audit --recursive --environment production --severity moderate"
|
"audit": "yarn npm audit --recursive --environment production --severity moderate"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
|
Loading…
Reference in New Issue
Block a user