Monorepo Utils: Add changelog addition from actions (#38510)
This commit is contained in:
parent
3314855487
commit
d53cfd4336
|
@ -1,9 +1,9 @@
|
||||||
### Submission Review Guidelines:
|
### Submission Review Guidelines:
|
||||||
|
|
||||||
- I have followed the [WooCommerce Contributing Guidelines](https://github.com/woocommerce/woocommerce/blob/trunk/.github/CONTRIBUTING.md) and the [WordPress Coding Standards](https://make.wordpress.org/core/handbook/best-practices/coding-standards/).
|
- I have followed the [WooCommerce Contributing Guidelines](https://github.com/woocommerce/woocommerce/blob/trunk/.github/CONTRIBUTING.md) and the [WordPress Coding Standards](https://make.wordpress.org/core/handbook/best-practices/coding-standards/).
|
||||||
- I have checked to ensure there aren't other open [Pull Requests](https://github.com/woocommerce/woocommerce/pulls) for the same update/change.
|
- I have checked to ensure there aren't other open [Pull Requests](https://github.com/woocommerce/woocommerce/pulls) for the same update/change.
|
||||||
- I have reviewed my code for [security best practices](https://developer.wordpress.org/apis/security/).
|
- I have reviewed my code for [security best practices](https://developer.wordpress.org/apis/security/).
|
||||||
- Following the above guidelines will result in quick merges and clear and detailed feedback when appropriate.
|
- Following the above guidelines will result in quick merges and clear and detailed feedback when appropriate.
|
||||||
|
|
||||||
<!-- You can erase any parts of this template not applicable to your Pull Request. -->
|
<!-- You can erase any parts of this template not applicable to your Pull Request. -->
|
||||||
|
|
||||||
|
@ -28,3 +28,37 @@ Using the [WooCommerce Testing Instructions Guide](https://github.com/woocommerc
|
||||||
3.
|
3.
|
||||||
|
|
||||||
<!-- End testing instructions -->
|
<!-- End testing instructions -->
|
||||||
|
|
||||||
|
### Changelog entry
|
||||||
|
|
||||||
|
<!-- You can optionally choose to enter a changelog entry by checking the box and supplying data. -->
|
||||||
|
|
||||||
|
- [ ] Automatically create a changelog entry from the details below.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
|
||||||
|
#### Significance
|
||||||
|
|
||||||
|
<!-- Choose only one -->
|
||||||
|
|
||||||
|
- [ ] Patch
|
||||||
|
- [ ] Minor
|
||||||
|
- [ ] Major
|
||||||
|
|
||||||
|
#### Type
|
||||||
|
|
||||||
|
<!-- Choose only one -->
|
||||||
|
|
||||||
|
- [ ] Fix - Fixes an existing bug
|
||||||
|
- [ ] Add - Adds functionality
|
||||||
|
- [ ] Update - Update existing functionality
|
||||||
|
- [ ] Dev - Development related task
|
||||||
|
- [ ] Tweak - A minor adjustment to the codebase
|
||||||
|
- [ ] Performance - Address performance issues
|
||||||
|
- [ ] Enhancement
|
||||||
|
|
||||||
|
#### Message <!-- Add a changelog message here -->
|
||||||
|
|
||||||
|
#### Comment <!-- If the changes in this pull request don't warrant a changelog entry, you can alternatively supply a comment here. Note that comments are only accepted with a significance of "Patch" -->
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
|
@ -1,10 +1,46 @@
|
||||||
name: 'Changelog Auto Add'
|
name: 'Changelog Auto Add'
|
||||||
on: workflow_dispatch
|
on:
|
||||||
|
pull_request:
|
||||||
|
types: [opened, synchronize, reopened, edited]
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
prNumber:
|
||||||
|
description: Pull request number
|
||||||
|
required: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
hello-world:
|
add-changelog:
|
||||||
name: 'Hello World'
|
name: 'Add changelog to PR'
|
||||||
|
if: ${{ github.event.pull_request.user.login != 'github-actions[bot]' }}
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
issues: write
|
||||||
|
pull-requests: write
|
||||||
steps:
|
steps:
|
||||||
- name: Hello
|
- name: Checkout code
|
||||||
run: echo "Hello World"
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Setup PNPM
|
||||||
|
uses: pnpm/action-setup@c3b53f6a16e57305370b4ae5a540c2077a1d50dd
|
||||||
|
with:
|
||||||
|
version: '8.3.1'
|
||||||
|
|
||||||
|
- 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: Add changelog
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
run: pnpm utils changefile ${{github.event.number || inputs.prNumber}} -o ${{ github.repository_owner }}
|
||||||
|
|
|
@ -31,9 +31,3 @@ if [ $? -ne 0 ]; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Ensure both branches are tracked or check-changelogger-use will fail. Note we pass hooksPath
|
|
||||||
# to avoid running the pre-commit hook.
|
|
||||||
git -c core.hooksPath=/dev/null checkout $PROTECTED_BRANCH --quiet
|
|
||||||
git -c core.hooksPath=/dev/null checkout $CURRENT_BRANCH --quiet
|
|
||||||
|
|
||||||
php tools/monorepo/check-changelogger-use.php $PROTECTED_BRANCH $CURRENT_BRANCH
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ import {
|
||||||
getPullRequestData,
|
getPullRequestData,
|
||||||
shouldAutomateChangelog,
|
shouldAutomateChangelog,
|
||||||
getChangelogDetails,
|
getChangelogDetails,
|
||||||
|
getChangelogDetailsError,
|
||||||
} from './lib/github';
|
} from './lib/github';
|
||||||
import {
|
import {
|
||||||
getAllProjectPaths,
|
getAllProjectPaths,
|
||||||
|
@ -66,8 +67,13 @@ const program = new Command( 'changefile' )
|
||||||
process.exit( 0 );
|
process.exit( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
const { significance, type, message, comment } =
|
const details = getChangelogDetails( prBody );
|
||||||
getChangelogDetails( prBody );
|
const { significance, type, message, comment } = details;
|
||||||
|
const changelogDetailsError = getChangelogDetailsError( details );
|
||||||
|
|
||||||
|
if ( changelogDetailsError ) {
|
||||||
|
Logger.error( changelogDetailsError );
|
||||||
|
}
|
||||||
|
|
||||||
Logger.startTask(
|
Logger.startTask(
|
||||||
`Making a temporary clone of '${ headOwner }/${ name }'`
|
`Making a temporary clone of '${ headOwner }/${ name }'`
|
||||||
|
@ -76,7 +82,7 @@ const program = new Command( 'changefile' )
|
||||||
? devRepoPath
|
? devRepoPath
|
||||||
: await cloneAuthenticatedRepo(
|
: await cloneAuthenticatedRepo(
|
||||||
{ owner: headOwner, name },
|
{ owner: headOwner, name },
|
||||||
true
|
false
|
||||||
);
|
);
|
||||||
|
|
||||||
Logger.endTask();
|
Logger.endTask();
|
||||||
|
@ -85,15 +91,6 @@ const program = new Command( 'changefile' )
|
||||||
`Temporary clone of '${ headOwner }/${ name }' created at ${ tmpRepoPath }`
|
`Temporary clone of '${ headOwner }/${ name }' created at ${ tmpRepoPath }`
|
||||||
);
|
);
|
||||||
|
|
||||||
// When a devRepoPath is provided, assume that the dependencies are already installed.
|
|
||||||
if ( ! devRepoPath ) {
|
|
||||||
Logger.notice( `Installing dependencies in ${ tmpRepoPath }` );
|
|
||||||
execSync( 'pnpm install', {
|
|
||||||
cwd: tmpRepoPath,
|
|
||||||
stdio: 'inherit',
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.notice( `Checking out remote branch ${ branch }` );
|
Logger.notice( `Checking out remote branch ${ branch }` );
|
||||||
await checkoutRemoteBranch( tmpRepoPath, branch );
|
await checkoutRemoteBranch( tmpRepoPath, branch );
|
||||||
|
|
||||||
|
@ -106,13 +103,17 @@ const program = new Command( 'changefile' )
|
||||||
tmpRepoPath,
|
tmpRepoPath,
|
||||||
base,
|
base,
|
||||||
head,
|
head,
|
||||||
fileName
|
fileName,
|
||||||
|
owner,
|
||||||
|
name
|
||||||
);
|
);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const allProjectPaths = await getAllProjectPaths( tmpRepoPath );
|
const allProjectPaths = await getAllProjectPaths( tmpRepoPath );
|
||||||
|
|
||||||
// Remove any already existing changelog files in case a change is reverted and the entry is no longer needed.
|
Logger.notice(
|
||||||
|
'Removing existing changelog files in case a change is reverted and the entry is no longer needed'
|
||||||
|
);
|
||||||
allProjectPaths.forEach( ( projectPath ) => {
|
allProjectPaths.forEach( ( projectPath ) => {
|
||||||
const path = nodePath.join(
|
const path = nodePath.join(
|
||||||
tmpRepoPath,
|
tmpRepoPath,
|
||||||
|
@ -133,6 +134,22 @@ const program = new Command( 'changefile' )
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
if ( touchedProjectsRequiringChangelog.length === 0 ) {
|
||||||
|
Logger.notice( 'No projects require a changelog' );
|
||||||
|
process.exit( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
// When a devRepoPath is provided, assume that the dependencies are already installed.
|
||||||
|
if ( ! devRepoPath ) {
|
||||||
|
Logger.notice(
|
||||||
|
`Installing dependencies in ${ tmpRepoPath }`
|
||||||
|
);
|
||||||
|
execSync( 'pnpm install', {
|
||||||
|
cwd: tmpRepoPath,
|
||||||
|
stdio: 'inherit',
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
touchedProjectsRequiringChangelog.forEach( ( project ) => {
|
touchedProjectsRequiringChangelog.forEach( ( project ) => {
|
||||||
Logger.notice(
|
Logger.notice(
|
||||||
`Running changelog command for ${ project }`
|
`Running changelog command for ${ project }`
|
||||||
|
@ -150,10 +167,11 @@ const program = new Command( 'changefile' )
|
||||||
Logger.error( e );
|
Logger.error( e );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const touchedProjectsString =
|
||||||
|
touchedProjectsRequiringChangelog.join( ', ' );
|
||||||
|
|
||||||
Logger.notice(
|
Logger.notice(
|
||||||
`Changelogs created for ${ touchedProjectsRequiringChangelog.join(
|
`Changelogs created for ${ touchedProjectsString }`
|
||||||
', '
|
|
||||||
) }`
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const git = simpleGit( {
|
const git = simpleGit( {
|
||||||
|
@ -187,7 +205,9 @@ const program = new Command( 'changefile' )
|
||||||
|
|
||||||
Logger.notice( `Adding and committing changes` );
|
Logger.notice( `Adding and committing changes` );
|
||||||
await git.add( '.' );
|
await git.add( '.' );
|
||||||
await git.commit( 'Adding changelog from automation.' );
|
await git.commit(
|
||||||
|
`Add changefile(s) from automation for the following project(s): ${ touchedProjectsString }`
|
||||||
|
);
|
||||||
await git.push( 'origin', branch );
|
await git.push( 'origin', branch );
|
||||||
Logger.notice( `Pushed changes to ${ branch }` );
|
Logger.notice( `Pushed changes to ${ branch }` );
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import {
|
||||||
getChangelogSignificance,
|
getChangelogSignificance,
|
||||||
getChangelogType,
|
getChangelogType,
|
||||||
getChangelogDetails,
|
getChangelogDetails,
|
||||||
|
getChangelogDetailsError,
|
||||||
} from '../github';
|
} from '../github';
|
||||||
import { Logger } from '../../../core/logger';
|
import { Logger } from '../../../core/logger';
|
||||||
|
|
||||||
|
@ -48,11 +49,11 @@ describe( 'getChangelogSignificance', () => {
|
||||||
'- [ ] Performance - Address performance issues\r\n' +
|
'- [ ] Performance - Address performance issues\r\n' +
|
||||||
'- [ ] Enhancement\r\n' +
|
'- [ ] Enhancement\r\n' +
|
||||||
'\r\n' +
|
'\r\n' +
|
||||||
'#### Message\r\n' +
|
'#### Message ' +
|
||||||
'<!-- Add a changelog message here -->\r\n' +
|
'<!-- Add a changelog message here -->\r\n' +
|
||||||
'This is a very useful fix.\r\n' +
|
'This is a very useful fix.\r\n' +
|
||||||
'\r\n' +
|
'\r\n' +
|
||||||
'#### Comment\r\n' +
|
'#### Comment ' +
|
||||||
`<!-- If the changes in this pull request don't warrant a changelog entry, you can alternatively supply a comment here. Note that comments are only accepted with a significance of "Patch" -->\r\n` +
|
`<!-- If the changes in this pull request don't warrant a changelog entry, you can alternatively supply a comment here. Note that comments are only accepted with a significance of "Patch" -->\r\n` +
|
||||||
'\r\n' +
|
'\r\n' +
|
||||||
'</details>';
|
'</details>';
|
||||||
|
@ -87,11 +88,11 @@ describe( 'getChangelogSignificance', () => {
|
||||||
'- [ ] Performance - Address performance issues\r\n' +
|
'- [ ] Performance - Address performance issues\r\n' +
|
||||||
'- [ ] Enhancement\r\n' +
|
'- [ ] Enhancement\r\n' +
|
||||||
'\r\n' +
|
'\r\n' +
|
||||||
'#### Message\r\n' +
|
'#### Message ' +
|
||||||
'<!-- Add a changelog message here -->\r\n' +
|
'<!-- Add a changelog message here -->\r\n' +
|
||||||
'This is a very useful fix.\r\n' +
|
'This is a very useful fix.\r\n' +
|
||||||
'\r\n' +
|
'\r\n' +
|
||||||
'#### Comment\r\n' +
|
'#### Comment ' +
|
||||||
`<!-- If the changes in this pull request don't warrant a changelog entry, you can alternatively supply a comment here. Note that comments are only accepted with a significance of "Patch" -->\r\n` +
|
`<!-- If the changes in this pull request don't warrant a changelog entry, you can alternatively supply a comment here. Note that comments are only accepted with a significance of "Patch" -->\r\n` +
|
||||||
'\r\n' +
|
'\r\n' +
|
||||||
'</details>';
|
'</details>';
|
||||||
|
@ -129,11 +130,11 @@ describe( 'getChangelogSignificance', () => {
|
||||||
'- [ ] Performance - Address performance issues\r\n' +
|
'- [ ] Performance - Address performance issues\r\n' +
|
||||||
'- [ ] Enhancement\r\n' +
|
'- [ ] Enhancement\r\n' +
|
||||||
'\r\n' +
|
'\r\n' +
|
||||||
'#### Message\r\n' +
|
'#### Message ' +
|
||||||
'<!-- Add a changelog message here -->\r\n' +
|
'<!-- Add a changelog message here -->\r\n' +
|
||||||
'This is a very useful fix.\r\n' +
|
'This is a very useful fix.\r\n' +
|
||||||
'\r\n' +
|
'\r\n' +
|
||||||
'#### Comment\r\n' +
|
'#### Comment ' +
|
||||||
`<!-- If the changes in this pull request don't warrant a changelog entry, you can alternatively supply a comment here. Note that comments are only accepted with a significance of "Patch" -->\r\n` +
|
`<!-- If the changes in this pull request don't warrant a changelog entry, you can alternatively supply a comment here. Note that comments are only accepted with a significance of "Patch" -->\r\n` +
|
||||||
'\r\n' +
|
'\r\n' +
|
||||||
'</details>';
|
'</details>';
|
||||||
|
@ -173,11 +174,11 @@ describe( 'getChangelogType', () => {
|
||||||
'- [ ] Performance - Address performance issues\r\n' +
|
'- [ ] Performance - Address performance issues\r\n' +
|
||||||
'- [ ] Enhancement\r\n' +
|
'- [ ] Enhancement\r\n' +
|
||||||
'\r\n' +
|
'\r\n' +
|
||||||
'#### Message\r\n' +
|
'#### Message ' +
|
||||||
'<!-- Add a changelog message here -->\r\n' +
|
'<!-- Add a changelog message here -->\r\n' +
|
||||||
'This is a very useful fix.\r\n' +
|
'This is a very useful fix.\r\n' +
|
||||||
'\r\n' +
|
'\r\n' +
|
||||||
'#### Comment\r\n' +
|
'#### Comment ' +
|
||||||
`<!-- If the changes in this pull request don't warrant a changelog entry, you can alternatively supply a comment here. Note that comments are only accepted with a significance of "Patch" -->\r\n` +
|
`<!-- If the changes in this pull request don't warrant a changelog entry, you can alternatively supply a comment here. Note that comments are only accepted with a significance of "Patch" -->\r\n` +
|
||||||
'\r\n' +
|
'\r\n' +
|
||||||
'</details>';
|
'</details>';
|
||||||
|
@ -212,11 +213,11 @@ describe( 'getChangelogType', () => {
|
||||||
'- [ ] Performance - Address performance issues\r\n' +
|
'- [ ] Performance - Address performance issues\r\n' +
|
||||||
'- [ ] Enhancement\r\n' +
|
'- [ ] Enhancement\r\n' +
|
||||||
'\r\n' +
|
'\r\n' +
|
||||||
'#### Message\r\n' +
|
'#### Message ' +
|
||||||
'<!-- Add a changelog message here -->\r\n' +
|
'<!-- Add a changelog message here -->\r\n' +
|
||||||
'This is a very useful fix.\r\n' +
|
'This is a very useful fix.\r\n' +
|
||||||
'\r\n' +
|
'\r\n' +
|
||||||
'#### Comment\r\n' +
|
'#### Comment ' +
|
||||||
`<!-- If the changes in this pull request don't warrant a changelog entry, you can alternatively supply a comment here. Note that comments are only accepted with a significance of "Patch" -->\r\n` +
|
`<!-- If the changes in this pull request don't warrant a changelog entry, you can alternatively supply a comment here. Note that comments are only accepted with a significance of "Patch" -->\r\n` +
|
||||||
'\r\n' +
|
'\r\n' +
|
||||||
'</details>';
|
'</details>';
|
||||||
|
@ -254,11 +255,11 @@ describe( 'getChangelogType', () => {
|
||||||
'- [ ] Performance - Address performance issues\r\n' +
|
'- [ ] Performance - Address performance issues\r\n' +
|
||||||
'- [ ] Enhancement\r\n' +
|
'- [ ] Enhancement\r\n' +
|
||||||
'\r\n' +
|
'\r\n' +
|
||||||
'#### Message\r\n' +
|
'#### Message ' +
|
||||||
'<!-- Add a changelog message here -->\r\n' +
|
'<!-- Add a changelog message here -->\r\n' +
|
||||||
'This is a very useful fix.\r\n' +
|
'This is a very useful fix.\r\n' +
|
||||||
'\r\n' +
|
'\r\n' +
|
||||||
'#### Comment\r\n' +
|
'#### Comment ' +
|
||||||
`<!-- If the changes in this pull request don't warrant a changelog entry, you can alternatively supply a comment here. Note that comments are only accepted with a significance of "Patch" -->\r\n` +
|
`<!-- If the changes in this pull request don't warrant a changelog entry, you can alternatively supply a comment here. Note that comments are only accepted with a significance of "Patch" -->\r\n` +
|
||||||
'\r\n' +
|
'\r\n' +
|
||||||
'</details>';
|
'</details>';
|
||||||
|
@ -298,11 +299,11 @@ describe( 'getChangelogDetails', () => {
|
||||||
'- [ ] Performance - Address performance issues\r\n' +
|
'- [ ] Performance - Address performance issues\r\n' +
|
||||||
'- [ ] Enhancement\r\n' +
|
'- [ ] Enhancement\r\n' +
|
||||||
'\r\n' +
|
'\r\n' +
|
||||||
'#### Message\r\n' +
|
'#### Message ' +
|
||||||
'<!-- Add a changelog message here -->\r\n' +
|
'<!-- Add a changelog message here -->\r\n' +
|
||||||
'This is a very useful fix.\r\n' +
|
'This is a very useful fix.\r\n' +
|
||||||
'\r\n' +
|
'\r\n' +
|
||||||
'#### Comment\r\n' +
|
'#### Comment ' +
|
||||||
`<!-- If the changes in this pull request don't warrant a changelog entry, you can alternatively supply a comment here. Note that comments are only accepted with a significance of "Patch" -->\r\n` +
|
`<!-- If the changes in this pull request don't warrant a changelog entry, you can alternatively supply a comment here. Note that comments are only accepted with a significance of "Patch" -->\r\n` +
|
||||||
'\r\n' +
|
'\r\n' +
|
||||||
'</details>';
|
'</details>';
|
||||||
|
@ -314,7 +315,7 @@ describe( 'getChangelogDetails', () => {
|
||||||
expect( details.comment ).toEqual( '' );
|
expect( details.comment ).toEqual( '' );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
it( 'should error if a comment and message are added', () => {
|
it( 'should provide comment and message when both are added', () => {
|
||||||
const body =
|
const body =
|
||||||
'### Changelog entry\r\n' +
|
'### Changelog entry\r\n' +
|
||||||
'\r\n' +
|
'\r\n' +
|
||||||
|
@ -340,24 +341,22 @@ describe( 'getChangelogDetails', () => {
|
||||||
'- [ ] Performance - Address performance issues\r\n' +
|
'- [ ] Performance - Address performance issues\r\n' +
|
||||||
'- [ ] Enhancement\r\n' +
|
'- [ ] Enhancement\r\n' +
|
||||||
'\r\n' +
|
'\r\n' +
|
||||||
'#### Message\r\n' +
|
'#### Message ' +
|
||||||
'<!-- Add a changelog message here -->\r\n' +
|
'<!-- Add a changelog message here -->\r\n' +
|
||||||
'This is a very useful fix.\r\n' +
|
'This is a very useful fix.\r\n' +
|
||||||
'\r\n' +
|
'\r\n' +
|
||||||
'#### Comment\r\n' +
|
'#### Comment ' +
|
||||||
`<!-- If the changes in this pull request don't warrant a changelog entry, you can alternatively supply a comment here. Note that comments are only accepted with a significance of "Patch" -->\r\n` +
|
`<!-- If the changes in this pull request don't warrant a changelog entry, you can alternatively supply a comment here. Note that comments are only accepted with a significance of "Patch" -->\r\n` +
|
||||||
'This is a very useful comment.\r\n' +
|
'This is a very useful comment.\r\n' +
|
||||||
'\r\n' +
|
'\r\n' +
|
||||||
'</details>';
|
'</details>';
|
||||||
|
|
||||||
const details = getChangelogDetails( body );
|
const details = getChangelogDetails( body );
|
||||||
expect( details ).toBeUndefined();
|
expect( details.message ).toEqual( 'This is a very useful fix.' );
|
||||||
expect( Logger.error ).toHaveBeenCalledWith(
|
expect( details.comment ).toEqual( 'This is a very useful comment.' );
|
||||||
'Both a message and comment were found. Only one can be entered'
|
|
||||||
);
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
it( 'should error if a comment is entered with a significance other than patch', () => {
|
it( 'should return a comment even when it is entered with a significance other than patch', () => {
|
||||||
const body =
|
const body =
|
||||||
'### Changelog entry\r\n' +
|
'### Changelog entry\r\n' +
|
||||||
'\r\n' +
|
'\r\n' +
|
||||||
|
@ -383,19 +382,73 @@ describe( 'getChangelogDetails', () => {
|
||||||
'- [ ] Performance - Address performance issues\r\n' +
|
'- [ ] Performance - Address performance issues\r\n' +
|
||||||
'- [ ] Enhancement\r\n' +
|
'- [ ] Enhancement\r\n' +
|
||||||
'\r\n' +
|
'\r\n' +
|
||||||
'#### Message\r\n' +
|
'#### Message ' +
|
||||||
'<!-- Add a changelog message here -->\r\n' +
|
'<!-- Add a changelog message here -->\r\n' +
|
||||||
'\r\n' +
|
'\r\n' +
|
||||||
'#### Comment\r\n' +
|
'#### Comment ' +
|
||||||
`<!-- If the changes in this pull request don't warrant a changelog entry, you can alternatively supply a comment here. Note that comments are only accepted with a significance of "Patch" -->\r\n` +
|
`<!-- If the changes in this pull request don't warrant a changelog entry, you can alternatively supply a comment here. Note that comments are only accepted with a significance of "Patch" -->\r\n` +
|
||||||
'This is a very useful comment.\r\n' +
|
'This is a very useful comment.\r\n' +
|
||||||
'\r\n' +
|
'\r\n' +
|
||||||
'</details>';
|
'</details>';
|
||||||
|
|
||||||
const details = getChangelogDetails( body );
|
const details = getChangelogDetails( body );
|
||||||
expect( details ).toBeUndefined();
|
expect( details.comment ).toEqual( 'This is a very useful comment.' );
|
||||||
expect( Logger.error ).toHaveBeenCalledWith(
|
expect( details.significance ).toEqual( 'minor' );
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
|
describe( 'getChangelogDetailsError', () => {
|
||||||
|
it( 'should return an error when both a message and comment provided', () => {
|
||||||
|
const error = getChangelogDetailsError( {
|
||||||
|
message: 'message',
|
||||||
|
comment: 'comment',
|
||||||
|
type: 'fix',
|
||||||
|
significance: 'minor',
|
||||||
|
} );
|
||||||
|
expect( error ).toEqual(
|
||||||
|
'Both a message and comment were found. Only one can be entered'
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
it( 'should return an error when a comment is provided with a significance other than patch', () => {
|
||||||
|
const error = getChangelogDetailsError( {
|
||||||
|
message: '',
|
||||||
|
comment: 'comment',
|
||||||
|
type: 'fix',
|
||||||
|
significance: 'minor',
|
||||||
|
} );
|
||||||
|
expect( error ).toEqual(
|
||||||
'Only patch changes can have a comment. Please change the significance to patch or remove the comment'
|
'Only patch changes can have a comment. Please change the significance to patch or remove the comment'
|
||||||
);
|
);
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
it( 'should return an error when no significance found', () => {
|
||||||
|
const error = getChangelogDetailsError( {
|
||||||
|
message: 'message',
|
||||||
|
comment: '',
|
||||||
|
type: 'fix',
|
||||||
|
significance: '',
|
||||||
|
} );
|
||||||
|
expect( error ).toEqual( 'No changelog significance found' );
|
||||||
|
} );
|
||||||
|
|
||||||
|
it( 'should return an error when no type found', () => {
|
||||||
|
const error = getChangelogDetailsError( {
|
||||||
|
message: 'message',
|
||||||
|
comment: '',
|
||||||
|
type: '',
|
||||||
|
significance: 'minor',
|
||||||
|
} );
|
||||||
|
expect( error ).toEqual( 'No changelog type found' );
|
||||||
|
} );
|
||||||
|
|
||||||
|
it( 'should return an error when neither a comment or message is provided', () => {
|
||||||
|
const error = getChangelogDetailsError( {
|
||||||
|
message: '',
|
||||||
|
comment: '',
|
||||||
|
type: 'fix',
|
||||||
|
significance: 'minor',
|
||||||
|
} );
|
||||||
|
expect( error ).toEqual( 'No changelog message or comment found' );
|
||||||
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
|
@ -113,7 +113,7 @@ export const getChangelogType = ( body: string ) => {
|
||||||
* @return {void|string} changelog message.
|
* @return {void|string} changelog message.
|
||||||
*/
|
*/
|
||||||
export const getChangelogMessage = ( body: string ) => {
|
export const getChangelogMessage = ( body: string ) => {
|
||||||
const messageRegex = /#### Message\r\n(<!--(.*)-->)?(.*)#### Comment/gms;
|
const messageRegex = /#### Message ?(<!--(.*)-->)?(.*)#### Comment/gms;
|
||||||
const match = messageRegex.exec( body );
|
const match = messageRegex.exec( body );
|
||||||
|
|
||||||
if ( ! match ) {
|
if ( ! match ) {
|
||||||
|
@ -130,38 +130,62 @@ export const getChangelogMessage = ( body: string ) => {
|
||||||
* @return {void|string} changelog comment.
|
* @return {void|string} changelog comment.
|
||||||
*/
|
*/
|
||||||
export const getChangelogComment = ( body: string ) => {
|
export const getChangelogComment = ( body: string ) => {
|
||||||
const commentRegex = /#### Comment\r\n(<!--(.*)-->)?(.*)<\/details>/gms;
|
const commentRegex = /#### Comment ?(<!--(.*)-->)?(.*)<\/details>/gms;
|
||||||
const match = commentRegex.exec( body );
|
const match = commentRegex.exec( body );
|
||||||
|
|
||||||
return match ? match[ 3 ].trim() : '';
|
return match ? match[ 3 ].trim() : '';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the changelog details from a pull request description.
|
||||||
|
*
|
||||||
|
* @param {string} body Pull request description
|
||||||
|
* @return {Object} Changelog details
|
||||||
|
*/
|
||||||
export const getChangelogDetails = ( body: string ) => {
|
export const getChangelogDetails = ( body: string ) => {
|
||||||
const message = getChangelogMessage( body );
|
|
||||||
const comment = getChangelogComment( body );
|
|
||||||
|
|
||||||
if ( comment && message ) {
|
|
||||||
Logger.error(
|
|
||||||
'Both a message and comment were found. Only one can be entered'
|
|
||||||
);
|
|
||||||
// Logger.error has a process.exit( 1 ) call, this return is purely for testing purposes.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const significance = getChangelogSignificance( body );
|
|
||||||
|
|
||||||
if ( comment && significance !== 'patch' ) {
|
|
||||||
Logger.error(
|
|
||||||
'Only patch changes can have a comment. Please change the significance to patch or remove the comment'
|
|
||||||
);
|
|
||||||
// Logger.error has a process.exit( 1 ) call, this return is purely for testing purposes.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
significance,
|
significance: getChangelogSignificance( body ),
|
||||||
type: getChangelogType( body ),
|
type: getChangelogType( body ),
|
||||||
message,
|
message: getChangelogMessage( body ),
|
||||||
comment,
|
comment: getChangelogComment( body ),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if a pull request description contains changelog input errors.
|
||||||
|
*
|
||||||
|
* @param {Object} details changelog details.
|
||||||
|
* @param {string} details.significance changelog significance.
|
||||||
|
* @param {string} details.type changelog type.
|
||||||
|
* @param {string} details.message changelog message.
|
||||||
|
* @param {string} details.comment changelog comment.
|
||||||
|
* @return {string|null} error message, or null if none found
|
||||||
|
*/
|
||||||
|
export const getChangelogDetailsError = ( {
|
||||||
|
significance,
|
||||||
|
type,
|
||||||
|
message,
|
||||||
|
comment,
|
||||||
|
}: {
|
||||||
|
significance?: string;
|
||||||
|
type?: string;
|
||||||
|
message?: string;
|
||||||
|
comment?: string;
|
||||||
|
} ) => {
|
||||||
|
if ( comment && message ) {
|
||||||
|
return 'Both a message and comment were found. Only one can be entered';
|
||||||
|
}
|
||||||
|
if ( comment && significance !== 'patch' ) {
|
||||||
|
return 'Only patch changes can have a comment. Please change the significance to patch or remove the comment';
|
||||||
|
}
|
||||||
|
if ( ! significance ) {
|
||||||
|
return 'No changelog significance found';
|
||||||
|
}
|
||||||
|
if ( ! type ) {
|
||||||
|
return 'No changelog type found';
|
||||||
|
}
|
||||||
|
if ( ! comment && ! message ) {
|
||||||
|
return 'No changelog message or comment found';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
|
@ -7,6 +7,10 @@ import path from 'path';
|
||||||
import { glob } from 'glob';
|
import { glob } from 'glob';
|
||||||
import simpleGit from 'simple-git';
|
import simpleGit from 'simple-git';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal dependencies
|
||||||
|
*/
|
||||||
|
import { getAuthenticatedRemote } from '../../core/git';
|
||||||
/**
|
/**
|
||||||
* Get all projects listed in the workspace yaml file.
|
* Get all projects listed in the workspace yaml file.
|
||||||
*
|
*
|
||||||
|
@ -32,7 +36,8 @@ export const getAllProjectsPathsFromWorkspace = async (
|
||||||
return project;
|
return project;
|
||||||
} )
|
} )
|
||||||
);
|
);
|
||||||
return globbedProjects.flat();
|
const r = globbedProjects.flat();
|
||||||
|
return r;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -72,13 +77,17 @@ export const getChangeloggerProjectPaths = async (
|
||||||
* @param {string} base base hash
|
* @param {string} base base hash
|
||||||
* @param {string} head head hash
|
* @param {string} head head hash
|
||||||
* @param {string} fileName changelog file name
|
* @param {string} fileName changelog file name
|
||||||
|
* @param {string} baseOwner PR base owner
|
||||||
|
* @param {string} baseName PR base name
|
||||||
* @return {Array<string>} List of files changed in a PR.
|
* @return {Array<string>} List of files changed in a PR.
|
||||||
*/
|
*/
|
||||||
export const getTouchedFilePaths = async (
|
export const getTouchedFilePaths = async (
|
||||||
tmpRepoPath: string,
|
tmpRepoPath: string,
|
||||||
base: string,
|
base: string,
|
||||||
head: string,
|
head: string,
|
||||||
fileName: string
|
fileName: string,
|
||||||
|
baseOwner: string,
|
||||||
|
baseName: string
|
||||||
) => {
|
) => {
|
||||||
const git = simpleGit( {
|
const git = simpleGit( {
|
||||||
baseDir: tmpRepoPath,
|
baseDir: tmpRepoPath,
|
||||||
|
@ -86,13 +95,12 @@ export const getTouchedFilePaths = async (
|
||||||
} );
|
} );
|
||||||
|
|
||||||
// make sure base sha is available.
|
// make sure base sha is available.
|
||||||
await git.raw( [
|
await git.addRemote(
|
||||||
'remote',
|
baseOwner,
|
||||||
'add',
|
getAuthenticatedRemote( { owner: baseOwner, name: baseName } )
|
||||||
'woocommerce',
|
);
|
||||||
'git@github.com:woocommerce/woocommerce.git',
|
await git.fetch( baseOwner, base );
|
||||||
] );
|
|
||||||
await git.raw( [ 'fetch', 'woocommerce', base ] );
|
|
||||||
const diff = await git.raw( [
|
const diff = await git.raw( [
|
||||||
'diff',
|
'diff',
|
||||||
'--name-only',
|
'--name-only',
|
||||||
|
@ -101,7 +109,7 @@ export const getTouchedFilePaths = async (
|
||||||
return (
|
return (
|
||||||
diff
|
diff
|
||||||
.split( '\n' )
|
.split( '\n' )
|
||||||
.filter( ( item ) => item.trim() )
|
.map( ( item ) => item.trim() )
|
||||||
// Don't count changelogs themselves as touched files.
|
// Don't count changelogs themselves as touched files.
|
||||||
.filter( ( item ) => ! item.includes( `/changelog/${ fileName }` ) )
|
.filter( ( item ) => ! item.includes( `/changelog/${ fileName }` ) )
|
||||||
);
|
);
|
||||||
|
@ -165,13 +173,17 @@ export const getAllProjectPaths = async ( tmpRepoPath: string ) => {
|
||||||
* @param {string} base base hash
|
* @param {string} base base hash
|
||||||
* @param {string} head head hash
|
* @param {string} head head hash
|
||||||
* @param {string} fileName changelog file name
|
* @param {string} fileName changelog file name
|
||||||
|
* @param {string} baseOwner PR base owner
|
||||||
|
* @param {string} baseName PR base name
|
||||||
* @return {Array<string>} List of projects that have Jetpack changelogger enabled and have files changed in a PR.
|
* @return {Array<string>} List of projects that have Jetpack changelogger enabled and have files changed in a PR.
|
||||||
*/
|
*/
|
||||||
export const getTouchedProjectsRequiringChangelog = async (
|
export const getTouchedProjectsRequiringChangelog = async (
|
||||||
tmpRepoPath: string,
|
tmpRepoPath: string,
|
||||||
base: string,
|
base: string,
|
||||||
head: string,
|
head: string,
|
||||||
fileName: string
|
fileName: string,
|
||||||
|
baseOwner: string,
|
||||||
|
baseName: string
|
||||||
) => {
|
) => {
|
||||||
const allProjectPaths = await getAllProjectPaths( tmpRepoPath );
|
const allProjectPaths = await getAllProjectPaths( tmpRepoPath );
|
||||||
const changeloggerProjectsPaths = await getChangeloggerProjectPaths(
|
const changeloggerProjectsPaths = await getChangeloggerProjectPaths(
|
||||||
|
@ -182,7 +194,9 @@ export const getTouchedProjectsRequiringChangelog = async (
|
||||||
tmpRepoPath,
|
tmpRepoPath,
|
||||||
base,
|
base,
|
||||||
head,
|
head,
|
||||||
fileName
|
fileName,
|
||||||
|
baseOwner,
|
||||||
|
baseName
|
||||||
);
|
);
|
||||||
|
|
||||||
return getTouchedChangeloggerProjectsPathsMappedToProjects(
|
return getTouchedChangeloggerProjectsPathsMappedToProjects(
|
||||||
|
|
|
@ -115,6 +115,24 @@ export const cloneRepoShallow = async ( repoPath: string ) => {
|
||||||
return await cloneRepo( repoPath, { '--depth': 1 } );
|
return await cloneRepo( repoPath, { '--depth': 1 } );
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a remote using the authenticated token `GITHUB_TOKEN`
|
||||||
|
*
|
||||||
|
* @param {Object} options CLI options
|
||||||
|
* @param {string} options.owner repo owner
|
||||||
|
* @param {string} options.name repo name
|
||||||
|
* @return {string} remote
|
||||||
|
*/
|
||||||
|
export const getAuthenticatedRemote = ( options: {
|
||||||
|
owner: string;
|
||||||
|
name: string;
|
||||||
|
} ) => {
|
||||||
|
const { owner, name } = options;
|
||||||
|
const source = `github.com/${ owner }/${ name }`;
|
||||||
|
const token = getEnvVar( 'GITHUB_TOKEN', true );
|
||||||
|
return `https://${ owner }:${ token }@${ source }`;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clone a repo using the authenticated token `GITHUB_TOKEN`. This allows the script to push branches to origin.
|
* Clone a repo using the authenticated token `GITHUB_TOKEN`. This allows the script to push branches to origin.
|
||||||
*
|
*
|
||||||
|
@ -128,10 +146,7 @@ export const cloneAuthenticatedRepo = async (
|
||||||
options: { owner: string; name: string },
|
options: { owner: string; name: string },
|
||||||
isShallow = true
|
isShallow = true
|
||||||
): Promise< string > => {
|
): Promise< string > => {
|
||||||
const { owner, name } = options;
|
const remote = getAuthenticatedRemote( options );
|
||||||
const source = `github.com/${ owner }/${ name }`;
|
|
||||||
const token = getEnvVar( 'GITHUB_TOKEN' );
|
|
||||||
const remote = `https://${ owner }:${ token }@${ source }`;
|
|
||||||
|
|
||||||
return isShallow
|
return isShallow
|
||||||
? await cloneRepoShallow( remote )
|
? await cloneRepoShallow( remote )
|
||||||
|
|
|
@ -212,10 +212,6 @@ export const isCommunityPullRequest = (
|
||||||
owner: string,
|
owner: string,
|
||||||
name: string
|
name: string
|
||||||
) => {
|
) => {
|
||||||
return (
|
// We can't use author_association here because it can be changed by PR authors. Instead check PR source.
|
||||||
pullRequestData.author_association === 'CONTRIBUTOR' ||
|
return pullRequestData.head.repo.full_name !== `${ owner }/${ name }`;
|
||||||
// It's possible a MEMBER can open a PR from their own fork.
|
|
||||||
( pullRequestData.author_association === 'MEMBER' &&
|
|
||||||
pullRequestData.head.repo.full_name !== `${ owner }/${ name }` )
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue