Cherry pick CFE and PRR flow to release/9.4 (#52710)

* New CFE flow (#51182)

* Create changelog during build step

* removed changelog generation during code freeze step

* lint fixes

* modified monorepo messaging

* Added changelog

* added workflow dispatch

* version override

* renamed file

* New CFE workflow (#51207)

* New CFE workflow

* added slack notifications

* lint fixes

* continue workflow only if the label is present

* Bump to github scripts v7

* Moved notification to core releases daily channel

* New CFE workflow notifications (#51466)

* New CFE workflow notifications

* added notification for woo release slack channel

* add woo core daily slack channel

* remove github debug

* change notification channel to Woo core releases

* New CFE workflow GitHub template (#51468)

* New CFE github template

* review changes

* review changes

* CFE - added strict check for PR and release number extracted from issue body (#52002)

* Init

* comment tweak

* changelog

* use gihub recommended method

* removed content write permission

* change in how to extract PR number

* regex change

* template updates

* updated comments

* set global permission to empty and moved it within each job

* refactored code, created a needs step

* add condition to prep

* added acknowdegement section

* added github comment

* Moved variables to env

* review changes

* PRR flow (#52160)

* init

* comment tweak

* changelog

* use gihub recommended method

* removed content write permission

* change in how to extract PR number

* change in how to extract PR number

* change in how to extract PR number

* regex change

* regex change

* template updates

* updated comments

* set global permission to empty and moved it within each job

* refactored code, created a needs step

* add condition to prep

* added acknowdegement section

* added github comment

* Moved variables to env

* PRR template

* PRR template changes

* Added changes to cfe notifications

* minor changes

* Added slack message sanitization

* PRR cherry-pick flow

* add cherry pick to frozen release label

* bug fix

* use js instead of shell

* use js instead of shell

* template updates

* frozen release as output

* added some comments

* pr base change

* pr base change

* descp change

* copy changes

* Added checkboxes conformation

* added ack section

* fixed bug

* fixed bug

* fixed bug

* typo

* bug fix

* bug fix

* added logic for github comment

* bug fix

* GH PR comment

* GH PR comment for CFE flow

* GH PR comment for CFE flow

* changelog

* In complechangelog step - extract version from branch

* add validation for manual version input

* log the version user entered

* log the version user entered

* rebased changes

* Code refactor

* bug fixes and formatting

* code refactor

* bug fixes

* template updates and using context object instead of parsing

* bug fixes

* renamed file

* moved vars to env

* Improved messaging when CFE or PRR request is rejected (#52377)

Improved messaging for CFE file

* Apply milestone when the CFE or PRR issue is created (#52406)

Apply milestone when the CFE/PRR issue is created

* Change description for CFE and PRR templates (#52459)

* Change description for CFE and PRR templates

* removed changelog files
This commit is contained in:
Naman Malhotra 2024-11-11 21:23:18 +03:00 committed by GitHub
parent 7606b84e41
commit b0284be31e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 1040 additions and 10 deletions

View File

@ -0,0 +1,88 @@
name: 🚧 Code freeze exception request
description: Request to process a particular pull request as a code freeze exception.
title: "[CFE]: "
labels: ["code freeze exception"]
body:
- type: markdown
attributes:
value: |
Use this template to request changes to be included in a version of WooCommerce that is past its code freeze date.
**The request will be reviewed** and accepted or denied:
* If accepted, please test your changes in against the release branch and merge.
* If rejected, please change the base against `trunk` and merge it.
In either case you are responsible for managing the pull request as usual (provide a description, assign reviewers, ensure that CI jobs pass...)
- type: input
id: release-number
attributes:
label: "Which release does this request apply to?"
description: "Format: X.Y (Major.Minor)"
placeholder: "9.2"
validations:
required: true
- type: textarea
id: pr-urls
attributes:
label: "Which PR needs to be included? (please do not enter multiple PRs)"
description: "Pull request URL against the release branch"
placeholder: |
https://github.com/woocommerce/woocommerce/pull/1234
validations:
required: true
- type: textarea
id: why-needed
attributes:
label: "Why do these PRs need to break the code freeze?"
placeholder: "This is a revert of ... which introduced a bug that causes ..."
validations:
required: true
- type: textarea
attributes:
id: consequence-if-not-included
label: "What is the consequence if this exception does not get included?"
placeholder: "The ... flow will be broken for ... users"
validations:
required: true
- type: textarea
id: plan-if-defects-discovered
attributes:
label: "What is the plan should defects to be discovered in these PRs ahead of final release?"
placeholder: "Reverting this PR and ... would be enough"
validations:
required: true
- type: textarea
id: how-to-communicate
attributes:
label: "How should this change be communicated in the release post on the public developer blog:"
description: "See the blog at [https://developer.woo.com/blog/](https://developer.woo.com/blog/) cc @woocommerce/developer-advocacy"
placeholder: "There is no need to add new communication to the already planned one."
validations:
required: true
- type: textarea
id: who-to-ask
attributes:
label: "If youre not available and we have questions about this request, is there another person(s) and/or a team that we can ping?"
placeholder: "@person or anyone from the ... team"
validations:
required: true
- type: markdown
attributes:
value: |
## Escape Analysis
For the sake of expediting this request, the details below can be completed at a later time should you so choose.
However, the Escape Analysis section is **required** for any accepted Code Freeze Exception.
In this section:
* Think about how the bug escaped your team.
* Write down ideas on how you could prevent this bug for example, by writing automated tests, creating a new process, or updating documentation.
* Make a plan with your team to implement the changes proposed above in order to catch the bug earlier next time and add the related tasks to your backlog.
* Please, add a separate comment that includes the details for the Escape Analysis. Together with this Escape Analysis, please make sure to include an actionable item that covers the gap exposed by this analysis. It could be a GitHub issue, the reference of a new item to discuss in a team meeting, etc. Anything that prevents this analysis from getting lost in P2 will be useful.
- type: checkboxes
id: escape-analysis-completed
attributes:
label: "Acknowledgement"
options:
- label: "I understand that I need to write an incident report (aka Escape Analysis) as a comment on this post. This is required for the request to be accepted."
required: true
- label: "I understand that I need to create an issue as a result of the Escape Analysis and reference it in a comment on this post. This can be done at a later time, but it is required for this request to be closed."
required: true

View File

@ -0,0 +1,95 @@
name: 🚧 Point release request
description: Request to process a particular pull request as part of a point release.
title: "[PRR]: "
labels: ["point release request"]
body:
- type: markdown
attributes:
value: |
Use this template to request changes to be included as part of a point release.
**The request will be reviewed** and accepted or denied:
* If accepted, please test your changes in against the release branch and merge.
* If rejected, please change the base against `trunk` and merge it.
In either case you are responsible for managing the pull request as usual (provide a description, assign reviewers, ensure that CI jobs pass...)
- type: input
id: release-number
attributes:
label: "Which release does this request apply to?"
description: "Format: X.Y (Major.Minor)"
placeholder: "9.2"
validations:
required: true
- type: textarea
id: pr-urls
attributes:
label: "Which PR needs to be included? (please do not enter multiple PRs)"
description: "Pull request URL against the release branch"
placeholder: |
https://github.com/woocommerce/woocommerce/pull/1234
validations:
required: true
- type: textarea
id: why-needed
attributes:
label: "Why does this PR need a point release?"
placeholder: "This is a revert of ... which introduced a bug that causes ..."
validations:
required: true
- type: textarea
attributes:
id: consequence-if-not-included
label: "What is the consequence if this fix not being included in the point release (if any)? e.g. number of users affected and how they are affected"
placeholder: "The ... flow will be broken for ... users"
validations:
required: true
- type: textarea
id: plan-if-defects-discovered
attributes:
label: "What is the plan should defects to be discovered in these PR after the point release?"
placeholder: "Reverting this PR and ... would be enough"
validations:
required: true
- type: textarea
id: how-to-communicate
attributes:
label: "How should this change be communicated in the release post on the public developer blog: cc @woocommerce/developer-advocacy"
description: "See the blog at [https://developer.woo.com/blog/](https://developer.woo.com/blog/)"
placeholder: "There is no need to add new communication to the already planned one."
validations:
required: true
- type: textarea
id: workaround
attributes:
label: "Is there a workaround to the issue? If yes, how should we communicate it on the (public developer blog)[https://developer.woo.com/blog/]?"
placeholder: "Use the ... flow instead"
validations:
required: true
- type: textarea
id: who-to-ask
attributes:
label: "If youre not available and we have questions about this request, is there another person(s) and/or a team that we can ping?"
placeholder: "@person or anyone from the ... team"
validations:
required: true
- type: markdown
attributes:
value: |
## Escape Analysis
For the sake of expediting this request, the details below can be completed at a later time should you so choose.
However, the Escape Analysis section is **required** for any accepted Point Release Request.
In this section:
* Think about how the bug escaped your team.
* Write down ideas on how you could prevent this bug for example, by writing automated tests, creating a new process, or updating documentation.
* Make a plan with your team to implement the changes proposed above in order to catch the bug earlier next time and add the related tasks to your backlog.
* Please, add a separate comment that includes the details for the Escape Analysis. Together with this Escape Analysis, please make sure to include an actionable item that covers the gap exposed by this analysis. It could be a GitHub issue, the reference of a new item to discuss in a team meeting, etc. Anything that prevents this analysis from getting lost in P2 will be useful.
- type: checkboxes
id: escape-analysis-completed
attributes:
label: "Acknowledgement"
options:
- label: "I understand that I need to write an incident report (aka Escape Analysis) as a comment on this post. This is required for the request to be accepted."
required: true
- label: "I understand that I need to create an issue as a result of the Escape Analysis and reference it in a comment on this post. This can be done at a later time, but it is required for this request to be closed."
required: true

View File

@ -0,0 +1,253 @@
# This workflow is used to cherry pick PRs from release branche into trunk.
name: New CFE workflow - Cherry pick
on:
pull_request:
types: [closed]
workflow_dispatch:
inputs:
skipSlackPing:
description: 'Skip Slack Ping: If true, the Slack ping will be skipped (useful for testing)'
type: boolean
required: false
default: false
env:
GIT_COMMITTER_NAME: 'WooCommerce Bot'
GIT_COMMITTER_EMAIL: 'no-reply@woocommerce.com'
GIT_AUTHOR_NAME: 'WooCommerce Bot'
GIT_AUTHOR_EMAIL: 'no-reply@woocommerce.com'
permissions: {}
jobs:
verify:
name: Verify
runs-on: ubuntu-20.04
outputs:
run: ${{ steps.check.outputs.run }}
base_ref: ${{ steps.fetch_pr_details.outputs.base_ref }}
steps:
- name: Fetch Pull Request Details
if: github.event.pull_request
id: fetch_pr_details
uses: actions/github-script@v7
with:
script: |
const pullRequestUrl = context.payload.pull_request.url;
const prDetails = await github.request(pullRequestUrl);
const labels = prDetails.data.labels.map(label => label.name);
console.log('Labels:', labels);
if (!labels.includes('cherry pick to trunk')) {
console.log('Label "cherry pick to trunk" not found. Exiting job.');
process.exit(0);
}
core.setOutput('base_ref', prDetails.data.base.ref);
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: check
id: check
uses: actions/github-script@v7
with:
script: |
const baseRef = process.env.BASE_REF;
console.log("baseRef:", baseRef);
let run = false;
const isBot = context.payload.pull_request && ( context.payload.pull_request.user.login == 'github-actions[bot]' || context.payload.pull_request.user.type == 'Bot' );
console.log("isBot:", isBot);
console.log("baseRef.startsWith('release/'):", baseRef.startsWith('release/'));
if ( !isBot && baseRef.startsWith( 'release/' ) ) {
core.setOutput( 'run', 'true' );
} else {
core.setOutput( 'run', 'false' );
}
env:
BASE_REF: ${{ steps.fetch_pr_details.outputs.base_ref }}
prep:
name: Prep inputs
runs-on: ubuntu-20.04
if: needs.verify.outputs.run == 'true'
needs: verify
outputs:
release: ${{ steps.prep-inputs.outputs.release }}
pr: ${{ steps.prep-inputs.outputs.pr }}
version: ${{ steps.prep-inputs.outputs.version }}
steps:
- name: Prep inputs
id: prep-inputs
uses: actions/github-script@v7
with:
script: |
const event = ${{ toJSON( github.event ) }}
const releaseBranch = process.env.BASE_REF
const version = releaseBranch.replace( 'release/', '' )
const pr = event.pull_request.number
// Output the values
console.log( 'releaseBranch:', releaseBranch )
console.log( 'version:', version )
console.log( 'pr:', pr )
core.setOutput( 'pr', pr )
core.setOutput( 'version', version )
core.setOutput( 'release', releaseBranch )
env:
BASE_REF: ${{ needs.verify.outputs.base_ref }}
check-release-branch-exists:
name: Check for existence of release branch
runs-on: ubuntu-20.04
needs: prep
steps:
- name: Check for release branch
id: release-breanch-check
uses: actions/github-script@v7
with:
script: |
// This will throw an error for non-200 responses, which prevents subsequent jobs from completing, as desired.
await github.request( 'GET /repos/{owner}/{repo}/branches/{branch}', {
owner: context.repo.owner,
repo: context.repo.repo,
branch: process.env.RELEASE_BRANCH,
} );
env:
RELEASE_BRANCH: ${{ needs.prep.outputs.release }}
cherry-pick-run:
name: Run cherry pick tool
runs-on: ubuntu-20.04
permissions:
actions: write
contents: write
pull-requests: write
needs: [prep, check-release-branch-exists]
if: success()
steps:
- name: Checkout release branch
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Git fetch the release branch
run: git fetch origin trunk
- name: Checkout release branch
run: git checkout trunk
- name: Create a cherry pick branch based on trunk branch
run: git checkout -b cherry-pick-$RELEASE_BRANCH/$PR
env:
RELEASE_BRANCH: ${{ needs.prep.outputs.release }}
PR: ${{ needs.prep.outputs.pr }}
- name: Get commit sha from PR
id: commit-sha
uses: actions/github-script@v7
with:
script: |
const pr = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: process.env.PR
})
core.setOutput( 'sha', pr.data.merge_commit_sha )
env:
PR: ${{ needs.prep.outputs.pr }}
- name: Cherry pick
run: |
git cherry-pick $SHA -m1
env:
SHA: ${{ steps.commit-sha.outputs.sha }}
- name: Push cherry pick branch up
run: git push origin cherry-pick-$RELEASE_BRANCH/$PR
env:
RELEASE_BRANCH: ${{ needs.prep.outputs.release }}
PR: ${{ needs.prep.outputs.pr }}
- name: Create the PR for cherry pick branch
id: cherry-pick-pr
uses: actions/github-script@v7
with:
script: |
const prNumber = process.env.PR;
const releaseBranch = process.env.RELEASE_BRANCH;
let cherryPickPRBody = "This PR cherry-picks the following PRs into the trunk branch:\n";
cherryPickPRBody = `${cherryPickPRBody}` + `* #${prNumber}` + "\n";
const pr = await github.rest.pulls.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: `Cherry pick ${prNumber} into trunk`,
head: `cherry-pick-${releaseBranch}/${prNumber}`,
base: "trunk",
body: cherryPickPRBody
})
core.setOutput( 'cherry-pick-pr', pr.data.html_url )
console.log( 'cherry-pick-pr URL:', pr.data.html_url )
// label PR
const label = await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pr.data.number,
labels: ["metric: code freeze exception"],
});
env:
PR: ${{ needs.prep.outputs.pr }}
RELEASE_BRANCH: ${{ needs.prep.outputs.release }}
- name: Notify Slack on failure
if: ${{ failure() && inputs.skipSlackPing != true }}
uses: archive/github-actions-slack@v2.0.0
with:
slack-bot-user-oauth-access-token: ${{ secrets.CODE_FREEZE_BOT_TOKEN }}
slack-channel: ${{ secrets.WOO_CORE_RELESES_DAILY_SLACK_CHANNEL }}
slack-text: |
:warning-8c: CFE cherry pick failed for '${{ needs.prep.outputs.release }}'
An attempt to cherry pick PR(s) into outgoing trunk for `${{ needs.prep.outputs.release }}` has failed. This could be due to a merge conflict or something else that requires manual attention. Please check: https://github.com/woocommerce/woocommerce/pull/${{ needs.prep.outputs.pr }}
- name: Notify Slack on success
if: ${{ success() && inputs.skipSlackPing != true }}
uses: archive/github-actions-slack@v2.0.0
with:
slack-bot-user-oauth-access-token: ${{ secrets.CODE_FREEZE_BOT_TOKEN }}
slack-channel: ${{ secrets.WOO_CORE_RELESES_DAILY_SLACK_CHANNEL }}
slack-text: |
:info: CFE cherry pick succeeded for `${{ needs.prep.outputs.release }}`
Please merge the following PR :pr: into `trunk`:
${{ steps.cherry-pick-pr.outputs.cherry-pick-pr }}
- name: Comment on PR about the failed cherry pick
if: ${{ failure() }}
run: |
gh pr comment $HTML_URL --body "Cherry picking failed for the trunk. Please do it manually. Or debug, what happened and run the workflow again. Workflow link for debugging: https://github.com/${{ github.repository_owner }}/${{ github.repository }}/actions/workflows/new-cfe-cherry-pick.yml"
env:
GH_TOKEN: ${{ github.token }}
HTML_URL: ${{ github.event.pull_request.html_url }}
- name: Comment on PR about the cherry picked PRs to be merged
if: ${{ success() }}
run: |
gh pr comment $HTML_URL --body "Cherry picking was successful for trunk. Please merge the following PR: $CHERRY_PICK_PR"
env:
GH_TOKEN: ${{ github.token }}
HTML_URL: ${{ github.event.pull_request.html_url }}
CHERRY_PICK_PR: ${{ steps.cherry-pick-pr.outputs.cherry-pick-pr }}

View File

@ -0,0 +1,226 @@
name: New CFE/PRR workflow notifications
on:
issues:
types: [labeled]
permissions: {}
jobs:
prep:
if: github.event.label.name == 'code freeze exception' || github.event.label.name == 'point release request' || github.event.label.name == 'Approved' || github.event.label.name == 'Rejected'
runs-on: ubuntu-20.04
outputs:
release_number: ${{ steps.extract-release.outputs.RELEASE_NUMBER }}
steps:
- name: Extract Release Number from Issue Body
id: extract-release
uses: actions/github-script@v7
with:
script: |
const body = context.payload.issue.body; // Accessing the issue body directly from the context
// Regular expression to match the release number after the specific question
const releaseRegex = /Which release does this request apply to\?.*?\n([0-9]+\.[0-9]+)/s;
// Match the body against the regex
const match = body.match(releaseRegex);
// Check if a valid release number was found
if (match && match[1]) {
const releaseNumber = match[1];
// Log the release number and set it as a GitHub output
console.log(`Valid release number: ${releaseNumber}`);
core.setOutput('RELEASE_NUMBER', releaseNumber);
} else {
// If no valid release number is found, fail the step
core.setFailed("No valid release number found after the 'Which release does this request apply to?' section. Aborting.");
}
apply-milestone:
if: github.event.label.name == 'code freeze exception' || github.event.label.name == 'point release request' || github.event.label.name == 'Approved' || github.event.label.name == 'Rejected'
runs-on: ubuntu-20.04
permissions:
issues: write
needs:
- prep
steps:
- name: Apply Milestone to the Issue
env:
MILESTONE: ${{ needs.prep.outputs.release_number }}.0
ISSUE_URL: ${{ github.event.issue.html_url }}
GH_TOKEN: ${{ github.token }}
run: |
echo "Applying milestone: $MILESTONE"
gh issue edit "$ISSUE_URL" --milestone "$MILESTONE"
cfe-created:
if: github.event.label.name == 'code freeze exception' || github.event.label.name == 'point release request'
runs-on: ubuntu-20.04
steps:
- name: Set Slack Message
id: set-message
uses: actions/github-script@v7
with:
script: |
const event = context.payload;
const labelName = event.label?.name;
const issueTitle = event.issue.title;
const issueUrl = event.issue.html_url;
let message = '';
// Determine the type of message based on the label name
if (labelName === 'code freeze exception') {
message = `:arrow_right: New CFE request: ${issueTitle} ${issueUrl}`;
} else {
message = `:arrow_right: New PRR request: ${issueTitle} ${issueUrl}`;
}
// Set the message as a core output
core.setOutput('SLACK_MESSAGE', message);
- name: Notify Slack
uses: archive/github-actions-slack@v2.0.0
id: notify
with:
slack-bot-user-oauth-access-token: ${{ secrets.CODE_FREEZE_BOT_TOKEN }}
slack-channel: ${{ secrets.WOO_RELEASE_SLACK_CHANNEL }}
slack-text: ${{ steps.set-message.outputs.SLACK_MESSAGE }}
slack-optional-unfurl_links: false
slack-optional-unfurl_media: false
continue-on-error: true
request-approved:
if: ${{ github.event.label.name == 'Approved' }}
runs-on: ubuntu-20.04
permissions:
pull-requests: write
issues: write
steps:
- name: Extract PR number from issue body
id: extract-pr
uses: actions/github-script@v7
with:
script: |
const body = context.payload.issue.body;
// Regular expression to match the PR link that follows the specific question
const prRegex = /Which PR needs to be included\?.*?\n(https:\/\/github\.com\/[a-zA-Z0-9_\-]+\/[a-zA-Z0-9_\-]+\/pull\/([0-9]+))/s;
// Match the body against the regex
const match = body.match(prRegex);
// Check if a valid PR number was found
if (match && match[2]) {
const prNumber = match[2];
// Log the PR number and set it as a GitHub output
console.log(`Valid PR number: ${prNumber}`);
core.setOutput('PR_NUMBER', prNumber);
} else {
// If no valid PR number is found, fail the step
core.setFailed("No valid PR found after the 'Which PR' section. Aborting.");
}
- name: Add label 'cherry pick to trunk' to PR
env:
OWNER: ${{ github.event.repository.owner.login }}
REPO: ${{ github.event.repository.name }}
PR_NUMBER: ${{ steps.extract-pr.outputs.PR_NUMBER }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh pr edit $PR_NUMBER --add-label "cherry pick to trunk" --repo "$OWNER/$REPO"
- name: Add label 'cherry pick to frozen release' to PR
if: contains(github.event.issue.labels.*.name, 'point release request')
env:
OWNER: ${{ github.event.repository.owner.login }}
REPO: ${{ github.event.repository.name }}
PR_NUMBER: ${{ steps.extract-pr.outputs.PR_NUMBER }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh pr edit $PR_NUMBER --add-label "cherry pick to frozen release" --repo "$OWNER/$REPO"
- name: Comment issue has been approved
env:
ISSUE_URL: ${{ github.event.issue.html_url }}
GH_TOKEN: ${{ github.token }}
run: |
gh issue comment "$ISSUE_URL" --body "This request has been approved. Please merge the PR to release branch."
- name: Set Slack Message
id: set-message
uses: actions/github-script@v7
with:
script: |
const event = context.payload; // Accessing the event directly from the context
const labelName = event.label?.name;
const issueTitle = event.issue.title;
const issueUrl = event.issue.html_url;
let message = '';
if (labelName === 'code freeze exception') {
message = `:white_check_mark: CFE request approved: ${issueTitle} ${issueUrl}`;
} else {
message = `:white_check_mark: PRR request approved: ${issueTitle} ${issueUrl}`;
}
core.setOutput('SLACK_MESSAGE', message);
- name: Notify Slack
uses: archive/github-actions-slack@v2.0.0
id: notify
with:
slack-bot-user-oauth-access-token: ${{ secrets.CODE_FREEZE_BOT_TOKEN }}
slack-channel: ${{ secrets.WOO_CORE_RELESES_DAILY_SLACK_CHANNEL }}
slack-text: ${{ steps.set-message.outputs.SLACK_MESSAGE }}
slack-optional-unfurl_links: false
slack-optional-unfurl_media: false
continue-on-error: true
request-rejected:
if: ${{ github.event.label.name == 'Rejected' }}
runs-on: ubuntu-20.04
permissions:
issues: write
steps:
- name: Close the request
env:
ISSUE_URL: ${{ github.event.issue.html_url }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh issue close "$ISSUE_URL" --comment "Closing issue as the request is rejected - $ISSUE_URL. Please switch the base to trunk and merge."
- name: Set Slack Message
id: set-message
uses: actions/github-script@v7
with:
script: |
const event = context.payload;
const labelName = event.label?.name;
const issueTitle = event.issue.title;
const issueUrl = event.issue.html_url;
let message = '';
if (labelName === 'code freeze exception') {
message = `:x: CFE request rejected: ${issueTitle} ${issueUrl}`;
} else {
message = `:x: PRR request rejected: ${issueTitle} ${issueUrl}`;
}
core.setOutput('SLACK_MESSAGE', message);
- name: Notify Slack
uses: archive/github-actions-slack@v2.0.0
id: notify
with:
slack-bot-user-oauth-access-token: ${{ secrets.CODE_FREEZE_BOT_TOKEN }}
slack-channel: ${{ secrets.WOO_CORE_RELESES_DAILY_SLACK_CHANNEL }}
slack-text: ${{ steps.set-message.outputs.SLACK_MESSAGE }}
slack-optional-unfurl_links: false
slack-optional-unfurl_media: false
continue-on-error: true

View File

@ -0,0 +1,81 @@
name: Pre build step - Compile changelog file
on:
workflow_dispatch:
inputs:
version:
description: 'Version override. Default version is fetched from the base branch name, you can override the version but make sure the that the branch release/{version} exists on remote. Format: X.Y (Major.Minor)'
required: false
default: ''
env:
GIT_COMMITTER_NAME: 'WooCommerce Bot'
GIT_COMMITTER_EMAIL: 'no-reply@woocommerce.com'
GIT_AUTHOR_NAME: 'WooCommerce Bot'
GIT_AUTHOR_EMAIL: 'no-reply@woocommerce.com'
jobs:
build-prep:
name: Create changelog PR
runs-on: ubuntu-20.04
permissions:
contents: write
pull-requests: write
steps:
- name: Get version from the branch name workflow is running on
if: ${{ github.event.inputs.version == '' }}
uses: actions/github-script@v7
id: extract-version
with:
script: |
const refName = process.env.GITHUB_REF_NAME;
const versionMatch = refName.match(/^release\/(\d+\.\d+)$/);
if (versionMatch) {
const version = versionMatch[1];
console.log(`Extracted version: ${version}`);
core.setOutput('version', version);
} else {
core.setFailed(`Branch name ${refName} does not match the expected pattern 'release/x.y'`);
process.exit(1);
}
- name: Validate version input override
if: ${{ github.event.inputs.version != '' }}
uses: actions/github-script@v7
env:
VERSION: ${{ github.event.inputs.version }}
with:
script: |
const version = process.env.VERSION;
if (!/^\d+\.\d+$/.test(version)) {
core.setFailed('Invalid version format. The version must be in the format X.Y');
core.info(`Version you entered: ${version}`);
process.exit(1);
}
- name: Checkout code
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Setup PNPM
uses: pnpm/action-setup@a3252b78c470c02df07e9d59298aecedc3ccdd6d
- name: Setup Node
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c
with:
node-version-file: .nvmrc
cache: pnpm
registry-url: 'https://registry.npmjs.org'
- name: Install prerequisites
run: |
pnpm install --filter monorepo-utils --ignore-scripts
# ignore scripts speeds up setup signficantly, but we still need to build monorepo utils
pnpm build
working-directory: tools/monorepo-utils
- name: Generate changelog changes and create PR
id: changelog
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: pnpm utils code-freeze changelog -o ${{ github.repository_owner }} -v ${{ github.event.inputs.version || steps.extract-version.outputs.version }}

View File

@ -0,0 +1,295 @@
# This workflow is used to cherry pick PRs into a frozen release branch.
name: New PRR workflow - Cherry pick
on:
pull_request:
types: [closed]
workflow_dispatch:
inputs:
skipSlackPing:
description: 'Skip Slack Ping: If true, the Slack ping will be skipped (useful for testing)'
type: boolean
required: false
default: false
env:
GIT_COMMITTER_NAME: 'WooCommerce Bot'
GIT_COMMITTER_EMAIL: 'no-reply@woocommerce.com'
GIT_AUTHOR_NAME: 'WooCommerce Bot'
GIT_AUTHOR_EMAIL: 'no-reply@woocommerce.com'
permissions: {}
jobs:
verify:
name: Verify
runs-on: ubuntu-20.04
outputs:
run: ${{ steps.check.outputs.run }}
base_ref: ${{ steps.fetch_pr_details.outputs.base_ref }}
steps:
- name: Fetch Pull Request Details
if: github.event.pull_request
id: fetch_pr_details
uses: actions/github-script@v7
with:
script: |
const pullRequestUrl = context.payload.pull_request.url;
const prDetails = await github.request(pullRequestUrl);
const labels = prDetails.data.labels.map(label => label.name);
console.log('Labels:', labels);
if (!labels.includes('cherry pick to frozen release')) {
console.log('Label "cherry pick to frozen release" not found. Exiting job.');
process.exit(0);
}
core.setOutput('base_ref', prDetails.data.base.ref);
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: check
id: check
uses: actions/github-script@v7
with:
script: |
const baseRef = process.env.BASE_REF;
console.log("baseRef:", baseRef);
let run = false;
const isBot = context.payload.pull_request && ( context.payload.pull_request.user.login == 'github-actions[bot]' || context.payload.pull_request.user.type == 'Bot' );
console.log("isBot:", isBot);
console.log("baseRef.startsWith('release/'):", baseRef.startsWith('release/'));
if ( !isBot && baseRef.startsWith( 'release/' ) ) {
core.setOutput( 'run', 'true' );
} else {
core.setOutput( 'run', 'false' );
}
env:
BASE_REF: ${{ steps.fetch_pr_details.outputs.base_ref }}
prep:
name: Prep inputs
runs-on: ubuntu-20.04
if: needs.verify.outputs.run == 'true'
needs: verify
outputs:
release: ${{ steps.prep-inputs.outputs.release }}
frozenRelease: ${{ steps.prep-inputs.outputs.frozenRelease }}
pr: ${{ steps.prep-inputs.outputs.pr }}
version: ${{ steps.prep-inputs.outputs.version }}
steps:
- name: Prep inputs
id: prep-inputs
uses: actions/github-script@v7
with:
script: |
const event = ${{ toJSON( github.event ) }}
const releaseBranch = process.env.BASE_REF
const version = releaseBranch.replace( 'release/', '' )
const pr = event.pull_request.number
// Split the version to get major and minor parts
let [major, minor] = version.split('.').map(Number)
// Check if minor version is 9, increment major and reset minor
if (minor === 9) {
major += 1
minor = 0
} else {
// Otherwise, just increment the minor version
minor += 1
}
// Create the frozen release branch name
const frozenRelease = `release/${major}.${minor}`
// Output the values
console.log('releaseBranch:', releaseBranch)
console.log('version:', version)
console.log('pr:', pr)
console.log('frozenRelease:', frozenRelease)
core.setOutput('pr', pr)
core.setOutput('version', version)
core.setOutput('release', releaseBranch)
core.setOutput('frozenRelease', frozenRelease)
env:
BASE_REF: ${{ needs.verify.outputs.base_ref }}
check-release-branch-exists:
name: Check for existence of release branch
runs-on: ubuntu-20.04
needs: prep
steps:
- name: Check for release branch
id: release-breanch-check
uses: actions/github-script@v7
with:
script: |
// This will throw an error for non-200 responses, which prevents subsequent jobs from completing, as desired.
await github.request( 'GET /repos/{owner}/{repo}/branches/{branch}', {
owner: context.repo.owner,
repo: context.repo.repo,
branch: process.env.RELEASE_BRANCH,
} );
env:
RELEASE_BRANCH: ${{ needs.prep.outputs.release }}
check-frozen-release-branch-exists:
name: Check for existence of frozen release branch
runs-on: ubuntu-20.04
needs: prep
steps:
- name: Check for release branch
id: release-breanch-check
uses: actions/github-script@v7
with:
script: |
// This will throw an error for non-200 responses, which prevents subsequent jobs from completing, as desired.
await github.request( 'GET /repos/{owner}/{repo}/branches/{branch}', {
owner: context.repo.owner,
repo: context.repo.repo,
branch: process.env.FROZEN_RELEASE_BRANCH,
} );
env:
FROZEN_RELEASE_BRANCH: ${{ needs.prep.outputs.frozenRelease }}
cherry-pick-run:
name: Run cherry pick tool
runs-on: ubuntu-20.04
permissions:
actions: write
contents: write
pull-requests: write
needs: [prep, check-release-branch-exists, check-frozen-release-branch-exists]
if: success()
steps:
- name: Checkout release branch
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Git fetch the frozen release branch
run: git fetch origin $FROZEN_RELEASE_BRANCH
env:
FROZEN_RELEASE_BRANCH: ${{ needs.prep.outputs.frozenRelease }}
- name: Checkout frozen release branch
run: git checkout $FROZEN_RELEASE_BRANCH
env:
FROZEN_RELEASE_BRANCH: ${{ needs.prep.outputs.frozenRelease }}
- name: Create a cherry pick branch
run: git checkout -b cherry-pick-$FROZEN_RELEASE_BRANCH/$PR
env:
FROZEN_RELEASE_BRANCH: ${{ needs.prep.outputs.frozenRelease }}
PR: ${{ needs.prep.outputs.pr }}
- name: Get commit sha from PR
id: commit-sha
uses: actions/github-script@v7
with:
script: |
const pr = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: process.env.PR
})
core.setOutput( 'sha', pr.data.merge_commit_sha )
env:
PR: ${{ needs.prep.outputs.pr }}
- name: Cherry pick
run: |
git cherry-pick $SHA -m1
env:
SHA: ${{ steps.commit-sha.outputs.sha }}
- name: Push cherry pick branch up
run: git push origin cherry-pick-$FROZEN_RELEASE_BRANCH/$PR
env:
FROZEN_RELEASE_BRANCH: ${{ needs.prep.outputs.frozenRelease }}
PR: ${{ needs.prep.outputs.pr }}
- name: Create the PR for cherry pick branch
id: cherry-pick-pr
uses: actions/github-script@v7
with:
script: |
const frozenReleaseBranch = process.env.FROZEN_RELEASE_BRANCH;
const prNumber = process.env.PR;
let cherryPickPRBody = `This PR cherry-picks the following PRs into the frozen release branch: ${frozenReleaseBranch}`;
cherryPickPRBody = `${cherryPickPRBody}\n* #${prNumber}\n`;
const pr = await github.rest.pulls.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: `Cherry pick ${prNumber} into frozen release: ${frozenReleaseBranch}`,
head: `cherry-pick-${frozenReleaseBranch}/${prNumber}`,
base: frozenReleaseBranch,
body: cherryPickPRBody
});
core.setOutput('cherry-pick-pr', pr.data.html_url);
console.log('cherry-pick-pr URL:', pr.data.html_url);
// label PR
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pr.data.number,
labels: ["metric: point release request"],
});
env:
PR: ${{ needs.prep.outputs.pr }}
FROZEN_RELEASE_BRANCH: ${{ needs.prep.outputs.frozenRelease }}
- name: Notify Slack on failure
if: ${{ failure() && inputs.skipSlackPing != true }}
uses: archive/github-actions-slack@v2.0.0
with:
slack-bot-user-oauth-access-token: ${{ secrets.CODE_FREEZE_BOT_TOKEN }}
slack-channel: ${{ secrets.WOO_CORE_RELESES_DAILY_SLACK_CHANNEL }}
slack-text: |
:warning-8c: Point release request cherry pick failed for `${{ needs.prep.outputs.release }}`
An attempt to cherry pick PR(s) into outgoing `${{ needs.prep.outputs.frozenRelease }}` for `${{ needs.prep.outputs.release }}` has failed. This could be due to a merge conflict or something else that requires manual attention. Please check: https://github.com/woocommerce/woocommerce/pull/${{ needs.prep.outputs.pr }}
- name: Notify Slack on success
if: ${{ success() && inputs.skipSlackPing != true }}
uses: archive/github-actions-slack@v2.0.0
with:
slack-bot-user-oauth-access-token: ${{ secrets.CODE_FREEZE_BOT_TOKEN }}
slack-channel: ${{ secrets.WOO_CORE_RELESES_DAILY_SLACK_CHANNEL }}
slack-text: |
:info: Point release request cherry pick succeeded for `${{ needs.prep.outputs.release }}`
Please merge the following PR :pr: into `${{ needs.prep.outputs.frozenRelease }}`:
${{ steps.cherry-pick-pr.outputs.cherry-pick-pr }}
- name: Comment on PR about the failed cherry pick
if: ${{ failure() }}
run: |
gh pr comment $HTML_URL --body "Cherry picking failed for the frozen release: $FROZEN_RELEASE_BRANCH. Please do it manually. Or debug, what happened and run the workflow again. Workflow link for debugging:https://github.com/${{ github.repository_owner }}/${{ github.repository }}/actions/workflows/new-prr-cherry-pick.yml"
env:
GH_TOKEN: ${{ github.token }}
HTML_URL: ${{ github.event.pull_request.html_url }}
FROZEN_RELEASE_BRANCH: ${{ needs.prep.outputs.frozenRelease }}
- name: Comment on PR about the cherry picked PRs to be merged
if: ${{ success() }}
run: |
gh pr comment $HTML_URL --body "Cherry picking was successful for frozen release: $FROZEN_RELEASE_BRANCH. Please merge the following PR: $CHERRY_PICK_PR"
env:
GH_TOKEN: ${{ github.token }}
HTML_URL: ${{ github.event.pull_request.html_url }}
FROZEN_RELEASE_BRANCH: ${{ needs.prep.outputs.frozenRelease }}
CHERRY_PICK_PR: ${{ steps.cherry-pick-pr.outputs.cherry-pick-pr }}

View File

@ -116,14 +116,6 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: pnpm utils code-freeze version-bump ${{ steps.get-versions.outputs.monthlyMilestone }}-dev -o ${{ github.repository_owner }}
- name: Generate changelog changes
id: changelog
if: steps.get-versions.outputs.isTodayMonthlyFreeze == 'yes'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: pnpm utils code-freeze changelog -c -o ${{ github.repository_owner }} -v ${{ steps.get-versions.outputs.monthlyVersionXY }}
notify-slack:
name: 'Sends code freeze notification to Slack'
runs-on: ubuntu-20.04

View File

@ -154,7 +154,7 @@ export const updateReleaseBranchChangelogs = async (
owner,
name,
title: `Release: Prepare the changelog for ${ version }`,
body: `This pull request was automatically generated during the code freeze to prepare the changelog for ${ version }`,
body: `This pull request was automatically generated to prepare the changelog for ${ version }`,
head: branch,
base: releaseBranch,
} );
@ -209,7 +209,7 @@ export const updateTrunkChangelog = async (
owner,
name,
title: `Release: Remove ${ version } change files`,
body: `This pull request was automatically generated during the code freeze to remove the changefiles from ${ version } that are compiled into the \`${ releaseBranch }\` ${
body: `This pull request was automatically generated to remove the changefiles from ${ version } that are compiled into the \`${ releaseBranch }\` ${
prNumber > 0 ? `branch via #${ prNumber }` : ''
}`,
head: branch,