Code Freeze CLI: Add release changelog command (#38082)
This commit is contained in:
parent
68fe31abe4
commit
1188197a2f
|
@ -3250,6 +3250,9 @@ importers:
|
|||
'@octokit/graphql-schema':
|
||||
specifier: ^14.1.0
|
||||
version: 14.1.0
|
||||
'@octokit/types':
|
||||
specifier: ^9.2.0
|
||||
version: 9.2.1
|
||||
'@types/uuid':
|
||||
specifier: ^9.0.1
|
||||
version: 9.0.1
|
||||
|
@ -3507,43 +3510,6 @@ importers:
|
|||
specifier: ^5.70.0
|
||||
version: 5.70.0(uglify-js@3.14.5)(webpack-cli@4.9.2)
|
||||
|
||||
tools/version-bump:
|
||||
dependencies:
|
||||
'@commander-js/extra-typings':
|
||||
specifier: ^0.1.0
|
||||
version: 0.1.0(commander@9.4.0)
|
||||
'@woocommerce/monorepo-utils':
|
||||
specifier: workspace:*
|
||||
version: link:../monorepo-utils
|
||||
chalk:
|
||||
specifier: ^4.1.2
|
||||
version: 4.1.2
|
||||
commander:
|
||||
specifier: 9.4.0
|
||||
version: 9.4.0
|
||||
express:
|
||||
specifier: ^4.18.1
|
||||
version: 4.18.1
|
||||
ora:
|
||||
specifier: ^5.4.1
|
||||
version: 5.4.1
|
||||
semver:
|
||||
specifier: ^7.3.2
|
||||
version: 7.3.7
|
||||
ts-node:
|
||||
specifier: ^10.9.1
|
||||
version: 10.9.1(@types/node@16.18.21)(typescript@4.9.5)
|
||||
devDependencies:
|
||||
'@tsconfig/node16':
|
||||
specifier: ^1.0.3
|
||||
version: 1.0.3
|
||||
'@types/express':
|
||||
specifier: ^4.17.13
|
||||
version: 4.17.14
|
||||
typescript:
|
||||
specifier: ^4.9.5
|
||||
version: 4.9.5
|
||||
|
||||
packages:
|
||||
|
||||
/@actions/core@1.10.0:
|
||||
|
@ -3871,7 +3837,7 @@ packages:
|
|||
'@babel/core': ^7.0.0-0
|
||||
dependencies:
|
||||
'@babel/core': 7.21.3
|
||||
'@jridgewell/trace-mapping': 0.3.17
|
||||
'@jridgewell/trace-mapping': 0.3.16
|
||||
commander: 4.1.1
|
||||
convert-source-map: 1.8.0
|
||||
fs-readdir-recursive: 1.1.0
|
||||
|
@ -8720,9 +8686,9 @@ packages:
|
|||
'@babel/core': 7.21.3
|
||||
'@babel/helper-annotate-as-pure': 7.16.7
|
||||
'@babel/helper-module-imports': 7.16.7
|
||||
'@babel/helper-plugin-utils': 7.18.9
|
||||
'@babel/helper-plugin-utils': 7.20.2
|
||||
'@babel/plugin-syntax-jsx': 7.16.7(@babel/core@7.21.3)
|
||||
'@babel/types': 7.17.0
|
||||
'@babel/types': 7.21.3
|
||||
dev: true
|
||||
|
||||
/@babel/plugin-transform-react-jsx@7.19.0(@babel/core@7.12.9):
|
||||
|
@ -8951,8 +8917,8 @@ packages:
|
|||
dependencies:
|
||||
'@babel/core': 7.21.3
|
||||
'@babel/helper-module-imports': 7.16.0
|
||||
'@babel/helper-plugin-utils': 7.20.2
|
||||
babel-plugin-polyfill-corejs2: 0.3.3(@babel/core@7.21.3)
|
||||
'@babel/helper-plugin-utils': 7.14.5
|
||||
babel-plugin-polyfill-corejs2: 0.3.0(@babel/core@7.21.3)
|
||||
babel-plugin-polyfill-corejs3: 0.4.0(@babel/core@7.21.3)
|
||||
babel-plugin-polyfill-regenerator: 0.3.0(@babel/core@7.21.3)
|
||||
semver: 6.3.0
|
||||
|
@ -11969,7 +11935,6 @@ packages:
|
|||
dependencies:
|
||||
'@jridgewell/resolve-uri': 3.1.0
|
||||
'@jridgewell/sourcemap-codec': 1.4.14
|
||||
dev: true
|
||||
|
||||
/@jridgewell/trace-mapping@0.3.17:
|
||||
resolution: {integrity: sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==}
|
||||
|
@ -12494,7 +12459,7 @@ packages:
|
|||
'@octokit/graphql': 4.8.0
|
||||
'@octokit/request': 5.6.3
|
||||
'@octokit/request-error': 2.1.0
|
||||
'@octokit/types': 6.34.0
|
||||
'@octokit/types': 6.41.0
|
||||
before-after-hook: 2.2.2
|
||||
universal-user-agent: 6.0.0
|
||||
transitivePeerDependencies:
|
||||
|
@ -12594,10 +12559,6 @@ packages:
|
|||
- encoding
|
||||
dev: false
|
||||
|
||||
/@octokit/openapi-types@11.2.0:
|
||||
resolution: {integrity: sha512-PBsVO+15KSlGmiI8QAzaqvsNlZlrDlyAJYcrXBCvVUxCp7VnXjkwPoFHgjEJXx3WF9BAwkA6nfCUA7i9sODzKA==}
|
||||
dev: true
|
||||
|
||||
/@octokit/openapi-types@12.11.0:
|
||||
resolution: {integrity: sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==}
|
||||
|
||||
|
@ -12794,12 +12755,6 @@ packages:
|
|||
- encoding
|
||||
dev: false
|
||||
|
||||
/@octokit/types@6.34.0:
|
||||
resolution: {integrity: sha512-s1zLBjWhdEI2zwaoSgyOFoKSl109CUcVBCc7biPJ3aAf6LGLU6szDvi31JPU7bxfla2lqfhjbbg/5DdFNxOwHw==}
|
||||
dependencies:
|
||||
'@octokit/openapi-types': 11.2.0
|
||||
dev: true
|
||||
|
||||
/@octokit/types@6.41.0:
|
||||
resolution: {integrity: sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==}
|
||||
dependencies:
|
||||
|
@ -20857,8 +20812,8 @@ packages:
|
|||
peerDependencies:
|
||||
postcss: ^8.1.0
|
||||
dependencies:
|
||||
browserslist: 4.20.2
|
||||
caniuse-lite: 1.0.30001352
|
||||
browserslist: 4.21.4
|
||||
caniuse-lite: 1.0.30001418
|
||||
fraction.js: 4.2.0
|
||||
normalize-range: 0.1.2
|
||||
picocolors: 1.0.0
|
||||
|
@ -22401,6 +22356,7 @@ packages:
|
|||
escalade: 3.1.1
|
||||
node-releases: 2.0.6
|
||||
picocolors: 1.0.0
|
||||
dev: true
|
||||
|
||||
/browserslist@4.20.4:
|
||||
resolution: {integrity: sha512-ok1d+1WpnU24XYN7oC3QWgTyMhY/avPJ/r9T00xxvUOIparA/gc+UPUMaod3i+G6s+nI2nUb9xZ5k794uIwShw==}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
"@commander-js/extra-typings": "^10.0.3",
|
||||
"@octokit/graphql": "4.8.0",
|
||||
"@octokit/graphql-schema": "^14.1.0",
|
||||
"@octokit/types": "^9.2.0",
|
||||
"@types/uuid": "^9.0.1",
|
||||
"chalk": "^4.1.2",
|
||||
"commander": "^10.0.1",
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { Command } from '@commander-js/extra-typings';
|
||||
import { execSync } from 'child_process';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { Logger } from '../../../core/logger';
|
||||
import { cloneAuthenticatedRepo } from '../../../core/git';
|
||||
import { updateTrunkChangelog, updateReleaseBranchChangelogs } from './lib';
|
||||
import { Options } from './types';
|
||||
|
||||
export const changelogCommand = new Command( 'changelog' )
|
||||
.description( 'Create a new release branch' )
|
||||
.option(
|
||||
'-o --owner <owner>',
|
||||
'Repository owner. Default: woocommerce',
|
||||
'woocommerce'
|
||||
)
|
||||
.option(
|
||||
'-n --name <name>',
|
||||
'Repository name. Default: woocommerce',
|
||||
'woocommerce'
|
||||
)
|
||||
.option(
|
||||
'-d --dev-repo-path <devRepoPath>',
|
||||
'Path to existing repo. Use this option to avoid cloning a fresh repo for development purposes. Note that using this option assumes dependencies are already installed.'
|
||||
)
|
||||
.requiredOption( '-v, --version <version>', 'Version to bump to' )
|
||||
.action( async ( options: Options ) => {
|
||||
const { owner, name, version, devRepoPath } = options;
|
||||
Logger.startTask(
|
||||
`Making a temporary clone of '${ owner }/${ name }'`
|
||||
);
|
||||
// Use a supplied path, otherwise do a full clone of the repo, including history so that changelogs can be created with links to PRs.
|
||||
const tmpRepoPath = devRepoPath
|
||||
? devRepoPath
|
||||
: await cloneAuthenticatedRepo( options, false );
|
||||
|
||||
Logger.endTask();
|
||||
|
||||
Logger.notice(
|
||||
`Temporary clone of '${ owner }/${ 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 --filter woocommerce', {
|
||||
cwd: tmpRepoPath,
|
||||
stdio: 'inherit',
|
||||
} );
|
||||
}
|
||||
|
||||
const releaseBranch = `release/${ version }`;
|
||||
|
||||
// Update the release branch.
|
||||
const releaseBranchChanges = await updateReleaseBranchChangelogs(
|
||||
options,
|
||||
tmpRepoPath,
|
||||
releaseBranch
|
||||
);
|
||||
|
||||
// Update trunk.
|
||||
await updateTrunkChangelog(
|
||||
options,
|
||||
tmpRepoPath,
|
||||
releaseBranch,
|
||||
releaseBranchChanges
|
||||
);
|
||||
} );
|
|
@ -0,0 +1,153 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import simpleGit from 'simple-git';
|
||||
import { execSync } from 'child_process';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { Logger } from '../../../../core/logger';
|
||||
import { checkoutRemoteBranch } from '../../../../core/git';
|
||||
import { createPullRequest } from '../../../../core/github/repo';
|
||||
import { Options } from '../types';
|
||||
|
||||
/**
|
||||
* Perform changelog operations on release branch by submitting a pull request. The release branch is a remote branch.
|
||||
*
|
||||
* @param {Object} options CLI options
|
||||
* @param {string} tmpRepoPath temp repo path
|
||||
* @param {string} releaseBranch release branch name. The release branch is a remote branch on Github.
|
||||
* @return {Object} update data
|
||||
*/
|
||||
export const updateReleaseBranchChangelogs = async (
|
||||
options: Options,
|
||||
tmpRepoPath: string,
|
||||
releaseBranch: string
|
||||
): Promise< { deletionCommitHash: string; prNumber: number } > => {
|
||||
const { owner, name, version } = options;
|
||||
try {
|
||||
await checkoutRemoteBranch( tmpRepoPath, releaseBranch );
|
||||
} catch ( e ) {
|
||||
if ( e.message.includes( "couldn't find remote ref" ) ) {
|
||||
Logger.error(
|
||||
`${ releaseBranch } does not exist on ${ owner }/${ name }.`
|
||||
);
|
||||
}
|
||||
Logger.error( e );
|
||||
}
|
||||
|
||||
const git = simpleGit( {
|
||||
baseDir: tmpRepoPath,
|
||||
config: [ 'core.hooksPath=/dev/null' ],
|
||||
} );
|
||||
|
||||
const branch = `update/${ version }-changelog`;
|
||||
|
||||
try {
|
||||
await git.checkout( {
|
||||
'-b': null,
|
||||
[ branch ]: null,
|
||||
} );
|
||||
|
||||
Logger.notice( `Running the changelog script in ${ tmpRepoPath }` );
|
||||
execSync(
|
||||
`pnpm --filter=woocommerce run changelog write --add-pr-num -n -vvv --use-version ${ version }`,
|
||||
{
|
||||
cwd: tmpRepoPath,
|
||||
stdio: 'inherit',
|
||||
}
|
||||
);
|
||||
Logger.notice( `Committing deleted files in ${ tmpRepoPath }` );
|
||||
//Checkout pnpm-lock.yaml to prevent issues in case of an out of date lockfile.
|
||||
await git.checkout( 'pnpm-lock.yaml' );
|
||||
await git.add( 'plugins/woocommerce/changelog/' );
|
||||
await git.commit( `Delete changelog files from ${ version } release` );
|
||||
const deletionCommitHash = await git.raw( [ 'rev-parse', 'HEAD' ] );
|
||||
Logger.notice( `git deletion hash: ${ deletionCommitHash }` );
|
||||
|
||||
Logger.notice( `Updating readme.txt in ${ tmpRepoPath }` );
|
||||
execSync( 'php .github/workflows/scripts/release-changelog.php', {
|
||||
cwd: tmpRepoPath,
|
||||
stdio: 'inherit',
|
||||
} );
|
||||
|
||||
Logger.notice(
|
||||
`Committing readme.txt changes in ${ branch } on ${ tmpRepoPath }`
|
||||
);
|
||||
await git.add( 'plugins/woocommerce/readme.txt' );
|
||||
await git.commit(
|
||||
`Update the readme files for the ${ version } release`
|
||||
);
|
||||
await git.push( 'origin', branch );
|
||||
await git.checkout( '.' );
|
||||
|
||||
Logger.notice( `Creating PR for ${ branch }` );
|
||||
const pullRequest = await createPullRequest( {
|
||||
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 }`,
|
||||
head: branch,
|
||||
base: releaseBranch,
|
||||
} );
|
||||
Logger.notice( `Pull request created: ${ pullRequest.html_url }` );
|
||||
return {
|
||||
deletionCommitHash: deletionCommitHash.trim(),
|
||||
prNumber: pullRequest.number,
|
||||
};
|
||||
} catch ( e ) {
|
||||
Logger.error( e );
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Perform changelog operations on trunk by submitting a pull request.
|
||||
*
|
||||
* @param {Object} options CLI options
|
||||
* @param {string} tmpRepoPath temp repo path
|
||||
* @param {string} releaseBranch release branch name
|
||||
* @param {Object} releaseBranchChanges update data from updateReleaseBranchChangelogs
|
||||
* @param {Object} releaseBranchChanges.deletionCommitHash commit from the changelog deletions in updateReleaseBranchChangelogs
|
||||
* @param {Object} releaseBranchChanges.prNumber pr number created in updateReleaseBranchChangelogs
|
||||
*/
|
||||
export const updateTrunkChangelog = async (
|
||||
options: Options,
|
||||
tmpRepoPath: string,
|
||||
releaseBranch: string,
|
||||
releaseBranchChanges: { deletionCommitHash: string; prNumber: number }
|
||||
): Promise< void > => {
|
||||
const { owner, name, version } = options;
|
||||
const { deletionCommitHash, prNumber } = releaseBranchChanges;
|
||||
Logger.notice( `Deleting changelogs from trunk ${ tmpRepoPath }` );
|
||||
const git = simpleGit( {
|
||||
baseDir: tmpRepoPath,
|
||||
config: [ 'core.hooksPath=/dev/null' ],
|
||||
} );
|
||||
|
||||
try {
|
||||
await git.checkout( 'trunk' );
|
||||
const branch = `delete/${ version }-changelog`;
|
||||
Logger.notice(
|
||||
`Committing deletions in ${ branch } on ${ tmpRepoPath }`
|
||||
);
|
||||
await git.checkout( {
|
||||
'-b': null,
|
||||
[ branch ]: null,
|
||||
} );
|
||||
await git.raw( [ 'cherry-pick', deletionCommitHash ] );
|
||||
await git.push( 'origin', branch );
|
||||
Logger.notice( `Creating PR for ${ branch }` );
|
||||
const pullRequest = await createPullRequest( {
|
||||
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 }\` branch via #${ prNumber }`,
|
||||
head: branch,
|
||||
base: 'trunk',
|
||||
} );
|
||||
Logger.notice( `Pull request created: ${ pullRequest.html_url }` );
|
||||
} catch ( e ) {
|
||||
Logger.error( e );
|
||||
}
|
||||
};
|
|
@ -0,0 +1,6 @@
|
|||
export type Options = {
|
||||
owner: string;
|
||||
name: string;
|
||||
version: string;
|
||||
devRepoPath?: string;
|
||||
};
|
|
@ -10,12 +10,14 @@ import { verifyDayCommand } from './verify-day';
|
|||
import { milestoneCommand } from './milestone';
|
||||
import { branchCommand } from './branch';
|
||||
import { versionBumpCommand } from './version-bump';
|
||||
import { changelogCommand } from './changelog';
|
||||
|
||||
const program = new Command( 'code-freeze' )
|
||||
.description( 'Code freeze utilities' )
|
||||
.addCommand( verifyDayCommand )
|
||||
.addCommand( milestoneCommand )
|
||||
.addCommand( branchCommand )
|
||||
.addCommand( versionBumpCommand );
|
||||
.addCommand( versionBumpCommand )
|
||||
.addCommand( changelogCommand );
|
||||
|
||||
export default program;
|
||||
|
|
|
@ -9,7 +9,7 @@ import simpleGit from 'simple-git';
|
|||
*/
|
||||
import { Logger } from '../../../core/logger';
|
||||
import { sparseCheckoutRepoShallow } from '../../../core/git';
|
||||
import { octokitWithAuth } from '../../../core/github/api';
|
||||
import { createPullRequest } from '../../../core/github/repo';
|
||||
import { getEnvVar } from '../../../core/environment';
|
||||
import { getMajorMinor } from '../../../core/version';
|
||||
import { bumpFiles } from './bump';
|
||||
|
@ -101,18 +101,16 @@ export const versionBumpCommand = new Command( 'version-bump' )
|
|||
|
||||
try {
|
||||
Logger.startTask( 'Creating a pull request' );
|
||||
const pr = await octokitWithAuth.request(
|
||||
'POST /repos/{owner}/{repo}/pulls',
|
||||
{
|
||||
owner,
|
||||
repo: name,
|
||||
title: `Prep trunk for ${ majorMinor } cycle`,
|
||||
body: `This PR updates the versions in trunk to ${ version } for next development cycle.`,
|
||||
head: branch,
|
||||
base,
|
||||
}
|
||||
);
|
||||
Logger.notice( `Pull request created: ${ pr.data.html_url }` );
|
||||
|
||||
const pullRequest = await createPullRequest( {
|
||||
owner,
|
||||
name,
|
||||
title: `Prep trunk for ${ majorMinor } cycle`,
|
||||
body: `This PR updates the versions in trunk to ${ version } for next development cycle.`,
|
||||
head: branch,
|
||||
base,
|
||||
} );
|
||||
Logger.notice( `Pull request created: ${ pullRequest.html_url }` );
|
||||
Logger.endTask();
|
||||
} catch ( e ) {
|
||||
Logger.error( e );
|
||||
|
|
|
@ -10,6 +10,11 @@ import { v4 } from 'uuid';
|
|||
import { mkdir, rm } from 'fs/promises';
|
||||
import { URL } from 'node:url';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { getEnvVar } from './environment';
|
||||
|
||||
/**
|
||||
* Get filename from patch
|
||||
*
|
||||
|
@ -110,6 +115,29 @@ export const cloneRepoShallow = async ( repoPath: string ) => {
|
|||
return await cloneRepo( repoPath, { '--depth': 1 } );
|
||||
};
|
||||
|
||||
/**
|
||||
* Clone a repo using the authenticated token `GITHUB_TOKEN`. This allows the script to push branches to origin.
|
||||
*
|
||||
* @param {Object} options CLI options
|
||||
* @param {string} options.owner repo owner
|
||||
* @param {string} options.name repo name
|
||||
* @param {boolean} isShallow whether to do a shallow clone or not.
|
||||
* @return {string} temporary repo path
|
||||
*/
|
||||
export const cloneAuthenticatedRepo = async (
|
||||
options: { owner: string; name: string },
|
||||
isShallow = true
|
||||
): Promise< string > => {
|
||||
const { owner, name } = options;
|
||||
const source = `github.com/${ owner }/${ name }`;
|
||||
const token = getEnvVar( 'GITHUB_TOKEN' );
|
||||
const remote = `https://${ owner }:${ token }@${ source }`;
|
||||
|
||||
return isShallow
|
||||
? await cloneRepoShallow( remote )
|
||||
: await cloneRepo( remote );
|
||||
};
|
||||
|
||||
/**
|
||||
* Do a minimal sparse checkout of a github repo.
|
||||
*
|
||||
|
@ -391,3 +419,23 @@ export const generateDiff = async (
|
|||
return '';
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} tmpRepoPath path to temporary repo
|
||||
* @param {string} branch remote branch to checkout
|
||||
*/
|
||||
export const checkoutRemoteBranch = async (
|
||||
tmpRepoPath: string,
|
||||
branch: string
|
||||
): Promise< void > => {
|
||||
const git = simpleGit( {
|
||||
baseDir: tmpRepoPath,
|
||||
config: [ 'core.hooksPath=/dev/null' ],
|
||||
} );
|
||||
|
||||
// When the clone is shallow, we need to call this before fetching.
|
||||
await git.raw( [ 'remote', 'set-branches', '--add', 'origin', branch ] );
|
||||
await git.raw( [ 'fetch', 'origin', branch ] );
|
||||
await git.raw( [ 'checkout', '-b', branch, `origin/${ branch }` ] );
|
||||
};
|
||||
|
|
|
@ -4,12 +4,17 @@
|
|||
import { graphql } from '@octokit/graphql';
|
||||
import { Octokit } from 'octokit';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { getEnvVar } from '../environment';
|
||||
|
||||
export const graphqlWithAuth = graphql.defaults( {
|
||||
headers: {
|
||||
authorization: `Bearer ${ process.env.GITHUB_TOKEN }`,
|
||||
authorization: `Bearer ${ getEnvVar( 'GITHUB_TOKEN', true ) }`,
|
||||
},
|
||||
} );
|
||||
|
||||
export const octokitWithAuth = new Octokit( {
|
||||
auth: process.env.GITHUB_TOKEN,
|
||||
auth: getEnvVar( 'GITHUB_TOKEN', true ),
|
||||
} );
|
||||
|
|
|
@ -7,6 +7,8 @@ import { Repository } from '@octokit/graphql-schema';
|
|||
* Internal dependencies
|
||||
*/
|
||||
import { graphqlWithAuth, octokitWithAuth } from './api';
|
||||
import { Logger } from '../logger';
|
||||
import { PullRequestEndpointResponse } from './types';
|
||||
|
||||
export const getLatestGithubReleaseVersion = async ( options: {
|
||||
owner?: string;
|
||||
|
@ -128,3 +130,39 @@ export const deleteGithubBranch = async (
|
|||
}
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a pull request from branches on Github.
|
||||
*
|
||||
* @param {Object} options pull request options.
|
||||
* @param {string} options.head branch name containing the changes you want to merge.
|
||||
* @param {string} options.base branch name you want the changes pulled into.
|
||||
* @param {string} options.owner repository owner.
|
||||
* @param {string} options.name repository name.
|
||||
* @param {string} options.title pull request title.
|
||||
* @param {string} options.body pull request body.
|
||||
* @return {Promise<object>} pull request data.
|
||||
*/
|
||||
export const createPullRequest = async ( options: {
|
||||
head: string;
|
||||
base: string;
|
||||
owner: string;
|
||||
name: string;
|
||||
title: string;
|
||||
body: string;
|
||||
} ): Promise< PullRequestEndpointResponse[ 'data' ] > => {
|
||||
const { head, base, owner, name, title, body } = options;
|
||||
const pullRequest = await octokitWithAuth.request(
|
||||
'POST /repos/{owner}/{repo}/pulls',
|
||||
{
|
||||
owner,
|
||||
repo: name,
|
||||
title,
|
||||
body,
|
||||
head,
|
||||
base,
|
||||
}
|
||||
);
|
||||
//@ts-ignore There is a type mismatch between the graphql schema and the response. pullRequest.data.head.repo.has_discussions is a boolean, but the graphql schema doesn't have that field.
|
||||
return pullRequest.data;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { Endpoints } from '@octokit/types';
|
||||
|
||||
export type PullRequestEndpointResponse =
|
||||
Endpoints[ 'POST /repos/{owner}/{repo}/pulls' ][ 'response' ];
|
Loading…
Reference in New Issue