Compare commits

...

46 Commits

Author SHA1 Message Date
Peter Evans 1e6b4d1790 Merge pull request #145 from peter-evans/dev
Create pull requests in the parent repository of a checked out fork
2020-03-29 21:02:48 +09:00
Peter Evans a70c6ebe2a Merge pull request #144 from jderusse/fork
Allow custom repository when pushin in fork
2020-03-29 20:47:00 +09:00
Jérémy Derussé 5bd05538d0 Update src/cpr/create_or_update_pull_request.py
Co-Authored-By: Peter Evans <peter-evans@users.noreply.github.com>
2020-03-29 13:36:48 +02:00
Jérémy Derussé 26bc40eea1 Add link in TOC 2020-03-29 12:44:57 +02:00
Jérémy Derussé 6bb0e7771c Apply suggestions from code review
Co-Authored-By: Peter Evans <peter-evans@users.noreply.github.com>
2020-03-29 12:43:21 +02:00
Jérémy Derussé 4c347a4514 Update docs/concepts-guidelines.md
Co-Authored-By: Tobias Nyholm <tobias.nyholm@gmail.com>
2020-03-28 16:42:57 +01:00
Jérémy Derussé cff2c3381d Add doc 2020-03-28 13:27:58 +01:00
Jérémy Derussé e48dab0c1c Add PR creation from Fork 2020-03-28 13:10:12 +01:00
Peter Evans ac9f92d6e7 Merge pull request #141 from peter-evans/renovate/jest-monorepo
Update dependency jest to v25.2.3
2020-03-27 08:15:40 +09:00
Renovate Bot 3ff256ce08 Update dependency jest to v25.2.3 2020-03-26 20:38:32 +00:00
Peter Evans 0bcb10560b Merge pull request #140 from peter-evans/renovate/jest-monorepo
Update dependency jest to v25.2.1
2020-03-26 19:03:52 +09:00
Renovate Bot 3c4b2793c1 Update dependency jest to v25.2.1 2020-03-26 09:43:37 +00:00
Peter Evans 22870d7816 Merge pull request #139 from peter-evans/renovate/jest-monorepo
Update dependency jest to v25.2.0
2020-03-26 10:23:31 +09:00
Renovate Bot e324a22ee1 Update dependency jest to v25.2.0 2020-03-25 18:18:56 +00:00
Peter Evans 8b60386018 Merge pull request #135 from peter-evans/renovate/zeit-ncc-0.x
Update dependency @zeit/ncc to v0.22.0
2020-03-24 09:20:19 +09:00
Renovate Bot 6852d55922 Update dependency @zeit/ncc to v0.22.0 2020-03-23 22:31:46 +00:00
Peter Evans 32e5bb80a5 Merge pull request #134 from peter-evans/dev
Update dependencies
2020-03-21 11:38:19 +09:00
Peter Evans 619cf2115d Update dependencies due to security vulnerabilities 2020-03-21 11:31:34 +09:00
Peter Evans 69008aa567 Update vendored dependencies 2020-03-21 11:29:37 +09:00
Renovate Bot ae4278bf24 Update dependency PyGithub to v1.47 2020-03-21 11:23:42 +09:00
Peter Evans 88da40fea7 Merge pull request #132 from peter-evans/dev
Update dependency GitPython to v3.1.0
2020-03-07 09:08:24 +09:00
Peter Evans 694e068136 Update vendored dependencies 2020-03-07 08:57:59 +09:00
Peter Evans 64c34f6885 Update README 2020-03-03 09:49:52 +09:00
Renovate Bot 52ada17960 Update dependency GitPython to v3.1.0 2020-02-25 13:12:00 +09:00
Peter Evans ce00b952cf Merge pull request #128 from peter-evans/dev
Unset and restore authorization extraheader only
2020-02-22 17:02:15 +09:00
Peter Evans 0d42c285a3 Unset and restore authorization extraheader only 2020-02-22 16:56:42 +09:00
Peter Evans ea1eaf1734 Merge pull request #127 from peter-evans/dev
Unset and restore extraheader config option
2020-02-22 14:53:46 +09:00
Peter Evans d5c5ea3e20 Unset and restore extraheader config option 2020-02-22 14:08:54 +09:00
Peter Evans c7b64af0a4 Merge pull request #123 from peter-evans/dev
Authenticate with git extraheader
2020-02-18 19:49:13 +09:00
Peter Evans 289fda9fea Authenticate with git extraheader 2020-02-18 19:35:15 +09:00
Peter Evans b021b9e27a Update vendored dependencies 2020-02-18 15:59:18 +09:00
Renovate Bot c26314237b Update dependency GitPython to v3.0.8 2020-02-18 15:57:13 +09:00
Peter Evans ed7dd8d236 Update documentation 2020-02-14 20:10:27 +09:00
Peter Evans ca0e9d75fd Update documentation 2020-02-14 00:23:21 +09:00
Peter Evans 87c27ee3eb Merge pull request #118 from peter-evans/dev
Assume python3 on PATH when running in a container
2020-02-14 00:07:03 +09:00
Peter Evans 4beea725d3 Call python3 when running in a container 2020-02-13 17:37:08 +09:00
Peter Evans 9d58699da5 Skip python setup when running in a container 2020-02-13 16:26:04 +09:00
Peter Evans bceebba814 Merge pull request #117 from peter-evans/renovate/zeit-ncc-0.x
Update dependency @zeit/ncc to v0.21.1
2020-02-13 09:58:46 +09:00
Renovate Bot 0b82710b2e Update dependency @zeit/ncc to v0.21.1 2020-02-12 16:54:11 +00:00
Peter Evans 4aaaa0e760 Update README 2020-02-11 16:36:16 +09:00
Peter Evans 918bfcb8a3 Update README 2020-02-11 16:28:16 +09:00
Peter Evans 1ecfd1ae40 Merge pull request #116 from peter-evans/dev
Update dependency PyGithub to v1.46
2020-02-11 14:03:17 +09:00
Peter Evans 4dd195d7c3 Update vendored dependencies 2020-02-11 13:51:59 +09:00
Renovate Bot 72b5f45bb4 Update dependency PyGithub to v1.46 2020-02-11 13:49:50 +09:00
Peter Evans 5394814b39 Update documentation 2020-02-11 01:21:05 +09:00
Peter Evans 83918398f5 Update documentation 2020-02-11 01:15:59 +09:00
44 changed files with 6818 additions and 279 deletions
+17
View File
@@ -0,0 +1,17 @@
{
"env": {
"commonjs": true,
"es6": true,
"node": true
},
"extends": "eslint:recommended",
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parserOptions": {
"ecmaVersion": 2018
},
"rules": {
}
}
@@ -30,6 +30,7 @@ jobs:
project: Example Project
project-column: To do
branch: example-patches
request-to-parent: false
- name: Check outputs
run: |
echo "Pull Request Number - ${{ env.PULL_REQUEST_NUMBER }}"
+5 -18
View File
@@ -18,7 +18,7 @@ Create Pull Request action will:
## Documentation
- [Concepts and guidelines](docs/concepts-guidelines.md)
- [Concepts, guidelines and advanced usage](docs/concepts-guidelines.md)
- [Examples](docs/examples.md)
- [Updating from v1](docs/updating.md)
@@ -37,8 +37,7 @@ You can also pin to a [specific release](https://github.com/peter-evans/create-p
With the exception of `token`, all inputs are **optional**. If not set, sensible default values will be used.
**Note**: If you want pull requests created by this action to trigger an `on: pull_request` workflow then you must use a [Personal Access Token](https://help.github.com/en/articles/creating-a-personal-access-token-for-the-command-line) instead of the default `GITHUB_TOKEN`.
See [this issue](https://github.com/peter-evans/create-pull-request/issues/48) for further details.
**Note**: If you want pull requests created by this action to trigger an `on: push` or `on: pull_request` workflow then you must use a [Personal Access Token](https://help.github.com/en/articles/creating-a-personal-access-token-for-the-command-line) instead of the default `GITHUB_TOKEN`. Alternatively, allow the action to [push using SSH](https://github.com/peter-evans/create-pull-request/blob/master/docs/concepts-guidelines.md#push-using-ssh-deploy-keys) by configuring a deploy key.
| Name | Description | Default |
| --- | --- | --- |
@@ -57,6 +56,7 @@ See [this issue](https://github.com/peter-evans/create-pull-request/issues/48) f
| `project` | The name of the project for which a card should be created. Requires `project-column`. | |
| `project-column` | The name of the project column under which a card should be created. Requires `project`. | |
| `branch` | The branch name. See [Branch naming](#branch-naming) for details. | `create-pull-request/patch` |
| `request-to-parent` | Create the pull request in the parent repository of the checked out fork. | `false` |
| `base` | Sets the pull request base branch. | Defaults to the branch checked out in the workflow. |
| `branch-suffix` | The branch suffix type. Valid values are `random`, `timestamp` and `short-commit-hash`. See [Branch naming](#branch-naming) for details. | |
@@ -88,21 +88,6 @@ If there is some reason you need to use `actions/checkout@v1` the following step
- run: git checkout "${GITHUB_REF:11}"
```
Checking out a branch from a different repository from where the workflow is executing will make *that repository* the target for the created pull request. In this case, a `repo` scoped [Personal Access Token (PAT)](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line) is required.
```yml
- uses: actions/checkout@v2
with:
token: ${{ secrets.PAT }}
repository: owner/repo
# Create changes to pull request here
- uses: peter-evans/create-pull-request@v2
with:
token: ${{ secrets.PAT }}
```
### Branch naming
For branch naming there are two strategies. Create a fixed-name pull request branch that will be updated with new changes until it is merged or closed, OR, always create a new unique branch each time there are changes to be committed.
@@ -197,10 +182,12 @@ jobs:
labels: report, automated pr
assignees: peter-evans
reviewers: peter-evans
team-reviewers: owners, maintainers
milestone: 1
project: Example Project
project-column: To do
branch: example-patches
request-to-parent: false
- name: Check outputs
run: |
echo "Pull Request Number - ${{ env.PULL_REQUEST_NUMBER }}"
+4 -1
View File
@@ -32,6 +32,9 @@ inputs:
description: 'The name of the project column under which a card should be created.'
branch:
description: 'The pull request branch name.'
request-to-parent:
description: 'Create the pull request in the parent repository of the checked out fork.'
default: false
base:
description: 'The pull request base branch.'
branch-suffix:
@@ -43,5 +46,5 @@ runs:
using: 'node12'
main: 'dist/index.js'
branding:
icon: 'git-pull-request'
icon: 'git-pull-request'
color: 'gray-dark'
View File
@@ -56,25 +56,37 @@ def create_or_update_pull_request(
team_reviewers,
project_name,
project_column_name,
request_to_parent,
):
if request_to_parent is None:
request_to_parent = False
else:
request_to_parent = request_to_parent.lower() in ['true', '1', 't', 'y', 'yes', 'on']
github_repo = head_repo = Github(github_token).get_repo(github_repository)
if request_to_parent:
github_repo = github_repo.parent
if github_repo is None:
raise ValueError("The checked out repository is not a fork. Input 'request-to-parent' should be set to false.")
head_branch = f"{head_repo.owner.login}:{branch}"
# Create the pull request
github_repo = Github(github_token).get_repo(github_repository)
try:
pull_request = github_repo.create_pull(
title=title, body=body, base=base, head=branch
title=title, body=body, base=base, head=head_branch
)
print(f"Created pull request #{pull_request.number} ({branch} => {base})")
print(f"Created pull request #{pull_request.number} ({head_branch} => {github_repo.owner.login}:{base})")
except GithubException as e:
if e.status == 422:
# A pull request exists for this branch and base
head_branch = "{}:{}".format(github_repository.split("/")[0], branch)
# Get the pull request
pull_request = github_repo.get_pulls(
state="open", base=base, head=head_branch
)[0]
# Update title and body
pull_request.as_issue().edit(title=title, body=body)
print(f"Updated pull request #{pull_request.number} ({branch} => {base})")
print(f"Updated pull request #{pull_request.number} ({head_branch} => {github_repo.owner.login}:{base})")
else:
print(str(e))
raise
@@ -1,5 +1,6 @@
#!/usr/bin/env python3
""" Create Pull Request """
import base64
import common as cmn
import create_or_update_branch as coub
import create_or_update_pull_request as coupr
@@ -31,7 +32,7 @@ def get_git_config_value(repo, name):
return None
def get_repository_detail():
def get_repository_detail(repo):
remote_origin_url = get_git_config_value(repo, "remote.origin.url")
if remote_origin_url is None:
raise ValueError("Failed to fetch 'remote.origin.url' from git config")
@@ -116,9 +117,21 @@ repo = Repo(path)
# Determine the GitHub repository from git config
# This will be the target repository for the pull request
repo_url, protocol, github_repository = get_repository_detail()
repo_url, protocol, github_repository = get_repository_detail(repo)
print(f"Target repository set to {github_repository}")
if protocol == "HTTPS":
print(f"::debug::Using HTTPS protocol")
# Encode and configure the basic credential for HTTPS access
basic_credential = base64.b64encode(
f"x-access-token:{github_token}".encode("utf-8")
).decode("utf-8")
# Mask the basic credential in logs and debug output
print(f"::add-mask::{basic_credential}")
repo.git.set_persistent_git_options(
c=f"http.https://github.com/.extraheader=AUTHORIZATION: basic {basic_credential}"
)
# Determine if the checked out ref is a valid base for a pull request
# The action needs the checked out HEAD ref to be a branch
# This check will fail in the following cases:
@@ -174,11 +187,6 @@ except ValueError as e:
print(f"::error::{e} " + "Unable to continue. Exiting.")
sys.exit(1)
# Set the auth token in the repo URL
# This supports checkout@v1. From v2 the auth token is saved for further use.
if protocol == "HTTPS":
repo_url = f"https://x-access-token:{github_token}@github.com/{github_repository}"
# Create or update the pull request branch
result = coub.create_or_update_branch(repo, repo_url, commit_message, base, branch)
@@ -216,4 +224,5 @@ if result["action"] in ["created", "updated"]:
os.environ.get("CPR_TEAM_REVIEWERS"),
os.environ.get("CPR_PROJECT_NAME"),
os.environ.get("CPR_PROJECT_COLUMN_NAME"),
os.environ.get("CPR_REQUEST_TO_PARENT"),
)
+2
View File
@@ -0,0 +1,2 @@
GitPython==3.1.0
PyGithub==1.47
+292 -119
View File
@@ -34,7 +34,7 @@ module.exports =
/******/ // the startup function
/******/ function startup() {
/******/ // Load entry module and return exports
/******/ return __webpack_require__(104);
/******/ return __webpack_require__(676);
/******/ };
/******/
/******/ // run startup
@@ -973,21 +973,6 @@ module.exports = util.assign(
module.exports = require("tls");
/***/ }),
/***/ 58:
/***/ (function(module, __unusedexports, __webpack_require__) {
// Unique ID creation requires a high quality random # generator. In node.js
// this is pretty straight-forward - we use the crypto API.
var crypto = __webpack_require__(417);
module.exports = function nodeRNG() {
return crypto.randomBytes(16);
};
/***/ }),
/***/ 87:
@@ -998,108 +983,6 @@ module.exports = require("os");
/***/ }),
/***/ 104:
/***/ (function(__unusedmodule, __unusedexports, __webpack_require__) {
const { inspect } = __webpack_require__(669);
const fs = __webpack_require__(747);
const core = __webpack_require__(470);
const exec = __webpack_require__(986);
const setupPython = __webpack_require__(139);
function fileExists(path) {
try {
return fs.statSync(path).isFile();
} catch (e) {
core.debug(`e: ${inspect(e)}`);
return false;
}
}
async function run() {
try {
// Allows ncc to find assets to be included in the distribution
const src = __webpack_require__.ab + "src";
core.debug(`src: ${src}`);
// Check if the platfrom is Alpine Linux
const alpineLinux = fileExists("/etc/alpine-release");
core.debug(`alpineLinux: ${alpineLinux}`);
// Skip Python setup if the platform is Alpine Linux
if (!alpineLinux)
// Setup Python from the tool cache
setupPython("3.8.x", "x64");
// Install requirements
await exec.exec("pip", [
"install",
"--requirement",
`${src}/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"),
branch: core.getInput("branch"),
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.branch) process.env.CPR_BRANCH = inputs.branch;
if (inputs.base) process.env.CPR_BASE = inputs.base;
if (inputs.branchSuffix) process.env.CPR_BRANCH_SUFFIX = inputs.branchSuffix;
// Execute python script
await exec.exec("python", [`${src}/create_pull_request.py`]);
} catch (error) {
core.setFailed(error.message);
}
}
run();
/***/ }),
/***/ 129:
/***/ (function(module) {
module.exports = require("child_process");
/***/ }),
/***/ 139:
/***/ (function(module, __unusedexports, __webpack_require__) {
const core = __webpack_require__(470);
@@ -1156,6 +1039,28 @@ let setupPython = function(versionSpec, arch) {
module.exports = setupPython;
/***/ }),
/***/ 129:
/***/ (function(module) {
module.exports = require("child_process");
/***/ }),
/***/ 139:
/***/ (function(module, __unusedexports, __webpack_require__) {
// Unique ID creation requires a high quality random # generator. In node.js
// this is pretty straight-forward - we use the crypto API.
var crypto = __webpack_require__(417);
module.exports = function nodeRNG() {
return crypto.randomBytes(16);
};
/***/ }),
/***/ 141:
@@ -1411,6 +1316,43 @@ if (process.env.NODE_DEBUG && /\btunnel\b/.test(process.env.NODE_DEBUG)) {
exports.debug = debug; // for test
/***/ }),
/***/ 160:
/***/ (function(module, __unusedexports, __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;
};
/***/ }),
/***/ 211:
@@ -4263,6 +4205,237 @@ 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"),
branch: core.getInput("branch"),
request_to_parent: 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.branch) process.env.CPR_BRANCH = inputs.branch;
if (inputs.request_to_parent) process.env.CPR_REQUEST_TO_PARENT = inputs.request_to_parent;
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:
@@ -4695,7 +4868,7 @@ module.exports = require("zlib");
/***/ 826:
/***/ (function(module, __unusedexports, __webpack_require__) {
var rng = __webpack_require__(58);
var rng = __webpack_require__(139);
var bytesToUuid = __webpack_require__(722);
function v4(options, buf, offset) {
-2
View File
@@ -1,2 +0,0 @@
GitPython==3.0.7
PyGithub==1.45
-52
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;
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+161 -28
View File
@@ -1,6 +1,6 @@
# Concepts and guidelines
# Concepts, guidelines and advanced usage
This document covers terminology, how the action works, and general usage guidelines.
This document covers terminology, how the action works, general usage guidelines, and advanced usage.
- [Terminology](#terminology)
- [Events and checkout](#events-and-checkout)
@@ -9,8 +9,13 @@ This document covers terminology, how the action works, and general usage guidel
- [Providing a consistent base](#providing-a-consistent-base)
- [Pull request events](#pull-request-events)
- [Restrictions on forked repositories](#restrictions-on-forked-repositories)
- [Tag push events](#tag-push-events)
- [Security](#security)
- [Advanced usage](#advanced-usage)
- [Creating pull requests in a remote repository](#creating-pull-requests-in-a-remote-repository)
- [Push using SSH (deploy keys)](#push-using-ssh-deploy-keys)
- [Push pull request branches to a fork](#push-pull-request-branches-to-a-fork)
- [Running in a container](#running-in-a-container)
- [Creating pull requests on tag push](#creating-pull-requests-on-tag-push)
## Terminology
@@ -108,7 +113,157 @@ jobs:
if: github.event.pull_request.head.repo.full_name == github.repository
```
### Tag push events
### Security
From a security perspective it's good practice to fork third-party actions, review the code, and use your fork of the action in workflows.
By using third-party actions directly the risk exists that it could be modified to do something malicious, such as capturing secrets.
This action uses [ncc](https://github.com/zeit/ncc) to compile the Node.js code and dependencies into a single file.
Python dependencies are vendored and committed to the repository [here](https://github.com/peter-evans/create-pull-request/tree/master/dist/vendor).
No dependencies are downloaded during the action execution.
Vendored Python dependencies can be reviewed by rebuilding the [dist](https://github.com/peter-evans/create-pull-request/tree/master/dist) directory and redownloading dependencies.
The following commands require Node and Python 3.
```
npm install
npm run clean
npm run package
```
The `dist` directory should be rebuilt leaving no git diff.
## Advanced usage
### Creating pull requests in a remote repository
Checking out a branch from a different repository from where the workflow is executing will make *that repository* the target for the created pull request. In this case, a `repo` scoped [Personal Access Token (PAT)](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line) is required.
```yml
- uses: actions/checkout@v2
with:
token: ${{ secrets.PAT }}
repository: owner/repo
# Make changes to pull request here
- uses: peter-evans/create-pull-request@v2
with:
token: ${{ secrets.PAT }}
```
### Push using SSH (deploy keys)
[Deploy keys](https://developer.github.com/v3/guides/managing-deploy-keys/#deploy-keys) can be set per repository and so are arguably more secure than using a `repo` scoped [Personal Access Token (PAT)](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line).
Allowing the action to push with a configured deploy key will trigger `on: push` workflows. This makes it an alternative to using a PAT to trigger checks for pull requests.
How to use SSH (deploy keys) with create-pull-request action:
1. [Create a new SSH key pair](https://help.github.com/en/github/authenticating-to-github/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent#generating-a-new-ssh-key) for your repository. Do not set a passphrase.
2. Copy the contents of the public key (.pub file) to a new repository [deploy key](https://developer.github.com/v3/guides/managing-deploy-keys/#deploy-keys) and check the box to "Allow write access."
3. Add a secret to the repository containing the entire contents of the private key.
4. As shown in the example steps below, use the [`webfactory/ssh-agent`](https://github.com/webfactory/ssh-agent) action to install the private key and clone your repository. Remember to checkout the `base` of your pull request if it's not the default branch, e.g. `git checkout my-branch`.
```yml
steps:
- uses: webfactory/ssh-agent@v0.2.0
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
- name: Checkout via SSH
run: git clone git@github.com:peter-evans/create-pull-request.git .
# Make changes to pull request here
- name: Create Pull Request
uses: peter-evans/create-pull-request@v2
with:
token: ${{ secrets.GITHUB_TOKEN }}
```
### Push pull request branches to a fork
To enforce security, you can use a dedicated user using [machine account](https://help.github.com/en/github/site-policy/github-terms-of-service#3-account-requirements).
This user has no access to the main repository, it will use their own fork to push code and create the pull request.
1. Create a new github user, then login with this user.
2. fork the repository.
3. create a [Personal Access Token (PAT)](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line).
4. logout and go back to your main user.
5. Add a secret to the repository containing the above PAT.
6. As shown in the example below, switch the git remote to the fork's url after checkout and set the action input `request-on-parent` to `true`.
```yaml
- uses: actions/checkout@v2
- run: |
git config user.password ${{ secrets.PAT }}
git remote set-url origin https://github.com/bot-user/fork-project
git fetch --unshallow -p origin
# Make changes to pull request here
- uses: peter-evans/create-pull-request@v2
with:
token: ${{ secrets.PAT }}
request-on-parent: true
```
### Running in a container
This action can be run inside a container by installing the action's dependencies either in the Docker image itself, or during the workflow.
The action requires `python3`, `pip3` and `git` to be installed and on the `PATH`.
Note that `actions/checkout` requires Git 2.18 or higher to be installed, otherwise it will just download the source of the repository instead of cloning it.
**Alpine container example:**
```yml
jobs:
createPullRequestAlpine:
runs-on: ubuntu-latest
container:
image: alpine
steps:
- name: Install dependencies
run: apk --no-cache add git python3
- uses: actions/checkout@v2
# Make changes to pull request here
- name: Create Pull Request
uses: peter-evans/create-pull-request@v2
with:
token: ${{ secrets.GITHUB_TOKEN }}
```
**Ubuntu container example:**
```yml
jobs:
createPullRequestAlpine:
runs-on: ubuntu-latest
container:
image: ubuntu
steps:
- name: Install dependencies
run: |
apt-get update
apt-get install -y software-properties-common
add-apt-repository -y ppa:git-core/ppa
apt-get install -y python3 python3-pip git
- uses: actions/checkout@v2
# Make changes to pull request here
- name: Create Pull Request
uses: peter-evans/create-pull-request@v2
with:
token: ${{ secrets.GITHUB_TOKEN }}
```
### Creating pull requests on tag push
An `on: push` workflow will also trigger when tags are pushed.
During these events, the `actions/checkout` action will check out the `ref/tags/<tag>` git ref by default.
@@ -134,8 +289,7 @@ jobs:
git checkout -b temp-${GITHUB_REF:10}
git push --set-upstream origin temp-${GITHUB_REF:10}
- name: Create changes to pull request
run: <create changes here>
# Make changes to pull request here
- name: Create Pull Request
uses: peter-evans/create-pull-request@v2
@@ -164,31 +318,10 @@ jobs:
with:
ref: master
- name: Create changes to pull request
run: <create changes here>
# Make changes to pull request here
- name: Create Pull Request
uses: peter-evans/create-pull-request@v2
with:
token: ${{ secrets.GITHUB_TOKEN }}
```
### Security
From a security perspective it's good practice to fork third-party actions, review the code, and use your fork of the action in workflows.
By using third-party actions directly the risk exists that it could be modified to do something malicious, such as capturing secrets.
This action uses [ncc](https://github.com/zeit/ncc) to compile the Node.js code and dependencies into a single file.
Python dependencies are vendored and committed to the repository [here](https://github.com/peter-evans/create-pull-request/tree/master/dist/vendor).
No dependencies are downloaded during the action execution.
Vendored Python dependencies can be reviewed by rebuilding the [dist](https://github.com/peter-evans/create-pull-request/tree/master/dist) directory and redownloading dependencies.
The following commands require Node and Python 3.
```
npm install
npm run clean
npm run package
```
The `dist` directory should be rebuilt leaving no git diff.
+31
View File
@@ -2,6 +2,7 @@
- [Use case: Create a pull request to update X on push](#use-case-create-a-pull-request-to-update-x-on-push)
- [Update project authors](#update-project-authors)
- [Keep a branch up-to-date with another](#keep-a-branch-up-to-date-with-another)
- [Use case: Create a pull request to update X periodically](#use-case-create-a-pull-request-to-update-x-periodically)
- [Update NPM dependencies](#update-npm-dependencies)
- [Update SwaggerUI for GitHub Pages](#update-swaggerui-for-github-pages)
@@ -51,6 +52,36 @@ jobs:
branch: update-authors
```
### Keep a branch up-to-date with another
This is a use case where a branch should be kept up to date with another by opening a pull request to update it. The pull request should then be updated with new changes until it is merged or closed.
In this example scenario, a branch called `production` should be updated via pull request to keep it in sync with `master`. Merging the pull request is effectively promoting those changes to production.
```yml
name: Create production promotion pull request
on:
push:
branches:
- master
jobs:
productionPromotion:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
ref: production
- name: Reset promotion branch
run: |
git fetch origin master:master
git reset --hard master
- name: Create Pull Request
uses: peter-evans/create-pull-request@v2
with:
token: ${{ secrets.GITHUB_TOKEN }}
branch: production-promotion
```
## Use case: Create a pull request to update X periodically
This pattern will work well for updating any kind of static content from an external source. The workflow executes on a schedule and raises a pull request when there are changes.
+3
View File
@@ -0,0 +1,3 @@
process.env = Object.assign(process.env, {
GITHUB_WORKSPACE: __dirname
});
+5972 -3
View File
File diff suppressed because it is too large Load Diff
+9 -4
View File
@@ -5,8 +5,10 @@
"main": "index.js",
"scripts": {
"clean": "rm -rf dist",
"build": "ncc build index.js -o dist",
"vendor-deps": "pip download -r src/requirements.txt --no-binary=:all: -d dist/vendor",
"lint": "eslint src/index.js",
"test": "eslint src/index.js && jest",
"build": "ncc build src/index.js -o dist",
"vendor-deps": "pip download -r src/cpr/requirements.txt --no-binary=:all: -d dist/vendor",
"package": "npm run build && npm run vendor-deps"
},
"repository": {
@@ -23,9 +25,12 @@
"dependencies": {
"@actions/core": "^1.1.1",
"@actions/exec": "^1.0.1",
"@actions/tool-cache": "^1.1.2"
"@actions/tool-cache": "^1.1.2",
"is-docker": "^2.0.0"
},
"devDependencies": {
"@zeit/ncc": "0.21.0"
"@zeit/ncc": "0.22.0",
"eslint": "6.8.0",
"jest": "25.2.3"
}
}
View File
@@ -56,25 +56,37 @@ def create_or_update_pull_request(
team_reviewers,
project_name,
project_column_name,
request_to_parent,
):
if request_to_parent is None:
request_to_parent = False
else:
request_to_parent = request_to_parent.lower() in ['true', '1', 't', 'y', 'yes', 'on']
github_repo = head_repo = Github(github_token).get_repo(github_repository)
if request_to_parent:
github_repo = github_repo.parent
if github_repo is None:
raise ValueError("The checked out repository is not a fork. Input 'request-to-parent' should be set to false.")
head_branch = f"{head_repo.owner.login}:{branch}"
# Create the pull request
github_repo = Github(github_token).get_repo(github_repository)
try:
pull_request = github_repo.create_pull(
title=title, body=body, base=base, head=branch
title=title, body=body, base=base, head=head_branch
)
print(f"Created pull request #{pull_request.number} ({branch} => {base})")
print(f"Created pull request #{pull_request.number} ({head_branch} => {github_repo.owner.login}:{base})")
except GithubException as e:
if e.status == 422:
# A pull request exists for this branch and base
head_branch = "{}:{}".format(github_repository.split("/")[0], branch)
# Get the pull request
pull_request = github_repo.get_pulls(
state="open", base=base, head=head_branch
)[0]
# Update title and body
pull_request.as_issue().edit(title=title, body=body)
print(f"Updated pull request #{pull_request.number} ({branch} => {base})")
print(f"Updated pull request #{pull_request.number} ({head_branch} => {github_repo.owner.login}:{base})")
else:
print(str(e))
raise
@@ -1,5 +1,6 @@
#!/usr/bin/env python3
""" Create Pull Request """
import base64
import common as cmn
import create_or_update_branch as coub
import create_or_update_pull_request as coupr
@@ -31,7 +32,7 @@ def get_git_config_value(repo, name):
return None
def get_repository_detail():
def get_repository_detail(repo):
remote_origin_url = get_git_config_value(repo, "remote.origin.url")
if remote_origin_url is None:
raise ValueError("Failed to fetch 'remote.origin.url' from git config")
@@ -116,9 +117,21 @@ repo = Repo(path)
# Determine the GitHub repository from git config
# This will be the target repository for the pull request
repo_url, protocol, github_repository = get_repository_detail()
repo_url, protocol, github_repository = get_repository_detail(repo)
print(f"Target repository set to {github_repository}")
if protocol == "HTTPS":
print(f"::debug::Using HTTPS protocol")
# Encode and configure the basic credential for HTTPS access
basic_credential = base64.b64encode(
f"x-access-token:{github_token}".encode("utf-8")
).decode("utf-8")
# Mask the basic credential in logs and debug output
print(f"::add-mask::{basic_credential}")
repo.git.set_persistent_git_options(
c=f"http.https://github.com/.extraheader=AUTHORIZATION: basic {basic_credential}"
)
# Determine if the checked out ref is a valid base for a pull request
# The action needs the checked out HEAD ref to be a branch
# This check will fail in the following cases:
@@ -174,17 +187,12 @@ except ValueError as e:
print(f"::error::{e} " + "Unable to continue. Exiting.")
sys.exit(1)
# Set the auth token in the repo URL
# This supports checkout@v1. From v2 the auth token is saved for further use.
if protocol == "HTTPS":
repo_url = f"https://x-access-token:{github_token}@github.com/{github_repository}"
# Create or update the pull request branch
result = coub.create_or_update_branch(repo, repo_url, commit_message, base, branch)
if result["action"] in ["created", "updated"]:
# The branch was created or updated
print(f"Pushing pull request branch to 'origin/{branch}'")
print(f"Pushing pull request branch to '{repo.full_name}/{branch}'")
repo.git.push("--force", repo_url, f"HEAD:refs/heads/{branch}")
# Set the base. It would have been 'None' if not specified as an input
@@ -216,4 +224,5 @@ if result["action"] in ["created", "updated"]:
os.environ.get("CPR_TEAM_REVIEWERS"),
os.environ.get("CPR_PROJECT_NAME"),
os.environ.get("CPR_PROJECT_COLUMN_NAME"),
os.environ.get("CPR_REQUEST_TO_PARENT"),
)
+2
View File
@@ -0,0 +1,2 @@
GitPython==3.1.0
PyGithub==1.47
+97
View File
@@ -0,0 +1,97 @@
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
};
+98
View File
@@ -0,0 +1,98 @@
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();
});
+57 -25
View File
@@ -1,38 +1,47 @@
const { inspect } = require("util");
const fs = require("fs");
const isDocker = require("is-docker");
const core = require("@actions/core");
const exec = require("@actions/exec");
const setupPython = require("./src/setup-python");
const setupPython = require("./setup-python");
const {
getRepoPath,
getAndUnsetConfigOption,
addConfigOption
} = require("./git");
function fileExists(path) {
try {
return fs.statSync(path).isFile();
} catch (e) {
core.debug(`e: ${inspect(e)}`);
return false;
}
}
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 src = __dirname + "/src";
core.debug(`src: ${src}`);
const cpr = __dirname + "/cpr";
core.debug(`cpr: ${cpr}`);
// Check if the platfrom is Alpine Linux
const alpineLinux = fileExists("/etc/alpine-release");
core.debug(`alpineLinux: ${alpineLinux}`);
// Skip Python setup if the platform is Alpine Linux
if (!alpineLinux)
// Setup Python from the tool cache
setupPython("3.8.x", "x64");
// 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", [
await exec.exec(pip, [
"install",
"--requirement",
`${src}/requirements.txt`,
`${cpr}/requirements.txt`,
"--no-index",
`--find-links=${__dirname}/vendor`
]);
@@ -54,8 +63,9 @@ async function run() {
project: core.getInput("project"),
projectColumn: core.getInput("project-column"),
branch: core.getInput("branch"),
request_to_parent: core.getInput("request-to-parent"),
base: core.getInput("base"),
branchSuffix: core.getInput("branch-suffix"),
branchSuffix: core.getInput("branch-suffix")
};
core.debug(`Inputs: ${inspect(inputs)}`);
@@ -75,13 +85,35 @@ async function run() {
if (inputs.project) process.env.CPR_PROJECT_NAME = inputs.project;
if (inputs.projectColumn) process.env.CPR_PROJECT_COLUMN_NAME = inputs.projectColumn;
if (inputs.branch) process.env.CPR_BRANCH = inputs.branch;
if (inputs.request_to_parent) process.env.CPR_REQUEST_TO_PARENT = inputs.request_to_parent;
if (inputs.base) process.env.CPR_BASE = inputs.base;
if (inputs.branchSuffix) process.env.CPR_BRANCH_SUFFIX = inputs.branchSuffix;
// Execute python script
await exec.exec("python", [`${src}/create_pull_request.py`]);
// 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}'`);
}
}
}
-2
View File
@@ -1,2 +0,0 @@
GitPython==3.0.7
PyGithub==1.45