Compare commits

...

16 Commits

Author SHA1 Message Date
45c510e1f6 Merge pull request #672 from peter-evans/reset-perf
perf: git reset instead of fetch
2020-12-23 14:28:23 +09:00
249b80db6b perf: git reset instead of fetch 2020-12-23 14:10:40 +09:00
6c2b44c6ac Merge pull request #666 from peter-evans/dependabot/npm_and_yarn/node-notifier-8.0.1
build(deps): bump node-notifier from 8.0.0 to 8.0.1
2020-12-23 09:48:12 +09:00
76c58cf6a9 build(deps): bump node-notifier from 8.0.0 to 8.0.1
Bumps [node-notifier](https://github.com/mikaelbr/node-notifier) from 8.0.0 to 8.0.1.
- [Release notes](https://github.com/mikaelbr/node-notifier/releases)
- [Changelog](https://github.com/mikaelbr/node-notifier/blob/v8.0.1/CHANGELOG.md)
- [Commits](https://github.com/mikaelbr/node-notifier/compare/v8.0.0...v8.0.1)

Signed-off-by: dependabot[bot] <support@github.com>
2020-12-22 13:17:50 +00:00
8c603dbb04 Merge pull request #653 from peter-evans/fix-error-handling
fix: change or->and to catch all errors
2020-12-09 09:56:23 +09:00
d01e0807ef fix: change or->and to catch all errors 2020-12-09 09:38:10 +09:00
ce699aa2d1 Merge pull request #637 from peter-evans/prune-remote
fix: prune stale remote ref for self-hosted runners
2020-11-25 12:40:23 +09:00
9984f611a7 fix: prune stale remote ref for self-hosted runners 2020-11-24 12:34:57 +09:00
ff0beed1b2 Merge pull request #627 from peter-evans/git-diff-perf
perf: set diff quiet and switch isdirty command order
2020-11-17 13:22:44 +09:00
ddeca94037 perf: set diff quiet and switch isdirty command order 2020-11-17 11:42:31 +09:00
0fd77ba8cc docs: add missing contents link 2020-10-26 09:23:01 +09:00
c7f493a800 docs: remove deprecated set-env example 2020-10-02 15:53:49 +09:00
91664dfb28 Merge pull request #604 from peter-evans/update-distribution
Update distribution
2020-10-02 15:18:04 +09:00
13ec5274b1 build: update distribution 2020-10-02 06:17:23 +00:00
bcf9790963 Merge pull request #599 from peter-evans/dependabot/npm_and_yarn/actions/core-1.2.6
Bump @actions/core from 1.2.5 to 1.2.6
2020-10-02 15:14:43 +09:00
88ea447de7 Bump @actions/core from 1.2.5 to 1.2.6
Bumps [@actions/core](https://github.com/actions/toolkit/tree/HEAD/packages/core) from 1.2.5 to 1.2.6.
- [Release notes](https://github.com/actions/toolkit/releases)
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/core/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/core)

Signed-off-by: dependabot[bot] <support@github.com>
2020-10-01 17:24:16 +00:00
8 changed files with 171 additions and 99 deletions

172
dist/index.js vendored
View File

@ -93,12 +93,6 @@ function isEven(git, branch1, branch2) {
!(yield isBehind(git, branch1, branch2)));
});
}
function hasDiff(git, branch1, branch2) {
return __awaiter(this, void 0, void 0, function* () {
const result = yield git.diff([`${branch1}..${branch2}`]);
return result.length > 0;
});
}
function splitLines(multilineString) {
return multilineString
.split('\n')
@ -140,8 +134,19 @@ function createOrUpdateBranch(git, commitMessage, base, branch, branchRemoteName
// Perform fetch and reset the working base
// Commits made during the workflow will be removed
if (workingBaseType == WorkingBaseType.Branch) {
core.info(`Resetting working base branch '${workingBase}' to its remote`);
yield git.fetch([`${workingBase}:${workingBase}`], baseRemote, ['--force']);
core.info(`Resetting working base branch '${workingBase}'`);
if (branchRemoteName == 'fork') {
// If pushing to a fork we must fetch with 'unshallow' to avoid the following error on git push
// ! [remote rejected] HEAD -> tests/push-branch-to-fork (shallow update not allowed)
yield git.fetch([`${workingBase}:${workingBase}`], baseRemote, [
'--force'
]);
}
else {
// If the remote is 'origin' we can git reset
yield git.checkout(workingBase);
yield git.exec(['reset', '--hard', `${baseRemote}/${workingBase}`]);
}
}
// If the working base is not the base, rebase the temp branch commits
// This will also be true if the working base type is a commit
@ -168,7 +173,7 @@ function createOrUpdateBranch(git, commitMessage, base, branch, branchRemoteName
// The pull request branch does not exist
core.info(`Pull request branch '${branch}' does not exist yet.`);
// Create the pull request branch
yield git.checkout(branch, 'HEAD');
yield git.checkout(branch, tempBranch);
// Check if the pull request branch is ahead of the base
result.hasDiffWithBase = yield isAhead(git, base, branch);
if (result.hasDiffWithBase) {
@ -192,7 +197,7 @@ function createOrUpdateBranch(git, commitMessage, base, branch, branchRemoteName
// squash merged but not deleted. We need to reset to make sure it doesn't appear
// to have a diff with the base due to different commits for the same changes.
// For changes on base this reset is equivalent to a rebase of the pull request branch.
if ((yield hasDiff(git, branch, tempBranch)) ||
if ((yield git.hasDiff([`${branch}..${tempBranch}`])) ||
!(yield isAhead(git, base, tempBranch))) {
core.info(`Resetting '${branch}'`);
// Alternatively, git switch -C branch tempBranch
@ -321,6 +326,12 @@ function createPullRequest(inputs) {
if (branchRemoteName == 'origin' && base == inputs.branch) {
throw new Error(`The 'base' and 'branch' for a pull request must be different branches. Unable to continue.`);
}
// For self-hosted runners the repository state persists between runs.
// This command prunes the stale remote ref when the pull request branch was
// deleted after being merged or closed. Without this the push using
// '--force-with-lease' fails due to "stale info."
// https://github.com/peter-evans/create-pull-request/issues/633
yield git.exec(['remote', 'prune', branchRemoteName]);
core.endGroup();
// Apply the branch suffix if set
if (inputs.branchSuffix) {
@ -662,16 +673,6 @@ class GitCommandManager {
return output.exitCode === 0;
});
}
diff(options) {
return __awaiter(this, void 0, void 0, function* () {
const args = ['-c', 'core.pager=cat', 'diff'];
if (options) {
args.push(...options);
}
const output = yield this.exec(args);
return output.stdout.trim();
});
}
fetch(refSpec, remoteName, options) {
return __awaiter(this, void 0, void 0, function* () {
const args = ['-c', 'protocol.version=2', 'fetch'];
@ -712,19 +713,28 @@ class GitCommandManager {
getWorkingDirectory() {
return this.workingDirectory;
}
hasDiff(options) {
return __awaiter(this, void 0, void 0, function* () {
const args = ['diff', '--quiet'];
if (options) {
args.push(...options);
}
const output = yield this.exec(args, true);
return output.exitCode === 1;
});
}
isDirty(untracked) {
return __awaiter(this, void 0, void 0, function* () {
const diffArgs = ['--abbrev=40', '--full-index', '--raw'];
// Check staged changes
if (yield this.diff([...diffArgs, '--staged'])) {
// Check untracked changes
if (untracked && (yield this.status(['--porcelain', '-unormal']))) {
return true;
}
// Check working index changes
if (yield this.diff(diffArgs)) {
if (yield this.hasDiff()) {
return true;
}
// Check untracked changes
if (untracked && (yield this.status(['--porcelain', '-unormal']))) {
// Check staged changes
if (yield this.hasDiff(['--staged'])) {
return true;
}
return false;
@ -912,8 +922,11 @@ class GitHubHelper {
};
}
catch (e) {
if (!e.message ||
!e.message.includes(`A pull request already exists for ${headBranch}`)) {
if (e.message &&
e.message.includes(`A pull request already exists for ${headBranch}`)) {
core.info(`A pull request already exists for ${headBranch}`);
}
else {
throw e;
}
}
@ -1237,6 +1250,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
const os = __importStar(__webpack_require__(87));
const utils_1 = __webpack_require__(278);
/**
* Commands
*
@ -1290,28 +1304,14 @@ class Command {
return cmdStr;
}
}
/**
* Sanitizes an input into a string so it can be passed into issueCommand safely
* @param input input to sanitize into a string
*/
function toCommandValue(input) {
if (input === null || input === undefined) {
return '';
}
else if (typeof input === 'string' || input instanceof String) {
return input;
}
return JSON.stringify(input);
}
exports.toCommandValue = toCommandValue;
function escapeData(s) {
return toCommandValue(s)
return utils_1.toCommandValue(s)
.replace(/%/g, '%25')
.replace(/\r/g, '%0D')
.replace(/\n/g, '%0A');
}
function escapeProperty(s) {
return toCommandValue(s)
return utils_1.toCommandValue(s)
.replace(/%/g, '%25')
.replace(/\r/g, '%0D')
.replace(/\n/g, '%0A')
@ -1345,6 +1345,8 @@ var __importStar = (this && this.__importStar) || function (mod) {
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
const command_1 = __webpack_require__(351);
const file_command_1 = __webpack_require__(717);
const utils_1 = __webpack_require__(278);
const os = __importStar(__webpack_require__(87));
const path = __importStar(__webpack_require__(622));
/**
@ -1371,9 +1373,17 @@ var ExitCode;
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function exportVariable(name, val) {
const convertedVal = command_1.toCommandValue(val);
const convertedVal = utils_1.toCommandValue(val);
process.env[name] = convertedVal;
command_1.issueCommand('set-env', { name }, convertedVal);
const filePath = process.env['GITHUB_ENV'] || '';
if (filePath) {
const delimiter = '_GitHubActionsFileCommandDelimeter_';
const commandValue = `${name}<<${delimiter}${os.EOL}${convertedVal}${os.EOL}${delimiter}`;
file_command_1.issueCommand('ENV', commandValue);
}
else {
command_1.issueCommand('set-env', { name }, convertedVal);
}
}
exports.exportVariable = exportVariable;
/**
@ -1389,7 +1399,13 @@ exports.setSecret = setSecret;
* @param inputPath
*/
function addPath(inputPath) {
command_1.issueCommand('add-path', {}, inputPath);
const filePath = process.env['GITHUB_PATH'] || '';
if (filePath) {
file_command_1.issueCommand('PATH', inputPath);
}
else {
command_1.issueCommand('add-path', {}, inputPath);
}
process.env['PATH'] = `${inputPath}${path.delimiter}${process.env['PATH']}`;
}
exports.addPath = addPath;
@ -1551,6 +1567,68 @@ exports.getState = getState;
/***/ }),
/***/ 717:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
"use strict";
// For internal use, subject to change.
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
// We use any as a valid input type
/* eslint-disable @typescript-eslint/no-explicit-any */
const fs = __importStar(__webpack_require__(747));
const os = __importStar(__webpack_require__(87));
const utils_1 = __webpack_require__(278);
function issueCommand(command, message) {
const filePath = process.env[`GITHUB_${command}`];
if (!filePath) {
throw new Error(`Unable to find environment variable for file command ${command}`);
}
if (!fs.existsSync(filePath)) {
throw new Error(`Missing file at path: ${filePath}`);
}
fs.appendFileSync(filePath, `${utils_1.toCommandValue(message)}${os.EOL}`, {
encoding: 'utf8'
});
}
exports.issueCommand = issueCommand;
//# sourceMappingURL=file-command.js.map
/***/ }),
/***/ 278:
/***/ ((__unused_webpack_module, exports) => {
"use strict";
// We use any as a valid input type
/* eslint-disable @typescript-eslint/no-explicit-any */
Object.defineProperty(exports, "__esModule", ({ value: true }));
/**
* Sanitizes an input into a string so it can be passed into issueCommand safely
* @param input input to sanitize into a string
*/
function toCommandValue(input) {
if (input === null || input === undefined) {
return '';
}
else if (typeof input === 'string' || input instanceof String) {
return input;
}
return JSON.stringify(input);
}
exports.toCommandValue = toCommandValue;
//# sourceMappingURL=utils.js.map
/***/ }),
/***/ 514:
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {

View File

@ -20,6 +20,7 @@
- [Misc workflow tips](#misc-workflow-tips)
- [Filtering push events](#filtering-push-events)
- [Dynamic configuration using variables](#dynamic-configuration-using-variables)
- [Setting the pull request body from a file](#setting-the-pull-request-body-from-a-file)
- [Debugging GitHub Actions](#debugging-github-actions)
@ -539,21 +540,6 @@ The recommended method is to use [`set-output`](https://docs.github.com/en/actio
body: ${{ steps.vars.outputs.pr_body }}
```
Alternatively, [`set-env`](https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-environment-variable) can be used to create environment variables.
```yml
- name: Set environment variables
run: |
echo ::set-env name=PULL_REQUEST_TITLE::"[Test] Add report file $(date +%d-%m-%Y)"
echo ::set-env name=PULL_REQUEST_BODY::"This PR was auto-generated on $(date +%d-%m-%Y) \
by [create-pull-request](https://github.com/peter-evans/create-pull-request)."
- name: Create Pull Request
uses: peter-evans/create-pull-request@v3
with:
title: ${{ env.PULL_REQUEST_TITLE }}
body: ${{ env.PULL_REQUEST_BODY }}
```
### Setting the pull request body from a file
This example shows how file content can be read into a variable and passed to the action.

12
package-lock.json generated
View File

@ -5,9 +5,9 @@
"requires": true,
"dependencies": {
"@actions/core": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.2.5.tgz",
"integrity": "sha512-mwpoNjHSWWh0IiALdDEQi3tru124JKn0yVNziIBzTME8QRv7thwoghVuT1jBRjFvdtoHsqD58IRHy1nf86paRg=="
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.2.6.tgz",
"integrity": "sha512-ZQYitnqiyBc3D+k7LsgSBmMDVkOVidaagDG7j3fOym77jNunWRuYx7VSHa9GNfFZh+zh61xsCjRj4JxMZlDqTA=="
},
"@actions/exec": {
"version": "1.0.4",
@ -5764,9 +5764,9 @@
"dev": true
},
"node-notifier": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-8.0.0.tgz",
"integrity": "sha512-46z7DUmcjoYdaWyXouuFNNfUo6eFa94t23c53c+lG/9Cvauk4a98rAUp9672X5dxGdQmLpPzTxzu8f/OeEPaFA==",
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-8.0.1.tgz",
"integrity": "sha512-BvEXF+UmsnAfYfoapKM9nGxnP+Wn7P91YfXmrKnfcYCx6VBeoN5Ez5Ogck6I8Bi5k4RlpqRYaw75pAwzX9OphA==",
"dev": true,
"optional": true,
"requires": {

View File

@ -29,7 +29,7 @@
},
"homepage": "https://github.com/peter-evans/create-pull-request",
"dependencies": {
"@actions/core": "1.2.5",
"@actions/core": "1.2.6",
"@actions/exec": "1.0.4",
"@octokit/core": "3.1.2",
"@octokit/plugin-paginate-rest": "2.4.0",

View File

@ -78,15 +78,6 @@ async function isEven(
)
}
async function hasDiff(
git: GitCommandManager,
branch1: string,
branch2: string
): Promise<boolean> {
const result = await git.diff([`${branch1}..${branch2}`])
return result.length > 0
}
function splitLines(multilineString: string): string[] {
return multilineString
.split('\n')
@ -139,8 +130,18 @@ export async function createOrUpdateBranch(
// Perform fetch and reset the working base
// Commits made during the workflow will be removed
if (workingBaseType == WorkingBaseType.Branch) {
core.info(`Resetting working base branch '${workingBase}' to its remote`)
await git.fetch([`${workingBase}:${workingBase}`], baseRemote, ['--force'])
core.info(`Resetting working base branch '${workingBase}'`)
if (branchRemoteName == 'fork') {
// If pushing to a fork we must fetch with 'unshallow' to avoid the following error on git push
// ! [remote rejected] HEAD -> tests/push-branch-to-fork (shallow update not allowed)
await git.fetch([`${workingBase}:${workingBase}`], baseRemote, [
'--force'
])
} else {
// If the remote is 'origin' we can git reset
await git.checkout(workingBase)
await git.exec(['reset', '--hard', `${baseRemote}/${workingBase}`])
}
}
// If the working base is not the base, rebase the temp branch commits
@ -177,7 +178,7 @@ export async function createOrUpdateBranch(
// The pull request branch does not exist
core.info(`Pull request branch '${branch}' does not exist yet.`)
// Create the pull request branch
await git.checkout(branch, 'HEAD')
await git.checkout(branch, tempBranch)
// Check if the pull request branch is ahead of the base
result.hasDiffWithBase = await isAhead(git, base, branch)
if (result.hasDiffWithBase) {
@ -205,7 +206,7 @@ export async function createOrUpdateBranch(
// to have a diff with the base due to different commits for the same changes.
// For changes on base this reset is equivalent to a rebase of the pull request branch.
if (
(await hasDiff(git, branch, tempBranch)) ||
(await git.hasDiff([`${branch}..${tempBranch}`])) ||
!(await isAhead(git, base, tempBranch))
) {
core.info(`Resetting '${branch}'`)

View File

@ -106,6 +106,12 @@ export async function createPullRequest(inputs: Inputs): Promise<void> {
`The 'base' and 'branch' for a pull request must be different branches. Unable to continue.`
)
}
// For self-hosted runners the repository state persists between runs.
// This command prunes the stale remote ref when the pull request branch was
// deleted after being merged or closed. Without this the push using
// '--force-with-lease' fails due to "stale info."
// https://github.com/peter-evans/create-pull-request/issues/633
await git.exec(['remote', 'prune', branchRemoteName])
core.endGroup()
// Apply the branch suffix if set

View File

@ -96,15 +96,6 @@ export class GitCommandManager {
return output.exitCode === 0
}
async diff(options?: string[]): Promise<string> {
const args = ['-c', 'core.pager=cat', 'diff']
if (options) {
args.push(...options)
}
const output = await this.exec(args)
return output.stdout.trim()
}
async fetch(
refSpec: string[],
remoteName?: string,
@ -153,18 +144,26 @@ export class GitCommandManager {
return this.workingDirectory
}
async hasDiff(options?: string[]): Promise<boolean> {
const args = ['diff', '--quiet']
if (options) {
args.push(...options)
}
const output = await this.exec(args, true)
return output.exitCode === 1
}
async isDirty(untracked: boolean): Promise<boolean> {
const diffArgs = ['--abbrev=40', '--full-index', '--raw']
// Check staged changes
if (await this.diff([...diffArgs, '--staged'])) {
// Check untracked changes
if (untracked && (await this.status(['--porcelain', '-unormal']))) {
return true
}
// Check working index changes
if (await this.diff(diffArgs)) {
if (await this.hasDiff()) {
return true
}
// Check untracked changes
if (untracked && (await this.status(['--porcelain', '-unormal']))) {
// Check staged changes
if (await this.hasDiff(['--staged'])) {
return true
}
return false

View File

@ -58,9 +58,11 @@ export class GitHubHelper {
}
} catch (e) {
if (
!e.message ||
!e.message.includes(`A pull request already exists for ${headBranch}`)
e.message &&
e.message.includes(`A pull request already exists for ${headBranch}`)
) {
core.info(`A pull request already exists for ${headBranch}`)
} else {
throw e
}
}