Compare commits

...

12 Commits

Author SHA1 Message Date
172ec762f8 Merge pull request #301 from peter-evans/update-distribution
Update distribution
2020-05-17 18:28:48 +09:00
5cb0d674f3 Update distribution 2020-05-17 09:26:30 +00:00
eb892d7803 Merge pull request #308 from peter-evans/typescript
Typescript
2020-05-17 18:24:18 +09:00
f8274253bd Convert to typescript 2020-05-17 18:02:41 +09:00
0f423da02c Merge pull request #315 from peter-evans/input-def
Add missing draft input definition
2020-05-17 17:55:03 +09:00
9573f479a0 Add missing draft input definition 2020-05-17 17:47:54 +09:00
eb4cde120d Update documentation 2020-05-17 14:42:46 +09:00
25902ccdd1 Remove dockerhub-description workflow 2020-05-16 14:36:18 +09:00
39b337e8bb Remove codeowners 2020-05-14 10:19:06 +09:00
7e70d8e63c Skip test job for pull requests from forks 2020-05-13 17:25:18 +09:00
1a640f5b01 Update README 2020-05-11 14:31:26 +09:00
9faa8dc1d9 Update pull request example image 2020-05-11 14:28:02 +09:00
34 changed files with 2576 additions and 838 deletions

3
.eslintignore Normal file
View File

@ -0,0 +1,3 @@
dist/
lib/
node_modules/

View File

@ -1,17 +1,19 @@
{
"env": {
"commonjs": true,
"es6": true,
"node": true
},
"extends": "eslint:recommended",
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parserOptions": {
"ecmaVersion": 2018
},
"rules": {
}
}
"env": { "node": true, "jest": true },
"parser": "@typescript-eslint/parser",
"parserOptions": { "ecmaVersion": 9, "sourceType": "module" },
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"plugin:import/errors",
"plugin:import/warnings",
"plugin:import/typescript",
"plugin:prettier/recommended",
"prettier/@typescript-eslint"
],
"plugins": ["@typescript-eslint"],
"rules": {
"@typescript-eslint/camelcase": "off"
}
}

1
.github/CODEOWNERS vendored
View File

@ -1 +0,0 @@
* @peter-evans

View File

@ -23,6 +23,9 @@ jobs:
python-version: '3.x'
- run: npm ci
- run: npm run clean
- run: npm run build
- run: npm run format-check
- run: npm run lint
- run: npm run test
- run: npm run package
- uses: actions/upload-artifact@v2
@ -31,18 +34,16 @@ jobs:
path: dist
test:
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository
needs: [build]
runs-on: ubuntu-latest
strategy:
matrix:
target: [built, committed]
steps:
- if: github.event_name == 'push'
uses: actions/checkout@v2
- if: github.event_name == 'pull_request'
uses: actions/checkout@v2
- uses: actions/checkout@v2
with:
ref: ${{ github.head_ref }}
ref: master
- if: matrix.target == 'built' || github.event_name == 'pull_request'
uses: actions/download-artifact@v2
with:
@ -105,6 +106,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: rm -rf dist
- uses: actions/download-artifact@v2
with:
name: dist

View File

@ -1,19 +0,0 @@
name: Update Docker Hub Description
on:
push:
branches:
- master
paths:
- README.md
- .github/workflows/dockerhub-description.yml
jobs:
dockerHubDescription:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Docker Hub Description
uses: peter-evans/dockerhub-description@v2.1.0
env:
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }}
DOCKERHUB_REPOSITORY: peterevans/create-pull-request

3
.gitignore vendored
View File

@ -1,6 +1,7 @@
__pycache__
.python-version
node_modules
lib/
node_modules/
.DS_Store

3
.prettierignore Normal file
View File

@ -0,0 +1,3 @@
dist/
lib/
node_modules/

11
.prettierrc.json Normal file
View File

@ -0,0 +1,11 @@
{
"printWidth": 80,
"tabWidth": 2,
"useTabs": false,
"semi": false,
"singleQuote": true,
"trailingComma": "none",
"bracketSpacing": false,
"arrowParens": "avoid",
"parser": "typescript"
}

View File

@ -206,7 +206,7 @@ jobs:
echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}"
```
This reference configuration will create pull requests that look like this:
An example based on the above reference configuration creates pull requests that look like this:
![Pull Request Example](docs/assets/pull-request-example.png)

162
__test__/git.test.ts Normal file
View File

@ -0,0 +1,162 @@
import * as path from 'path'
import {
ConfigOption,
getRepoPath,
execGit,
addConfigOption,
unsetConfigOption,
configOptionExists,
getConfigOption,
getAndUnsetConfigOption
} from '../lib/git'
const originalGitHubWorkspace = process.env['GITHUB_WORKSPACE']
describe('git tests', () => {
beforeAll(() => {
// GitHub workspace
process.env['GITHUB_WORKSPACE'] = __dirname
})
afterAll(() => {
// Restore GitHub workspace
delete process.env['GITHUB_WORKSPACE']
if (originalGitHubWorkspace) {
process.env['GITHUB_WORKSPACE'] = originalGitHubWorkspace
}
})
test('getRepoPath', async () => {
expect(getRepoPath()).toEqual(process.env['GITHUB_WORKSPACE'])
expect(getRepoPath('foo')).toEqual(
path.resolve(process.env['GITHUB_WORKSPACE'] || '', 'foo')
)
})
test('execGit', async () => {
const repoPath = getRepoPath()
const result = await execGit(
repoPath,
['config', '--local', '--name-only', '--get-regexp', 'remote.origin.url'],
true
)
expect(result.exitCode).toEqual(0)
expect(result.stdout.trim()).toEqual('remote.origin.url')
})
it('adds and unsets a config option', async () => {
const repoPath = getRepoPath()
const add = await addConfigOption(
repoPath,
'test.add.and.unset.config.option',
'foo'
)
expect(add).toBeTruthy()
const unset = await unsetConfigOption(
repoPath,
'test.add.and.unset.config.option'
)
expect(unset).toBeTruthy()
})
it('adds and unsets a config option with value regex', async () => {
const repoPath = getRepoPath()
const add = await addConfigOption(
repoPath,
'test.add.and.unset.config.option',
'foo bar'
)
expect(add).toBeTruthy()
const unset = await unsetConfigOption(
repoPath,
'test.add.and.unset.config.option',
'^foo'
)
expect(unset).toBeTruthy()
})
test('configOptionExists returns true', async () => {
const repoPath = getRepoPath()
const result = await configOptionExists(repoPath, 'remote.origin.url')
expect(result).toBeTruthy()
})
test('configOptionExists returns false', async () => {
const repoPath = getRepoPath()
const result = await configOptionExists(repoPath, 'this.key.does.not.exist')
expect(result).toBeFalsy()
})
it('successfully retrieves a config option', async () => {
const repoPath = getRepoPath()
const add = await addConfigOption(repoPath, 'test.get.config.option', 'foo')
expect(add).toBeTruthy()
const option = await getConfigOption(repoPath, 'test.get.config.option')
expect(option.value).toEqual('foo')
const unset = await unsetConfigOption(repoPath, 'test.get.config.option')
expect(unset).toBeTruthy()
})
it('gets a config option with value regex', async () => {
const repoPath = getRepoPath()
const add = await addConfigOption(
repoPath,
'test.get.config.option',
'foo bar'
)
expect(add).toBeTruthy()
const option = await getConfigOption(
repoPath,
'test.get.config.option',
'^foo'
)
expect(option.value).toEqual('foo bar')
const unset = await unsetConfigOption(
repoPath,
'test.get.config.option',
'^foo'
)
expect(unset).toBeTruthy()
})
it('gets and unsets a config option', async () => {
const repoPath = getRepoPath()
const add = await addConfigOption(
repoPath,
'test.get.and.unset.config.option',
'foo'
)
expect(add).toBeTruthy()
const getAndUnset = await getAndUnsetConfigOption(
repoPath,
'test.get.and.unset.config.option'
)
expect(getAndUnset.value).toEqual('foo')
})
it('gets and unsets a config option with value regex', async () => {
const repoPath = getRepoPath()
const add = await addConfigOption(
repoPath,
'test.get.and.unset.config.option',
'foo bar'
)
expect(add).toBeTruthy()
const getAndUnset = await getAndUnsetConfigOption(
repoPath,
'test.get.and.unset.config.option',
'^foo'
)
expect(getAndUnset.value).toEqual('foo bar')
})
it('fails to get and unset a config option', async () => {
const repoPath = getRepoPath()
const getAndUnset = await getAndUnsetConfigOption(
repoPath,
'this.key.does.not.exist'
)
expect(getAndUnset.name).toEqual('')
expect(getAndUnset.value).toEqual('')
})
})

View File

@ -30,6 +30,8 @@ inputs:
description: 'Deprecated. See README for details.'
project-column:
description: 'Deprecated. See README for details.'
draft:
description: 'Create a draft pull request'
branch:
description: 'The pull request branch name.'
request-to-parent:

0
dist/cpr/create_pull_request.py vendored Executable file → Normal file
View File

733
dist/index.js vendored
View File

@ -34,7 +34,7 @@ module.exports =
/******/ // the startup function
/******/ function startup() {
/******/ // Load entry module and return exports
/******/ return __webpack_require__(676);
/******/ return __webpack_require__(198);
/******/ };
/******/
/******/ // run startup
@ -952,6 +952,58 @@ class ExecState extends events.EventEmitter {
module.exports = require("tls");
/***/ }),
/***/ 57:
/***/ (function(__unusedmodule, exports, __webpack_require__) {
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
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)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.isDocker = void 0;
const fs = __importStar(__webpack_require__(747));
function hasDockerEnv() {
try {
fs.statSync('/.dockerenv');
return true;
}
catch (_) {
return false;
}
}
function hasDockerCGroup() {
try {
return fs.readFileSync('/proc/self/cgroup', 'utf8').includes('docker');
}
catch (_) {
return false;
}
}
function isDocker() {
return hasDockerEnv() || hasDockerCGroup();
}
exports.isDocker = isDocker;
/***/ }),
/***/ 87:
@ -959,65 +1011,6 @@ module.exports = require("tls");
module.exports = require("os");
/***/ }),
/***/ 104:
/***/ (function(module, __unusedexports, __webpack_require__) {
const core = __webpack_require__(470);
const tc = __webpack_require__(533);
const path = __webpack_require__(622);
const semver = __webpack_require__(280);
/**
* Setup for Python from the GitHub Actions tool cache
* Converted from https://github.com/actions/setup-python
*
* @param {string} versionSpec version of Python
* @param {string} arch architecture (x64|x32)
*/
let setupPython = function(versionSpec, arch) {
return new Promise((resolve, reject) => {
const IS_WINDOWS = process.platform === "win32";
// Find the version of Python we want in the tool cache
const installDir = tc.find("Python", versionSpec, arch);
core.debug(`installDir: ${installDir}`);
// Set paths
core.exportVariable("pythonLocation", installDir);
core.addPath(installDir);
if (IS_WINDOWS) {
core.addPath(path.join(installDir, "Scripts"));
} else {
core.addPath(path.join(installDir, "bin"));
}
if (IS_WINDOWS) {
// Add --user directory
// `installDir` from tool cache should look like $AGENT_TOOLSDIRECTORY/Python/<semantic version>/x64/
// So if `findLocalTool` succeeded above, we must have a conformant `installDir`
const version = path.basename(path.dirname(installDir));
const major = semver.major(version);
const minor = semver.minor(version);
const userScriptsDir = path.join(
process.env["APPDATA"] || "",
"Python",
`Python${major}${minor}`,
"Scripts"
);
core.addPath(userScriptsDir);
}
// On Linux and macOS, pip will create the --user directory and add it to PATH as needed.
resolve();
});
};
module.exports = setupPython;
/***/ }),
/***/ 129:
@ -1314,39 +1307,165 @@ exports.debug = debug; // for test
/***/ }),
/***/ 160:
/***/ (function(module, __unusedexports, __webpack_require__) {
/***/ 198:
/***/ (function(__unusedmodule, exports, __webpack_require__) {
"use strict";
const fs = __webpack_require__(747);
let isDocker;
function hasDockerEnv() {
try {
fs.statSync('/.dockerenv');
return true;
} catch (_) {
return false;
}
}
function hasDockerCGroup() {
try {
return fs.readFileSync('/proc/self/cgroup', 'utf8').includes('docker');
} catch (_) {
return false;
}
}
module.exports = () => {
if (isDocker === undefined) {
isDocker = hasDockerEnv() || hasDockerCGroup();
}
return isDocker;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
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)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const core = __importStar(__webpack_require__(470));
const exec = __importStar(__webpack_require__(986));
const isDocker_1 = __webpack_require__(57);
const setupPython_1 = __webpack_require__(953);
const git_1 = __webpack_require__(453);
const util_1 = __webpack_require__(669);
const EXTRAHEADER_OPTION = 'http.https://github.com/.extraheader';
const EXTRAHEADER_VALUE_REGEX = '^AUTHORIZATION:';
function run() {
return __awaiter(this, void 0, void 0, function* () {
let repoPath;
let extraHeaderOption = new git_1.ConfigOption();
try {
// Python assets
const cpr = `${__dirname}/cpr`;
core.debug(`cpr: ${cpr}`);
// Determine how to access python and pip
const { pip, python } = (function () {
if (isDocker_1.isDocker()) {
core.info('Running inside a Docker container');
// Python 3 assumed to be installed and on the PATH
return {
pip: 'pip3',
python: 'python3'
};
}
else {
// Setup Python from the tool cache
setupPython_1.setupPython('3.x', 'x64');
return {
pip: 'pip',
python: 'python'
};
}
})();
// Install requirements
yield exec.exec(pip, [
'install',
'--requirement',
`${cpr}/requirements.txt`,
'--no-index',
`--find-links=${__dirname}/vendor`
]);
// Fetch action inputs
const inputs = {
token: core.getInput('token'),
path: core.getInput('path'),
commitMessage: core.getInput('commit-message'),
committer: core.getInput('committer'),
author: core.getInput('author'),
title: core.getInput('title'),
body: core.getInput('body'),
labels: core.getInput('labels'),
assignees: core.getInput('assignees'),
reviewers: core.getInput('reviewers'),
teamReviewers: core.getInput('team-reviewers'),
milestone: core.getInput('milestone'),
project: core.getInput('project'),
projectColumn: core.getInput('project-column'),
draft: core.getInput('draft'),
branch: core.getInput('branch'),
requestToParent: core.getInput('request-to-parent'),
base: core.getInput('base'),
branchSuffix: core.getInput('branch-suffix')
};
core.debug(`Inputs: ${util_1.inspect(inputs)}`);
// Set environment variables from inputs.
if (inputs.token)
process.env.GITHUB_TOKEN = inputs.token;
if (inputs.path)
process.env.CPR_PATH = inputs.path;
if (inputs.commitMessage)
process.env.CPR_COMMIT_MESSAGE = inputs.commitMessage;
if (inputs.committer)
process.env.CPR_COMMITTER = inputs.committer;
if (inputs.author)
process.env.CPR_AUTHOR = inputs.author;
if (inputs.title)
process.env.CPR_TITLE = inputs.title;
if (inputs.body)
process.env.CPR_BODY = inputs.body;
if (inputs.labels)
process.env.CPR_LABELS = inputs.labels;
if (inputs.assignees)
process.env.CPR_ASSIGNEES = inputs.assignees;
if (inputs.reviewers)
process.env.CPR_REVIEWERS = inputs.reviewers;
if (inputs.teamReviewers)
process.env.CPR_TEAM_REVIEWERS = inputs.teamReviewers;
if (inputs.milestone)
process.env.CPR_MILESTONE = inputs.milestone;
if (inputs.project)
process.env.CPR_PROJECT_NAME = inputs.project;
if (inputs.projectColumn)
process.env.CPR_PROJECT_COLUMN_NAME = inputs.projectColumn;
if (inputs.draft)
process.env.CPR_DRAFT = inputs.draft;
if (inputs.branch)
process.env.CPR_BRANCH = inputs.branch;
if (inputs.requestToParent)
process.env.CPR_REQUEST_TO_PARENT = inputs.requestToParent;
if (inputs.base)
process.env.CPR_BASE = inputs.base;
if (inputs.branchSuffix)
process.env.CPR_BRANCH_SUFFIX = inputs.branchSuffix;
// Get the repository path
repoPath = git_1.getRepoPath(inputs.path);
// Get the extraheader config option if it exists
extraHeaderOption = yield git_1.getAndUnsetConfigOption(repoPath, EXTRAHEADER_OPTION, EXTRAHEADER_VALUE_REGEX);
// Execute create pull request
yield exec.exec(python, [`${cpr}/create_pull_request.py`]);
}
catch (error) {
core.setFailed(error.message);
}
finally {
// Restore the extraheader config option
if (extraHeaderOption.value != '') {
if (yield git_1.addConfigOption(repoPath, EXTRAHEADER_OPTION, extraHeaderOption.value))
core.debug(`Restored config option '${EXTRAHEADER_OPTION}'`);
}
}
});
}
run();
/***/ }),
@ -3080,6 +3199,138 @@ function escapeProperty(s) {
}
//# sourceMappingURL=command.js.map
/***/ }),
/***/ 453:
/***/ (function(__unusedmodule, exports, __webpack_require__) {
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
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)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getAndUnsetConfigOption = exports.getConfigOption = exports.configOptionExists = exports.unsetConfigOption = exports.addConfigOption = exports.execGit = exports.getRepoPath = exports.ConfigOption = void 0;
const core = __importStar(__webpack_require__(470));
const exec = __importStar(__webpack_require__(986));
const path = __importStar(__webpack_require__(622));
class GitOutput {
constructor() {
this.stdout = '';
this.exitCode = 0;
}
}
class ConfigOption {
constructor() {
this.name = '';
this.value = '';
}
}
exports.ConfigOption = ConfigOption;
function getRepoPath(relativePath) {
let githubWorkspacePath = process.env['GITHUB_WORKSPACE'];
if (!githubWorkspacePath) {
throw new Error('GITHUB_WORKSPACE not defined');
}
githubWorkspacePath = path.resolve(githubWorkspacePath);
core.debug(`githubWorkspacePath: ${githubWorkspacePath}`);
let repoPath = githubWorkspacePath;
if (relativePath)
repoPath = path.resolve(repoPath, relativePath);
core.debug(`repoPath: ${repoPath}`);
return repoPath;
}
exports.getRepoPath = getRepoPath;
function execGit(repoPath, args, ignoreReturnCode = false) {
return __awaiter(this, void 0, void 0, function* () {
const result = new GitOutput();
const stdout = [];
const options = {
cwd: repoPath,
ignoreReturnCode: ignoreReturnCode,
listeners: {
stdout: (data) => {
stdout.push(data.toString());
}
}
};
result.exitCode = yield exec.exec('git', args, options);
result.stdout = stdout.join('');
return result;
});
}
exports.execGit = execGit;
function addConfigOption(repoPath, name, value) {
return __awaiter(this, void 0, void 0, function* () {
const result = yield execGit(repoPath, ['config', '--local', '--add', name, value], true);
return result.exitCode === 0;
});
}
exports.addConfigOption = addConfigOption;
function unsetConfigOption(repoPath, name, valueRegex = '.') {
return __awaiter(this, void 0, void 0, function* () {
const result = yield execGit(repoPath, ['config', '--local', '--unset', name, valueRegex], true);
return result.exitCode === 0;
});
}
exports.unsetConfigOption = unsetConfigOption;
function configOptionExists(repoPath, name, valueRegex = '.') {
return __awaiter(this, void 0, void 0, function* () {
const result = yield execGit(repoPath, ['config', '--local', '--name-only', '--get-regexp', name, valueRegex], true);
return result.exitCode === 0;
});
}
exports.configOptionExists = configOptionExists;
function getConfigOption(repoPath, name, valueRegex = '.') {
return __awaiter(this, void 0, void 0, function* () {
const option = new ConfigOption();
const result = yield execGit(repoPath, ['config', '--local', '--get-regexp', name, valueRegex], true);
option.name = name;
option.value = result.stdout.trim().split(`${name} `)[1];
return option;
});
}
exports.getConfigOption = getConfigOption;
function getAndUnsetConfigOption(repoPath, name, valueRegex = '.') {
return __awaiter(this, void 0, void 0, function* () {
if (yield configOptionExists(repoPath, name, valueRegex)) {
const option = yield getConfigOption(repoPath, name, valueRegex);
if (yield unsetConfigOption(repoPath, name, valueRegex)) {
core.debug(`Unset config option '${name}'`);
return option;
}
}
return new ConfigOption();
});
}
exports.getAndUnsetConfigOption = getAndUnsetConfigOption;
/***/ }),
/***/ 470:
@ -4592,239 +4843,6 @@ function isUnixExecutable(stats) {
}
//# sourceMappingURL=io-util.js.map
/***/ }),
/***/ 676:
/***/ (function(__unusedmodule, __unusedexports, __webpack_require__) {
const { inspect } = __webpack_require__(669);
const isDocker = __webpack_require__(160);
const core = __webpack_require__(470);
const exec = __webpack_require__(986);
const setupPython = __webpack_require__(104);
const {
getRepoPath,
getAndUnsetConfigOption,
addConfigOption
} = __webpack_require__(718);
const EXTRAHEADER_OPTION = "http.https://github.com/.extraheader";
const EXTRAHEADER_VALUE_REGEX = "^AUTHORIZATION:";
async function run() {
try {
// Allows ncc to find assets to be included in the distribution
const cpr = __webpack_require__.ab + "cpr";
core.debug(`cpr: ${cpr}`);
// Determine how to access python and pip
const { pip, python } = (function() {
if (isDocker()) {
core.info("Running inside a Docker container");
// Python 3 assumed to be installed and on the PATH
return {
pip: "pip3",
python: "python3"
};
} else {
// Setup Python from the tool cache
setupPython("3.x", "x64");
return {
pip: "pip",
python: "python"
};
}
})();
// Install requirements
await exec.exec(pip, [
"install",
"--requirement",
`${cpr}/requirements.txt`,
"--no-index",
`--find-links=${__dirname}/vendor`
]);
// Fetch action inputs
const inputs = {
token: core.getInput("token"),
path: core.getInput("path"),
commitMessage: core.getInput("commit-message"),
committer: core.getInput("committer"),
author: core.getInput("author"),
title: core.getInput("title"),
body: core.getInput("body"),
labels: core.getInput("labels"),
assignees: core.getInput("assignees"),
reviewers: core.getInput("reviewers"),
teamReviewers: core.getInput("team-reviewers"),
milestone: core.getInput("milestone"),
project: core.getInput("project"),
projectColumn: core.getInput("project-column"),
draft: core.getInput("draft"),
branch: core.getInput("branch"),
requestToParent: core.getInput("request-to-parent"),
base: core.getInput("base"),
branchSuffix: core.getInput("branch-suffix")
};
core.debug(`Inputs: ${inspect(inputs)}`);
// Set environment variables from inputs.
if (inputs.token) process.env.GITHUB_TOKEN = inputs.token;
if (inputs.path) process.env.CPR_PATH = inputs.path;
if (inputs.commitMessage) process.env.CPR_COMMIT_MESSAGE = inputs.commitMessage;
if (inputs.committer) process.env.CPR_COMMITTER = inputs.committer;
if (inputs.author) process.env.CPR_AUTHOR = inputs.author;
if (inputs.title) process.env.CPR_TITLE = inputs.title;
if (inputs.body) process.env.CPR_BODY = inputs.body;
if (inputs.labels) process.env.CPR_LABELS = inputs.labels;
if (inputs.assignees) process.env.CPR_ASSIGNEES = inputs.assignees;
if (inputs.reviewers) process.env.CPR_REVIEWERS = inputs.reviewers;
if (inputs.teamReviewers) process.env.CPR_TEAM_REVIEWERS = inputs.teamReviewers;
if (inputs.milestone) process.env.CPR_MILESTONE = inputs.milestone;
if (inputs.project) process.env.CPR_PROJECT_NAME = inputs.project;
if (inputs.projectColumn) process.env.CPR_PROJECT_COLUMN_NAME = inputs.projectColumn;
if (inputs.draft) process.env.CPR_DRAFT = inputs.draft;
if (inputs.branch) process.env.CPR_BRANCH = inputs.branch;
if (inputs.requestToParent) process.env.CPR_REQUEST_TO_PARENT = inputs.requestToParent;
if (inputs.base) process.env.CPR_BASE = inputs.base;
if (inputs.branchSuffix) process.env.CPR_BRANCH_SUFFIX = inputs.branchSuffix;
// Get the repository path
var repoPath = getRepoPath(inputs.path);
// Get the extraheader config option if it exists
var extraHeaderOption = await getAndUnsetConfigOption(
repoPath,
EXTRAHEADER_OPTION,
EXTRAHEADER_VALUE_REGEX
);
// Execute create pull request
await exec.exec(python, [`${cpr}/create_pull_request.py`]);
} catch (error) {
core.setFailed(error.message);
} finally {
// Restore the extraheader config option
if (extraHeaderOption) {
if (
await addConfigOption(
repoPath,
EXTRAHEADER_OPTION,
extraHeaderOption.value
)
)
core.debug(`Restored config option '${EXTRAHEADER_OPTION}'`);
}
}
}
run();
/***/ }),
/***/ 718:
/***/ (function(module, __unusedexports, __webpack_require__) {
const core = __webpack_require__(470);
const exec = __webpack_require__(986);
const path = __webpack_require__(622);
function getRepoPath(relativePath) {
let githubWorkspacePath = process.env["GITHUB_WORKSPACE"];
if (!githubWorkspacePath) {
throw new Error("GITHUB_WORKSPACE not defined");
}
githubWorkspacePath = path.resolve(githubWorkspacePath);
core.debug(`githubWorkspacePath: ${githubWorkspacePath}`);
repoPath = githubWorkspacePath;
if (relativePath) repoPath = path.resolve(repoPath, relativePath);
core.debug(`repoPath: ${repoPath}`);
return repoPath;
}
async function execGit(repoPath, args, ignoreReturnCode = false) {
const stdout = [];
const options = {
cwd: repoPath,
ignoreReturnCode: ignoreReturnCode,
listeners: {
stdout: data => {
stdout.push(data.toString());
}
}
};
var result = {};
result.exitCode = await exec.exec("git", args, options);
result.stdout = stdout.join("");
return result;
}
async function addConfigOption(repoPath, name, value) {
const result = await execGit(
repoPath,
["config", "--local", "--add", name, value],
true
);
return result.exitCode === 0;
}
async function unsetConfigOption(repoPath, name, valueRegex=".") {
const result = await execGit(
repoPath,
["config", "--local", "--unset", name, valueRegex],
true
);
return result.exitCode === 0;
}
async function configOptionExists(repoPath, name, valueRegex=".") {
const result = await execGit(
repoPath,
["config", "--local", "--name-only", "--get-regexp", name, valueRegex],
true
);
return result.exitCode === 0;
}
async function getConfigOption(repoPath, name, valueRegex=".") {
const result = await execGit(
repoPath,
["config", "--local", "--get-regexp", name, valueRegex],
true
);
const option = result.stdout.trim().split(`${name} `);
return {
name: name,
value: option[1]
}
}
async function getAndUnsetConfigOption(repoPath, name, valueRegex=".") {
if (await configOptionExists(repoPath, name, valueRegex)) {
const option = await getConfigOption(repoPath, name, valueRegex);
if (await unsetConfigOption(repoPath, name, valueRegex)) {
core.debug(`Unset config option '${name}'`);
return option;
}
}
return null;
}
module.exports = {
getRepoPath,
execGit,
addConfigOption,
unsetConfigOption,
configOptionExists,
getConfigOption,
getAndUnsetConfigOption
};
/***/ }),
/***/ 722:
@ -4979,6 +4997,77 @@ function checkBypass(reqUrl) {
exports.checkBypass = checkBypass;
/***/ }),
/***/ 953:
/***/ (function(__unusedmodule, exports, __webpack_require__) {
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
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)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.setupPython = void 0;
const core = __importStar(__webpack_require__(470));
const tc = __importStar(__webpack_require__(533));
const path = __importStar(__webpack_require__(622));
const semver = __importStar(__webpack_require__(280));
/**
* Setup for Python from the GitHub Actions tool cache
* Converted from https://github.com/actions/setup-python
*
* @param {string} versionSpec version of Python
* @param {string} arch architecture (x64|x32)
*/
function setupPython(versionSpec, arch) {
return new Promise(resolve => {
const IS_WINDOWS = process.platform === 'win32';
// Find the version of Python we want in the tool cache
const installDir = tc.find('Python', versionSpec, arch);
core.debug(`installDir: ${installDir}`);
// Set paths
core.exportVariable('pythonLocation', installDir);
core.addPath(installDir);
if (IS_WINDOWS) {
core.addPath(path.join(installDir, 'Scripts'));
}
else {
core.addPath(path.join(installDir, 'bin'));
}
if (IS_WINDOWS) {
// Add --user directory
// `installDir` from tool cache should look like $AGENT_TOOLSDIRECTORY/Python/<semantic version>/x64/
// So if `findLocalTool` succeeded above, we must have a conformant `installDir`
const version = path.basename(path.dirname(installDir));
const major = semver.major(version);
const minor = semver.minor(version);
const userScriptsDir = path.join(process.env['APPDATA'] || '', 'Python', `Python${major}${minor}`, 'Scripts');
core.addPath(userScriptsDir);
}
// On Linux and macOS, pip will create the --user directory and add it to PATH as needed.
resolve();
});
}
exports.setupPython = setupPython;
/***/ }),
/***/ 979:

BIN
dist/vendor/Deprecated-1.2.10.tar.gz vendored Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 414 KiB

After

Width:  |  Height:  |  Size: 126 KiB

View File

@ -90,7 +90,7 @@ Workflows triggered by `pull_request` events will by default check out a [merge
### Restrictions on forked repositories
GitHub Actions have imposed restrictions on events triggered by a forked repository. For example, the `pull_request` event triggered by a fork opening a pull request in the upstream repository.
GitHub Actions have imposed restrictions on events triggered by a forked repository. Specifically, the `pull_request` event triggered by a fork opening a pull request in the upstream repository.
- Events from forks cannot access secrets, except for for the default `GITHUB_TOKEN`.
> With the exception of GITHUB_TOKEN, secrets are not passed to the runner when a workflow is triggered from a forked repository.
@ -101,7 +101,7 @@ GitHub Actions have imposed restrictions on events triggered by a forked reposit
[GitHub Actions: Permissions for the GITHUB_TOKEN](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/authenticating-with-the-github_token#permissions-for-the-github_token)
These restrictions mean that during a `pull_request` event triggered by a forked repository the action will be unable to commit changes to a branch.
These restrictions mean that during a `pull_request` event triggered by a forked repository, actions have no write access to GitHub resources and will fail on attempt.
A job condition can be added to prevent workflows from executing when triggered by a repository fork.

View File

@ -1,3 +1,11 @@
process.env = Object.assign(process.env, {
GITHUB_WORKSPACE: __dirname
});
module.exports = {
clearMocks: true,
moduleFileExtensions: ['js', 'ts'],
testEnvironment: 'node',
testMatch: ['**/*.test.ts'],
testRunner: 'jest-circus/runner',
transform: {
'^.+\\.ts$': 'ts-jest'
},
verbose: true
}

1674
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,21 +1,29 @@
{
"name": "create-pull-request",
"version": "2.0.0",
"private": true,
"description": "Creates a pull request for changes to your repository in the actions workspace",
"main": "index.js",
"main": "lib/main.js",
"scripts": {
"clean": "rm -rf dist",
"lint": "eslint src/index.js",
"test": "eslint src/index.js && jest",
"build": "ncc build src/index.js -o dist",
"build": "tsc && ncc build",
"format": "prettier --write '**/*.ts'",
"format-check": "prettier --check '**/*.ts'",
"lint": "eslint src/**/*.ts",
"test": "jest --passWithNoTests",
"pack-assets": "mkdir -p dist/cpr && cp -rv src/cpr/* dist/cpr",
"vendor-deps": "pip download -r src/cpr/requirements.txt --no-binary=:all: -d dist/vendor",
"package": "npm run build && npm run vendor-deps"
"package": "npm run build && npm run pack-assets && npm run vendor-deps"
},
"repository": {
"type": "git",
"url": "git+https://github.com/peter-evans/create-pull-request.git"
},
"keywords": [],
"keywords": [
"actions",
"pull",
"request"
],
"author": "Peter Evans",
"license": "MIT",
"bugs": {
@ -29,8 +37,18 @@
"is-docker": "2.0.0"
},
"devDependencies": {
"@types/jest": "25.2.2",
"@types/node": "14.0.1",
"@typescript-eslint/parser": "2.33.0",
"@zeit/ncc": "0.22.1",
"eslint": "6.8.0",
"jest": "26.0.1"
"eslint": "7.0.0",
"eslint-plugin-github": "3.4.1",
"eslint-plugin-jest": "23.11.0",
"jest": "26.0.1",
"jest-circus": "26.0.1",
"js-yaml": "3.13.1",
"prettier": "2.0.5",
"ts-jest": "25.5.1",
"typescript": "3.9.2"
}
}

View File

@ -1,97 +0,0 @@
const core = require("@actions/core");
const exec = require("@actions/exec");
const path = require("path");
function getRepoPath(relativePath) {
let githubWorkspacePath = process.env["GITHUB_WORKSPACE"];
if (!githubWorkspacePath) {
throw new Error("GITHUB_WORKSPACE not defined");
}
githubWorkspacePath = path.resolve(githubWorkspacePath);
core.debug(`githubWorkspacePath: ${githubWorkspacePath}`);
repoPath = githubWorkspacePath;
if (relativePath) repoPath = path.resolve(repoPath, relativePath);
core.debug(`repoPath: ${repoPath}`);
return repoPath;
}
async function execGit(repoPath, args, ignoreReturnCode = false) {
const stdout = [];
const options = {
cwd: repoPath,
ignoreReturnCode: ignoreReturnCode,
listeners: {
stdout: data => {
stdout.push(data.toString());
}
}
};
var result = {};
result.exitCode = await exec.exec("git", args, options);
result.stdout = stdout.join("");
return result;
}
async function addConfigOption(repoPath, name, value) {
const result = await execGit(
repoPath,
["config", "--local", "--add", name, value],
true
);
return result.exitCode === 0;
}
async function unsetConfigOption(repoPath, name, valueRegex=".") {
const result = await execGit(
repoPath,
["config", "--local", "--unset", name, valueRegex],
true
);
return result.exitCode === 0;
}
async function configOptionExists(repoPath, name, valueRegex=".") {
const result = await execGit(
repoPath,
["config", "--local", "--name-only", "--get-regexp", name, valueRegex],
true
);
return result.exitCode === 0;
}
async function getConfigOption(repoPath, name, valueRegex=".") {
const result = await execGit(
repoPath,
["config", "--local", "--get-regexp", name, valueRegex],
true
);
const option = result.stdout.trim().split(`${name} `);
return {
name: name,
value: option[1]
}
}
async function getAndUnsetConfigOption(repoPath, name, valueRegex=".") {
if (await configOptionExists(repoPath, name, valueRegex)) {
const option = await getConfigOption(repoPath, name, valueRegex);
if (await unsetConfigOption(repoPath, name, valueRegex)) {
core.debug(`Unset config option '${name}'`);
return option;
}
}
return null;
}
module.exports = {
getRepoPath,
execGit,
addConfigOption,
unsetConfigOption,
configOptionExists,
getConfigOption,
getAndUnsetConfigOption
};

View File

@ -1,98 +0,0 @@
const path = require("path");
const {
getRepoPath,
execGit,
addConfigOption,
unsetConfigOption,
configOptionExists,
getConfigOption,
getAndUnsetConfigOption
} = require("./git");
test("getRepoPath", async () => {
expect(getRepoPath()).toEqual(process.env["GITHUB_WORKSPACE"]);
expect(getRepoPath("foo")).toEqual(
path.resolve(process.env["GITHUB_WORKSPACE"], "foo")
);
});
test("execGit", async () => {
const repoPath = getRepoPath();
const result = await execGit(
repoPath,
["config", "--local", "--name-only", "--get-regexp", "remote.origin.url"],
true
);
expect(result.exitCode).toEqual(0);
expect(result.stdout.trim()).toEqual("remote.origin.url");
});
test("add and unset config option", async () => {
const repoPath = getRepoPath();
const add = await addConfigOption(repoPath, "test.add.and.unset.config.option", "foo");
expect(add).toBeTruthy();
const unset = await unsetConfigOption(repoPath, "test.add.and.unset.config.option");
expect(unset).toBeTruthy();
});
test("add and unset config option with value regex", async () => {
const repoPath = getRepoPath();
const add = await addConfigOption(repoPath, "test.add.and.unset.config.option", "foo bar");
expect(add).toBeTruthy();
const unset = await unsetConfigOption(repoPath, "test.add.and.unset.config.option", "^foo");
expect(unset).toBeTruthy();
});
test("configOptionExists returns true", async () => {
const repoPath = getRepoPath();
const result = await configOptionExists(repoPath, "remote.origin.url");
expect(result).toBeTruthy();
});
test("configOptionExists returns false", async () => {
const repoPath = getRepoPath();
const result = await configOptionExists(repoPath, "this.key.does.not.exist");
expect(result).toBeFalsy();
});
test("get config option", async () => {
const repoPath = getRepoPath();
const add = await addConfigOption(repoPath, "test.get.config.option", "foo");
expect(add).toBeTruthy();
const option = await getConfigOption(repoPath, "test.get.config.option");
expect(option.value).toEqual("foo");
const unset = await unsetConfigOption(repoPath, "test.get.config.option");
expect(unset).toBeTruthy();
});
test("get config option with value regex", async () => {
const repoPath = getRepoPath();
const add = await addConfigOption(repoPath, "test.get.config.option", "foo bar");
expect(add).toBeTruthy();
const option = await getConfigOption(repoPath, "test.get.config.option", "^foo");
expect(option.value).toEqual("foo bar");
const unset = await unsetConfigOption(repoPath, "test.get.config.option", "^foo");
expect(unset).toBeTruthy();
});
test("get and unset config option is successful", async () => {
const repoPath = getRepoPath();
const add = await addConfigOption(repoPath, "test.get.and.unset.config.option", "foo");
expect(add).toBeTruthy();
const getAndUnset = await getAndUnsetConfigOption(repoPath, "test.get.and.unset.config.option");
expect(getAndUnset.value).toEqual("foo");
});
test("get and unset config option is successful with value regex", async () => {
const repoPath = getRepoPath();
const add = await addConfigOption(repoPath, "test.get.and.unset.config.option", "foo bar");
expect(add).toBeTruthy();
const getAndUnset = await getAndUnsetConfigOption(repoPath, "test.get.and.unset.config.option", "^foo");
expect(getAndUnset.value).toEqual("foo bar");
});
test("get and unset config option is unsuccessful", async () => {
const repoPath = getRepoPath();
const getAndUnset = await getAndUnsetConfigOption(repoPath, "this.key.does.not.exist");
expect(getAndUnset).toBeNull();
});

117
src/git.ts Normal file
View File

@ -0,0 +1,117 @@
import * as core from '@actions/core'
import * as exec from '@actions/exec'
import * as path from 'path'
class GitOutput {
stdout = ''
exitCode = 0
}
export class ConfigOption {
name = ''
value = ''
}
export function getRepoPath(relativePath?: string): string {
let githubWorkspacePath = process.env['GITHUB_WORKSPACE']
if (!githubWorkspacePath) {
throw new Error('GITHUB_WORKSPACE not defined')
}
githubWorkspacePath = path.resolve(githubWorkspacePath)
core.debug(`githubWorkspacePath: ${githubWorkspacePath}`)
let repoPath = githubWorkspacePath
if (relativePath) repoPath = path.resolve(repoPath, relativePath)
core.debug(`repoPath: ${repoPath}`)
return repoPath
}
export async function execGit(
repoPath: string,
args: string[],
ignoreReturnCode = false
): Promise<GitOutput> {
const result = new GitOutput()
const stdout: string[] = []
const options = {
cwd: repoPath,
ignoreReturnCode: ignoreReturnCode,
listeners: {
stdout: (data: Buffer): void => {
stdout.push(data.toString())
}
}
}
result.exitCode = await exec.exec('git', args, options)
result.stdout = stdout.join('')
return result
}
export async function addConfigOption(repoPath, name, value): Promise<boolean> {
const result = await execGit(
repoPath,
['config', '--local', '--add', name, value],
true
)
return result.exitCode === 0
}
export async function unsetConfigOption(
repoPath,
name,
valueRegex = '.'
): Promise<boolean> {
const result = await execGit(
repoPath,
['config', '--local', '--unset', name, valueRegex],
true
)
return result.exitCode === 0
}
export async function configOptionExists(
repoPath,
name,
valueRegex = '.'
): Promise<boolean> {
const result = await execGit(
repoPath,
['config', '--local', '--name-only', '--get-regexp', name, valueRegex],
true
)
return result.exitCode === 0
}
export async function getConfigOption(
repoPath,
name,
valueRegex = '.'
): Promise<ConfigOption> {
const option = new ConfigOption()
const result = await execGit(
repoPath,
['config', '--local', '--get-regexp', name, valueRegex],
true
)
option.name = name
option.value = result.stdout.trim().split(`${name} `)[1]
return option
}
export async function getAndUnsetConfigOption(
repoPath,
name,
valueRegex = '.'
): Promise<ConfigOption> {
if (await configOptionExists(repoPath, name, valueRegex)) {
const option = await getConfigOption(repoPath, name, valueRegex)
if (await unsetConfigOption(repoPath, name, valueRegex)) {
core.debug(`Unset config option '${name}'`)
return option
}
}
return new ConfigOption()
}

View File

@ -1,122 +0,0 @@
const { inspect } = require("util");
const isDocker = require("is-docker");
const core = require("@actions/core");
const exec = require("@actions/exec");
const setupPython = require("./setup-python");
const {
getRepoPath,
getAndUnsetConfigOption,
addConfigOption
} = require("./git");
const EXTRAHEADER_OPTION = "http.https://github.com/.extraheader";
const EXTRAHEADER_VALUE_REGEX = "^AUTHORIZATION:";
async function run() {
try {
// Allows ncc to find assets to be included in the distribution
const cpr = __dirname + "/cpr";
core.debug(`cpr: ${cpr}`);
// Determine how to access python and pip
const { pip, python } = (function() {
if (isDocker()) {
core.info("Running inside a Docker container");
// Python 3 assumed to be installed and on the PATH
return {
pip: "pip3",
python: "python3"
};
} else {
// Setup Python from the tool cache
setupPython("3.x", "x64");
return {
pip: "pip",
python: "python"
};
}
})();
// Install requirements
await exec.exec(pip, [
"install",
"--requirement",
`${cpr}/requirements.txt`,
"--no-index",
`--find-links=${__dirname}/vendor`
]);
// Fetch action inputs
const inputs = {
token: core.getInput("token"),
path: core.getInput("path"),
commitMessage: core.getInput("commit-message"),
committer: core.getInput("committer"),
author: core.getInput("author"),
title: core.getInput("title"),
body: core.getInput("body"),
labels: core.getInput("labels"),
assignees: core.getInput("assignees"),
reviewers: core.getInput("reviewers"),
teamReviewers: core.getInput("team-reviewers"),
milestone: core.getInput("milestone"),
project: core.getInput("project"),
projectColumn: core.getInput("project-column"),
draft: core.getInput("draft"),
branch: core.getInput("branch"),
requestToParent: core.getInput("request-to-parent"),
base: core.getInput("base"),
branchSuffix: core.getInput("branch-suffix")
};
core.debug(`Inputs: ${inspect(inputs)}`);
// Set environment variables from inputs.
if (inputs.token) process.env.GITHUB_TOKEN = inputs.token;
if (inputs.path) process.env.CPR_PATH = inputs.path;
if (inputs.commitMessage) process.env.CPR_COMMIT_MESSAGE = inputs.commitMessage;
if (inputs.committer) process.env.CPR_COMMITTER = inputs.committer;
if (inputs.author) process.env.CPR_AUTHOR = inputs.author;
if (inputs.title) process.env.CPR_TITLE = inputs.title;
if (inputs.body) process.env.CPR_BODY = inputs.body;
if (inputs.labels) process.env.CPR_LABELS = inputs.labels;
if (inputs.assignees) process.env.CPR_ASSIGNEES = inputs.assignees;
if (inputs.reviewers) process.env.CPR_REVIEWERS = inputs.reviewers;
if (inputs.teamReviewers) process.env.CPR_TEAM_REVIEWERS = inputs.teamReviewers;
if (inputs.milestone) process.env.CPR_MILESTONE = inputs.milestone;
if (inputs.project) process.env.CPR_PROJECT_NAME = inputs.project;
if (inputs.projectColumn) process.env.CPR_PROJECT_COLUMN_NAME = inputs.projectColumn;
if (inputs.draft) process.env.CPR_DRAFT = inputs.draft;
if (inputs.branch) process.env.CPR_BRANCH = inputs.branch;
if (inputs.requestToParent) process.env.CPR_REQUEST_TO_PARENT = inputs.requestToParent;
if (inputs.base) process.env.CPR_BASE = inputs.base;
if (inputs.branchSuffix) process.env.CPR_BRANCH_SUFFIX = inputs.branchSuffix;
// Get the repository path
var repoPath = getRepoPath(inputs.path);
// Get the extraheader config option if it exists
var extraHeaderOption = await getAndUnsetConfigOption(
repoPath,
EXTRAHEADER_OPTION,
EXTRAHEADER_VALUE_REGEX
);
// Execute create pull request
await exec.exec(python, [`${cpr}/create_pull_request.py`]);
} catch (error) {
core.setFailed(error.message);
} finally {
// Restore the extraheader config option
if (extraHeaderOption) {
if (
await addConfigOption(
repoPath,
EXTRAHEADER_OPTION,
extraHeaderOption.value
)
)
core.debug(`Restored config option '${EXTRAHEADER_OPTION}'`);
}
}
}
run();

22
src/isDocker.ts Normal file
View File

@ -0,0 +1,22 @@
import * as fs from 'fs'
function hasDockerEnv(): boolean {
try {
fs.statSync('/.dockerenv')
return true
} catch (_) {
return false
}
}
function hasDockerCGroup(): boolean {
try {
return fs.readFileSync('/proc/self/cgroup', 'utf8').includes('docker')
} catch (_) {
return false
}
}
export function isDocker(): boolean {
return hasDockerEnv() || hasDockerCGroup()
}

129
src/main.ts Normal file
View File

@ -0,0 +1,129 @@
import * as core from '@actions/core'
import * as exec from '@actions/exec'
import {isDocker} from './isDocker'
import {setupPython} from './setupPython'
import {
ConfigOption,
getRepoPath,
getAndUnsetConfigOption,
addConfigOption
} from './git'
import {inspect} from 'util'
const EXTRAHEADER_OPTION = 'http.https://github.com/.extraheader'
const EXTRAHEADER_VALUE_REGEX = '^AUTHORIZATION:'
async function run(): Promise<void> {
let repoPath
let extraHeaderOption = new ConfigOption()
try {
// Python assets
const cpr = `${__dirname}/cpr`
core.debug(`cpr: ${cpr}`)
// Determine how to access python and pip
const {pip, python} = (function (): {pip: string; python: string} {
if (isDocker()) {
core.info('Running inside a Docker container')
// Python 3 assumed to be installed and on the PATH
return {
pip: 'pip3',
python: 'python3'
}
} else {
// Setup Python from the tool cache
setupPython('3.x', 'x64')
return {
pip: 'pip',
python: 'python'
}
}
})()
// Install requirements
await exec.exec(pip, [
'install',
'--requirement',
`${cpr}/requirements.txt`,
'--no-index',
`--find-links=${__dirname}/vendor`
])
// Fetch action inputs
const inputs = {
token: core.getInput('token'),
path: core.getInput('path'),
commitMessage: core.getInput('commit-message'),
committer: core.getInput('committer'),
author: core.getInput('author'),
title: core.getInput('title'),
body: core.getInput('body'),
labels: core.getInput('labels'),
assignees: core.getInput('assignees'),
reviewers: core.getInput('reviewers'),
teamReviewers: core.getInput('team-reviewers'),
milestone: core.getInput('milestone'),
project: core.getInput('project'),
projectColumn: core.getInput('project-column'),
draft: core.getInput('draft'),
branch: core.getInput('branch'),
requestToParent: core.getInput('request-to-parent'),
base: core.getInput('base'),
branchSuffix: core.getInput('branch-suffix')
}
core.debug(`Inputs: ${inspect(inputs)}`)
// Set environment variables from inputs.
if (inputs.token) process.env.GITHUB_TOKEN = inputs.token
if (inputs.path) process.env.CPR_PATH = inputs.path
if (inputs.commitMessage)
process.env.CPR_COMMIT_MESSAGE = inputs.commitMessage
if (inputs.committer) process.env.CPR_COMMITTER = inputs.committer
if (inputs.author) process.env.CPR_AUTHOR = inputs.author
if (inputs.title) process.env.CPR_TITLE = inputs.title
if (inputs.body) process.env.CPR_BODY = inputs.body
if (inputs.labels) process.env.CPR_LABELS = inputs.labels
if (inputs.assignees) process.env.CPR_ASSIGNEES = inputs.assignees
if (inputs.reviewers) process.env.CPR_REVIEWERS = inputs.reviewers
if (inputs.teamReviewers)
process.env.CPR_TEAM_REVIEWERS = inputs.teamReviewers
if (inputs.milestone) process.env.CPR_MILESTONE = inputs.milestone
if (inputs.project) process.env.CPR_PROJECT_NAME = inputs.project
if (inputs.projectColumn)
process.env.CPR_PROJECT_COLUMN_NAME = inputs.projectColumn
if (inputs.draft) process.env.CPR_DRAFT = inputs.draft
if (inputs.branch) process.env.CPR_BRANCH = inputs.branch
if (inputs.requestToParent)
process.env.CPR_REQUEST_TO_PARENT = inputs.requestToParent
if (inputs.base) process.env.CPR_BASE = inputs.base
if (inputs.branchSuffix) process.env.CPR_BRANCH_SUFFIX = inputs.branchSuffix
// Get the repository path
repoPath = getRepoPath(inputs.path)
// Get the extraheader config option if it exists
extraHeaderOption = await getAndUnsetConfigOption(
repoPath,
EXTRAHEADER_OPTION,
EXTRAHEADER_VALUE_REGEX
)
// Execute create pull request
await exec.exec(python, [`${cpr}/create_pull_request.py`])
} catch (error) {
core.setFailed(error.message)
} finally {
// Restore the extraheader config option
if (extraHeaderOption.value != '') {
if (
await addConfigOption(
repoPath,
EXTRAHEADER_OPTION,
extraHeaderOption.value
)
)
core.debug(`Restored config option '${EXTRAHEADER_OPTION}'`)
}
}
}
run()

View File

@ -1,52 +0,0 @@
const core = require("@actions/core");
const tc = require("@actions/tool-cache");
const path = require("path");
const semver = require("semver");
/**
* Setup for Python from the GitHub Actions tool cache
* Converted from https://github.com/actions/setup-python
*
* @param {string} versionSpec version of Python
* @param {string} arch architecture (x64|x32)
*/
let setupPython = function(versionSpec, arch) {
return new Promise((resolve, reject) => {
const IS_WINDOWS = process.platform === "win32";
// Find the version of Python we want in the tool cache
const installDir = tc.find("Python", versionSpec, arch);
core.debug(`installDir: ${installDir}`);
// Set paths
core.exportVariable("pythonLocation", installDir);
core.addPath(installDir);
if (IS_WINDOWS) {
core.addPath(path.join(installDir, "Scripts"));
} else {
core.addPath(path.join(installDir, "bin"));
}
if (IS_WINDOWS) {
// Add --user directory
// `installDir` from tool cache should look like $AGENT_TOOLSDIRECTORY/Python/<semantic version>/x64/
// So if `findLocalTool` succeeded above, we must have a conformant `installDir`
const version = path.basename(path.dirname(installDir));
const major = semver.major(version);
const minor = semver.minor(version);
const userScriptsDir = path.join(
process.env["APPDATA"] || "",
"Python",
`Python${major}${minor}`,
"Scripts"
);
core.addPath(userScriptsDir);
}
// On Linux and macOS, pip will create the --user directory and add it to PATH as needed.
resolve();
});
};
module.exports = setupPython;

50
src/setupPython.ts Normal file
View File

@ -0,0 +1,50 @@
import * as core from '@actions/core'
import * as tc from '@actions/tool-cache'
import * as path from 'path'
import * as semver from 'semver'
/**
* Setup for Python from the GitHub Actions tool cache
* Converted from https://github.com/actions/setup-python
*
* @param {string} versionSpec version of Python
* @param {string} arch architecture (x64|x32)
*/
export function setupPython(versionSpec, arch): Promise<void> {
return new Promise(resolve => {
const IS_WINDOWS = process.platform === 'win32'
// Find the version of Python we want in the tool cache
const installDir = tc.find('Python', versionSpec, arch)
core.debug(`installDir: ${installDir}`)
// Set paths
core.exportVariable('pythonLocation', installDir)
core.addPath(installDir)
if (IS_WINDOWS) {
core.addPath(path.join(installDir, 'Scripts'))
} else {
core.addPath(path.join(installDir, 'bin'))
}
if (IS_WINDOWS) {
// Add --user directory
// `installDir` from tool cache should look like $AGENT_TOOLSDIRECTORY/Python/<semantic version>/x64/
// So if `findLocalTool` succeeded above, we must have a conformant `installDir`
const version = path.basename(path.dirname(installDir))
const major = semver.major(version)
const minor = semver.minor(version)
const userScriptsDir = path.join(
process.env['APPDATA'] || '',
'Python',
`Python${major}${minor}`,
'Scripts'
)
core.addPath(userScriptsDir)
}
// On Linux and macOS, pip will create the --user directory and add it to PATH as needed.
resolve()
})
}

16
tsconfig.json Normal file
View File

@ -0,0 +1,16 @@
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"lib": [
"es6"
],
"outDir": "./lib",
"rootDir": "./src",
"declaration": true,
"strict": true,
"noImplicitAny": false,
"esModuleInterop": true
},
"exclude": ["__test__", "lib", "node_modules"]
}