Skip to content

[pull] main from MetaMask:main #45

[pull] main from MetaMask:main

[pull] main from MetaMask:main #45

name: Update Changelogs
on:
issue_comment:
types:
- created
pull_request_target:
branches:
- main
types:
- opened
- ready_for_review
permissions:
contents: write
pull-requests: write
jobs:
is-fork:
name: Determine whether this PR is from a fork
if: (github.event_name == 'pull_request_target' && !github.event.pull_request.draft) || (github.event.issue.pull_request && startsWith(github.event.comment.body, '@metamaskbot update-changelogs'))
runs-on: ubuntu-latest
outputs:
is-fork: ${{ steps.is-fork.outputs.is-fork }}
steps:
- name: Determine whether this PR is from a fork
id: is-fork
run: |
IS_FORK="$(gh pr view --json isCrossRepository --jq '.isCrossRepository' "$PR_NUMBER" --repo "$GITHUB_REPOSITORY")"
echo "is-fork=$IS_FORK" >> "$GITHUB_OUTPUT"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ github.event.issue.number || github.event.pull_request.number }}
is-release:
name: Determine whether this PR is a release PR
needs: is-fork
if: needs.is-fork.outputs.is-fork == 'false'
runs-on: ubuntu-latest
environment: default-branch
outputs:
is-release: ${{ steps.is-release.outputs.IS_RELEASE }}
head-sha: ${{ steps.pr-info.outputs.pr-head-sha }}
head-ref: ${{ steps.pr-info.outputs.pr-head-ref }}
base-ref: ${{ steps.pr-info.outputs.pr-base-ref }}
merge-base: ${{ steps.merge-base.outputs.merge-base }}
steps:
- name: Get pull request info
id: pr-info
env:
GH_TOKEN: ${{ secrets.UPDATE_CHANGELOG_TOKEN }}
PR_NUMBER: ${{ github.event.issue.number || github.event.pull_request.number }}
run: |
gh pr view "$PR_NUMBER" \
--repo "$GITHUB_REPOSITORY" \
--json baseRefName,headRefOid,headRefName,title \
--jq '"pr-base-ref=\(.baseRefName)\npr-head-sha=\(.headRefOid)\npr-head-ref=\(.headRefName)\npr-title=\(.title)"' \
>> "$GITHUB_OUTPUT"
- name: Checkout repository
uses: actions/checkout@v6
with:
token: ${{ secrets.GITHUB_TOKEN }}
fetch-depth: 0
ref: ${{ steps.pr-info.outputs.pr-head-sha }}
- name: Get merge base
id: merge-base
shell: bash
env:
BASE_REF: ${{ steps.pr-info.outputs.pr-base-ref }}
run: |
set -euo pipefail
MERGE_BASE=$(git merge-base HEAD "refs/remotes/origin/$BASE_REF")
echo "merge-base=$MERGE_BASE" >> "$GITHUB_OUTPUT"
- name: Check if the pull request is a release
id: is-release
uses: MetaMask/action-is-release@v2
with:
commit-starts-with: ${{ vars.RELEASE_COMMIT_PREFIX }}
commit-message: ${{ steps.pr-info.outputs.pr-title }}
before: ${{ steps.merge-base.outputs.merge-base }}
skip-checkout: true
react-to-comment:
name: React to the comment
needs: is-release
if: needs.is-release.outputs.is-release == 'true' && github.event_name == 'issue_comment'
runs-on: ubuntu-latest
environment: default-branch
continue-on-error: true
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: React to the comment
run: |
gh api \
--method POST \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
"/repos/${REPO}/issues/comments/${COMMENT_ID}/reactions" \
-f content='+1'
env:
COMMENT_ID: ${{ github.event.comment.id }}
GH_TOKEN: ${{ secrets.UPDATE_CHANGELOG_TOKEN }}
REPO: ${{ github.repository }}
update-changelogs:
name: Update changelogs
needs: is-release
if: ${{ needs.is-release.outputs.is-release == 'true' }}
runs-on: ubuntu-latest
environment: default-branch
steps:
- name: Check out the base branch
uses: actions/checkout@v6
with:
ref: ${{ needs.is-release.outputs.merge-base }}
token: ${{ secrets.UPDATE_CHANGELOG_TOKEN }}
- name: Detach HEAD (to prevent accidental pushes)
run: git checkout --detach HEAD
- name: Set up environment
uses: MetaMask/action-checkout-and-setup@v3
with:
is-high-risk-environment: false
- name: Overlay relevant files from current pull request
env:
PR_HEAD_SHA: ${{ needs.is-release.outputs.head-sha }}
PR_HEAD_REF: ${{ needs.is-release.outputs.head-ref }}
run: |
# These next two commands are also useful later when pushing
git fetch --no-tags origin "$PR_HEAD_SHA"
git fetch --no-tags origin "$PR_HEAD_REF"
git checkout "$PR_HEAD_SHA" -- '**/CHANGELOG.md' '**/package.json'
shell: bash
- name: Configure Git with name and email
run: |
# This is necessary to make a commit
# Passing `token` to the `checkout` action does not do this for us
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
shell: bash
- name: Commit relevant files from current pull request
run: |
git add -- '**/CHANGELOG.md' '**/package.json'
git commit -m "[Temporary] Add changelogs from current pull request"
shell: bash
- name: Ensure required dependency bump entries exist across all changelogs
id: update-changelogs
env:
PR_NUMBER: ${{ github.event.issue.number || github.event.pull_request.number }}
MERGE_BASE: ${{ needs.is-release.outputs.merge-base }}
run: |
yarn changelog:validate --checkDeps --fix --currentPr "$PR_NUMBER" --fromRef "$MERGE_BASE"
shell: bash
# If changelogs were updated but there were other validation errors
# found, we need to still create a commit below
continue-on-error: true
- name: Commit updated changelogs
id: commit-updated-changelogs
run: |
if git diff --quiet; then
# Nothing to commit; no changelogs updated
exit 0
fi
git add -- '**/CHANGELOG.md'
git commit -m "chore: Update dependency bump changelog entries"
new_commit_id="$(git log -1 --pretty='format:%H')"
echo "new-commit-id=${new_commit_id}" >> "$GITHUB_OUTPUT"
shell: bash
- name: Cherry-pick new commit on top of pull request branch and push it
id: push-changes
env:
NEW_COMMIT_ID: ${{ steps.commit-updated-changelogs.outputs.new-commit-id }}
PR_HEAD_SHA: ${{ needs.is-release.outputs.head-sha }}
PR_HEAD_REF: ${{ needs.is-release.outputs.head-ref }}
run: |
if [[ -n "$NEW_COMMIT_ID" ]]; then
git checkout "$PR_HEAD_SHA"
git cherry-pick "$NEW_COMMIT_ID"
git push origin "HEAD:$PR_HEAD_REF"
echo "changes-pushed=true" >> "$GITHUB_OUTPUT"
else
echo "changes-pushed=false" >> "$GITHUB_OUTPUT"
fi
shell: bash
- name: Comment result
if: always()
uses: actions/github-script@v9
env:
CHANGES_PUSHED: ${{ steps.push-changes.outputs.changes-pushed }}
PUSH_CHANGES_OUTCOME: ${{ steps.push-changes.outcome }}
UPDATE_CHANGELOGS_OUTCOME: ${{ steps.update-changelogs.outcome }}
PR_NUMBER: ${{ github.event.issue.number || github.event.pull_request.number }}
with:
github-token: ${{ secrets.UPDATE_CHANGELOG_TOKEN }}
script: |
const {
CHANGES_PUSHED,
PUSH_CHANGES_OUTCOME,
UPDATE_CHANGELOGS_OUTCOME,
PR_NUMBER,
} = process.env;
// List and minimize any existing changelog update comments.
const comments = await github.paginate(github.rest.issues.listComments, {
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: process.env.PR_NUMBER,
});
for (const comment of comments) {
if (comment.body.includes('<!-- Changelog update comment -->')) {
await github.graphql(`
mutation($commentId: ID!, $classifier: ReportedContentClassifiers!) {
minimizeComment(input: {subjectId: $commentId, classifier: $classifier}) {
minimizedComment {
isMinimized
}
}
}
`, {
commentId: comment.node_id,
classifier: 'OUTDATED',
});
}
}
function getCommentBody() {
if (CHANGES_PUSHED === 'true' && UPDATE_CHANGELOGS_OUTCOME === 'failure') {
return `⚠️ Changelogs updated and pushed, but some validation errors remain. Check the [workflow run](${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}) for details.`;
} else if (CHANGES_PUSHED === 'true') {
return '✅ Changelogs updated and pushed.';
} else if (PUSH_CHANGES_OUTCOME === 'failure') {
return `❌ Failed to push changelog fixes. Check the [workflow run](${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}) for details.`;
} else if (UPDATE_CHANGELOGS_OUTCOME === 'failure') {
return `❌ Changelog validation failed. Check the [workflow run](${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}) for details.`;
} else if (UPDATE_CHANGELOGS_OUTCOME === 'skipped' || PUSH_CHANGES_OUTCOME === 'skipped') {
return `❌ Workflow failed before changelog validation. Check the [workflow run](${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}) for details.`;
} else {
return '✅ No changelog changes needed.';
}
}
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: process.env.PR_NUMBER,
body: `${getCommentBody()}\n\n<!-- Changelog update comment -->`,
});