diff --git a/.github/workflows/update-changelogs.yml b/.github/workflows/update-changelogs.yml new file mode 100644 index 00000000000..43fc79acfa1 --- /dev/null +++ b/.github/workflows/update-changelogs.yml @@ -0,0 +1,122 @@ +name: Update Changelogs + +on: + issue_comment: + types: [created] + pull_request: + branches: [main] + types: [opened] + +concurrency: + group: update-changelogs-${{ github.event.issue.number || github.event.pull_request.number }} + cancel-in-progress: true + +permissions: + contents: write + pull-requests: write + +jobs: + is-fork-pull-request: + name: Determine whether this PR is from a fork + if: > + (github.event_name == 'pull_request' && startsWith(github.head_ref, 'release/')) || + (github.event.issue.pull_request && contains(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 }} + + update-changelogs: + name: Update changelogs + needs: is-fork-pull-request + if: ${{ needs.is-fork-pull-request.outputs.IS_FORK == 'false' }} + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - name: React to comment + if: github.event_name == 'issue_comment' + run: gh api "repos/${GITHUB_REPOSITORY}/issues/comments/${COMMENT_ID}/reactions" -f content='+1' + env: + GH_TOKEN: ${{ github.token }} + COMMENT_ID: ${{ github.event.comment.id }} + + - name: Get PR head ref + id: pr + run: | + PR_DATA=$(gh api "repos/${GITHUB_REPOSITORY}/pulls/${PR_NUMBER}" --jq '{ref: .head.ref, sha: .head.sha}') + echo "ref=$(echo "$PR_DATA" | jq -r .ref)" >> "$GITHUB_OUTPUT" + echo "sha=$(echo "$PR_DATA" | jq -r .sha)" >> "$GITHUB_OUTPUT" + env: + GH_TOKEN: ${{ github.token }} + PR_NUMBER: ${{ github.event.issue.number || github.event.pull_request.number }} + + - name: Checkout and setup environment + uses: MetaMask/action-checkout-and-setup@v2 + with: + is-high-risk-environment: false + cache-node-modules: true + node-version: 22.x + ref: ${{ steps.pr.outputs.sha }} + + # Fetch main for --checkDeps base comparison, and the PR branch for push + - name: Checkout PR branch + run: | + git fetch origin main "$PR_REF" + git checkout "$PR_REF" + env: + PR_REF: ${{ steps.pr.outputs.ref }} + + - name: Validate and fix dependency bump entries + id: validate + run: > + yarn workspaces foreach --all --no-private --parallel --interlaced --verbose + run changelog:validate --checkDeps --fix --currentPr "$PR_NUMBER" + continue-on-error: true + env: + PR_NUMBER: ${{ github.event.issue.number || github.event.pull_request.number }} + + - name: Commit and push if changed + id: commit + run: | + if git diff --quiet; then + echo "changed=false" >> "$GITHUB_OUTPUT" + exit 0 + fi + git diff --stat + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git add -- '**/CHANGELOG.md' + git commit -m "chore: auto-fix dependency bump changelog entries" + git push + echo "changed=true" >> "$GITHUB_OUTPUT" + + - name: Comment result + if: always() + run: | + if [ "$CHANGED" = "true" ] && [ "$VALIDATE_OUTCOME" = "failure" ]; then + gh pr comment "$PR_NUMBER" --body "Changelogs updated and pushed, but some validation errors remain. Check the [workflow run]($GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID) for details." + elif [ "$CHANGED" = "true" ]; then + gh pr comment "$PR_NUMBER" --body "Changelogs updated and pushed." + elif [ "$COMMIT_OUTCOME" = "failure" ]; then + gh pr comment "$PR_NUMBER" --body "Failed to push changelog fixes. Check the [workflow run]($GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID) for details." + elif [ "$VALIDATE_OUTCOME" = "failure" ]; then + gh pr comment "$PR_NUMBER" --body "Changelog validation failed. Check the [workflow run]($GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID) for details." + elif [ "$VALIDATE_OUTCOME" = "skipped" ] || [ "$COMMIT_OUTCOME" = "skipped" ]; then + gh pr comment "$PR_NUMBER" --body "Workflow failed before changelog validation. Check the [workflow run]($GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID) for details." + else + gh pr comment "$PR_NUMBER" --body "No changelog changes needed." + fi + env: + GH_TOKEN: ${{ github.token }} + PR_NUMBER: ${{ github.event.issue.number || github.event.pull_request.number }} + CHANGED: ${{ steps.commit.outputs.changed }} + COMMIT_OUTCOME: ${{ steps.commit.outcome }} + VALIDATE_OUTCOME: ${{ steps.validate.outcome }}