Compare commits
32 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
4d3b0a48ef | ||
![]() |
e9a825aacd | ||
![]() |
3509fd45ae | ||
![]() |
14ee9d1df2 | ||
![]() |
5d969a55c1 | ||
![]() |
44130f6fc9 | ||
![]() |
86ccd8cdef | ||
![]() |
7e7fa32a5f | ||
![]() |
5f7beeb2ff | ||
![]() |
926d56fcba | ||
![]() |
8d744a2cd3 | ||
![]() |
c2d829c681 | ||
![]() |
d77392faf0 | ||
![]() |
ccd2b64012 | ||
![]() |
58fb221778 | ||
![]() |
7a856e8b5d | ||
![]() |
65d7a66451 | ||
![]() |
44a7f59b6f | ||
![]() |
8acaf6bb4c | ||
![]() |
498d78cb23 | ||
![]() |
172ec762f8 | ||
![]() |
5cb0d674f3 | ||
![]() |
eb892d7803 | ||
![]() |
f8274253bd | ||
![]() |
0f423da02c | ||
![]() |
9573f479a0 | ||
![]() |
eb4cde120d | ||
![]() |
25902ccdd1 | ||
![]() |
39b337e8bb | ||
![]() |
7e70d8e63c | ||
![]() |
1a640f5b01 | ||
![]() |
9faa8dc1d9 |
3
.eslintignore
Normal file
3
.eslintignore
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
dist/
|
||||||
|
lib/
|
||||||
|
node_modules/
|
@@ -1,17 +1,19 @@
|
|||||||
{
|
{
|
||||||
"env": {
|
"env": { "node": true, "jest": true },
|
||||||
"commonjs": true,
|
"parser": "@typescript-eslint/parser",
|
||||||
"es6": true,
|
"parserOptions": { "ecmaVersion": 9, "sourceType": "module" },
|
||||||
"node": true
|
"extends": [
|
||||||
},
|
"eslint:recommended",
|
||||||
"extends": "eslint:recommended",
|
"plugin:@typescript-eslint/eslint-recommended",
|
||||||
"globals": {
|
"plugin:@typescript-eslint/recommended",
|
||||||
"Atomics": "readonly",
|
"plugin:import/errors",
|
||||||
"SharedArrayBuffer": "readonly"
|
"plugin:import/warnings",
|
||||||
},
|
"plugin:import/typescript",
|
||||||
"parserOptions": {
|
"plugin:prettier/recommended",
|
||||||
"ecmaVersion": 2018
|
"prettier/@typescript-eslint"
|
||||||
},
|
],
|
||||||
"rules": {
|
"plugins": ["@typescript-eslint"],
|
||||||
}
|
"rules": {
|
||||||
}
|
"@typescript-eslint/camelcase": "off"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
1
.github/CODEOWNERS
vendored
1
.github/CODEOWNERS
vendored
@@ -1 +0,0 @@
|
|||||||
* @peter-evans
|
|
21
.github/workflows/ci.yml
vendored
21
.github/workflows/ci.yml
vendored
@@ -23,31 +23,41 @@ jobs:
|
|||||||
python-version: '3.x'
|
python-version: '3.x'
|
||||||
- run: npm ci
|
- run: npm ci
|
||||||
- run: npm run clean
|
- run: npm run clean
|
||||||
|
- run: npm run build
|
||||||
|
- run: npm run format-check
|
||||||
|
- run: npm run lint
|
||||||
- run: npm run test
|
- run: npm run test
|
||||||
- run: npm run package
|
- run: npm run package
|
||||||
- uses: actions/upload-artifact@v2
|
- uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: dist
|
name: dist
|
||||||
path: dist
|
path: dist
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: action.yml
|
||||||
|
path: action.yml
|
||||||
|
|
||||||
test:
|
test:
|
||||||
|
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository
|
||||||
needs: [build]
|
needs: [build]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
target: [built, committed]
|
target: [built, committed]
|
||||||
steps:
|
steps:
|
||||||
- if: github.event_name == 'push'
|
- uses: actions/checkout@v2
|
||||||
uses: actions/checkout@v2
|
|
||||||
- if: github.event_name == 'pull_request'
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
with:
|
with:
|
||||||
ref: ${{ github.head_ref }}
|
ref: master
|
||||||
- if: matrix.target == 'built' || github.event_name == 'pull_request'
|
- if: matrix.target == 'built' || github.event_name == 'pull_request'
|
||||||
uses: actions/download-artifact@v2
|
uses: actions/download-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: dist
|
name: dist
|
||||||
path: dist
|
path: dist
|
||||||
|
- if: matrix.target == 'built' || github.event_name == 'pull_request'
|
||||||
|
uses: actions/download-artifact@v2
|
||||||
|
with:
|
||||||
|
name: action.yml
|
||||||
|
path: .
|
||||||
|
|
||||||
- name: Create change
|
- name: Create change
|
||||||
run: date +%s > report.txt
|
run: date +%s > report.txt
|
||||||
@@ -105,6 +115,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
- run: rm -rf dist
|
||||||
- uses: actions/download-artifact@v2
|
- uses: actions/download-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: dist
|
name: dist
|
||||||
|
19
.github/workflows/dockerhub-description.yml
vendored
19
.github/workflows/dockerhub-description.yml
vendored
@@ -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
|
|
9
.github/workflows/slash-command-dispatch.yml
vendored
9
.github/workflows/slash-command-dispatch.yml
vendored
@@ -9,8 +9,7 @@ jobs:
|
|||||||
- name: Slash Command Dispatch
|
- name: Slash Command Dispatch
|
||||||
uses: peter-evans/slash-command-dispatch@v1
|
uses: peter-evans/slash-command-dispatch@v1
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.REPO_ACCESS_TOKEN }}
|
token: ${{ secrets.ACTIONS_BOT_TOKEN }}
|
||||||
reaction-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
config: >
|
config: >
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
@@ -34,5 +33,11 @@ jobs:
|
|||||||
"command": "cpr-example",
|
"command": "cpr-example",
|
||||||
"permission": "admin",
|
"permission": "admin",
|
||||||
"issue_type": "issue"
|
"issue_type": "issue"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "rebase",
|
||||||
|
"permission": "admin",
|
||||||
|
"repository": "peter-evans/slash-command-dispatch-processor",
|
||||||
|
"issue_type": "pull-request"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,6 +1,7 @@
|
|||||||
__pycache__
|
__pycache__
|
||||||
.python-version
|
.python-version
|
||||||
|
|
||||||
node_modules
|
lib/
|
||||||
|
node_modules/
|
||||||
|
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
3
.prettierignore
Normal file
3
.prettierignore
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
dist/
|
||||||
|
lib/
|
||||||
|
node_modules/
|
11
.prettierrc.json
Normal file
11
.prettierrc.json
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"printWidth": 80,
|
||||||
|
"tabWidth": 2,
|
||||||
|
"useTabs": false,
|
||||||
|
"semi": false,
|
||||||
|
"singleQuote": true,
|
||||||
|
"trailingComma": "none",
|
||||||
|
"bracketSpacing": false,
|
||||||
|
"arrowParens": "avoid",
|
||||||
|
"parser": "typescript"
|
||||||
|
}
|
31
README.md
31
README.md
@@ -55,10 +55,10 @@ All inputs are **optional**. If not set, sensible default values will be used.
|
|||||||
| `project` | *Deprecated*. See [Create a project card](#create-a-project-card) for details. | |
|
| `project` | *Deprecated*. See [Create a project card](#create-a-project-card) for details. | |
|
||||||
| `project-column` | *Deprecated*. See [Create a project card](#create-a-project-card) for details. | |
|
| `project-column` | *Deprecated*. See [Create a project card](#create-a-project-card) for details. | |
|
||||||
| `draft` | Create a [draft pull request](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests#draft-pull-requests). | `false` |
|
| `draft` | Create a [draft pull request](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests#draft-pull-requests). | `false` |
|
||||||
| `branch` | The branch name. See [Branch naming](#branch-naming) for details. | `create-pull-request/patch` |
|
| `branch` | The branch name. See [Action behaviour](#action-behaviour) for details. | `create-pull-request/patch` |
|
||||||
| `request-to-parent` | Create the pull request in the parent repository of the checked out fork. See [push pull request branches to a fork](https://github.com/peter-evans/create-pull-request/blob/master/docs/concepts-guidelines.md#push-pull-request-branches-to-a-fork) for details. | `false` |
|
| `request-to-parent` | Create the pull request in the parent repository of the checked out fork. See [push pull request branches to a fork](https://github.com/peter-evans/create-pull-request/blob/master/docs/concepts-guidelines.md#push-pull-request-branches-to-a-fork) for details. | `false` |
|
||||||
| `base` | Sets the pull request base branch. | Defaults to the branch checked out in the workflow. |
|
| `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. | |
|
| `branch-suffix` | The branch suffix type. Valid values are `random`, `timestamp` and `short-commit-hash`. See [Action behaviour](#action-behaviour) for details. | |
|
||||||
|
|
||||||
### Action outputs
|
### Action outputs
|
||||||
|
|
||||||
@@ -86,20 +86,29 @@ If there is some reason you need to use `actions/checkout@v1` the following step
|
|||||||
- run: git checkout "${GITHUB_REF:11}"
|
- run: git checkout "${GITHUB_REF:11}"
|
||||||
```
|
```
|
||||||
|
|
||||||
### Branch naming
|
### Action behaviour
|
||||||
|
|
||||||
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.
|
The default behaviour of the action is to create a pull request that will be continually updated with new changes until it is merged or closed.
|
||||||
|
Changes are committed and pushed to a fixed-name branch, the name of which can be configured with the `branch` input.
|
||||||
|
Any subsequent changes will be committed to the *same* branch and reflected in the open pull request.
|
||||||
|
|
||||||
#### Strategy A - Create and update a pull request branch (default)
|
How the action behaves:
|
||||||
|
|
||||||
This strategy is the default behaviour of the action. The input `branch` defaults to `create-pull-request/patch`. Changes will be committed to this branch and a pull request created. Any subsequent changes will be committed to the *same* branch and reflected in the open pull request. If the pull request is merged or closed a new one will be created. If subsequent changes cause the branch to no longer differ from the base the pull request will be automatically closed and the branch deleted.
|
- If there are changes (i.e. a diff exists with the checked out base branch), the changes will be pushed to a new `branch` and a pull request created.
|
||||||
|
- If there are no changes (i.e. no diff exists with the checked out base branch), no pull request will be created and the action exits silently.
|
||||||
|
- If a pull request already exists and there are no further changes (i.e. no diff with the current pull request branch) then the action exits silently.
|
||||||
|
- If a pull request exists and new changes on the base branch make the pull request unnecessary (i.e. there is no longer a diff between the base and pull request branch), the pull request is automatically closed and the branch deleted.
|
||||||
|
|
||||||
#### Strategy B - Always create a new pull request branch
|
For further details about how the action works and usage guidelines, see [Concepts, guidelines and advanced usage](docs/concepts-guidelines.md).
|
||||||
|
|
||||||
For this strategy there are three options to suffix the branch name.
|
#### Alternative strategy - Always create a new pull request branch
|
||||||
The branch name is defined by the input `branch` and defaults to `create-pull-request/patch`. The following options are values for `branch-suffix`.
|
|
||||||
|
|
||||||
- `random` - Commits will be made to a branch suffixed with a random alpha-numeric string. This option should be used if multiple pull requests will be created during the execution of a workflow. e.g. `create-pull-request/patch-6qj97jr`, `create-pull-request/patch-5jrjhvd`
|
For some use cases it *may* be desirable to always create a new unique branch each time there are changes to be committed.
|
||||||
|
This strategy is not recommended and mainly kept for backwards compatibility.
|
||||||
|
|
||||||
|
To use this strategy, set input `branch-suffix` with one of the following options.
|
||||||
|
|
||||||
|
- `random` - Commits will be made to a branch suffixed with a random alpha-numeric string. e.g. `create-pull-request/patch-6qj97jr`, `create-pull-request/patch-5jrjhvd`
|
||||||
|
|
||||||
- `timestamp` - Commits will be made to a branch suffixed by a timestamp. e.g. `create-pull-request/patch-1569322532`, `create-pull-request/patch-1569322552`
|
- `timestamp` - Commits will be made to a branch suffixed by a timestamp. e.g. `create-pull-request/patch-1569322532`, `create-pull-request/patch-1569322552`
|
||||||
|
|
||||||
@@ -206,7 +215,7 @@ jobs:
|
|||||||
echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}"
|
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:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
29
__test__/entrypoint.sh
Executable file
29
__test__/entrypoint.sh
Executable file
@@ -0,0 +1,29 @@
|
|||||||
|
#!/bin/sh -l
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Save the working directory
|
||||||
|
WORKINGDIR=$PWD
|
||||||
|
|
||||||
|
# Serve remote repo
|
||||||
|
mkdir /git
|
||||||
|
git init --bare /git/test-repo.git
|
||||||
|
git daemon --verbose --enable=receive-pack --base-path=/git --export-all /git/test-repo.git &>/dev/null &
|
||||||
|
|
||||||
|
# Give the daemon time to start
|
||||||
|
sleep 2
|
||||||
|
|
||||||
|
# Clone and make an initial commit
|
||||||
|
git clone git://127.0.0.1/test-repo.git /git/test-repo
|
||||||
|
cd /git/test-repo
|
||||||
|
git config --global user.email "you@example.com"
|
||||||
|
git config --global user.name "Your Name"
|
||||||
|
echo "#test-repo" > README.md
|
||||||
|
git add .
|
||||||
|
git commit -m "initial commit"
|
||||||
|
git push -u
|
||||||
|
|
||||||
|
# Restore the working directory
|
||||||
|
cd $WORKINGDIR
|
||||||
|
|
||||||
|
# Execute integration tests
|
||||||
|
jest int
|
153
__test__/git.int.test.ts
Normal file
153
__test__/git.int.test.ts
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
import {
|
||||||
|
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'] = '/git/test-repo'
|
||||||
|
})
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
// Restore GitHub workspace
|
||||||
|
delete process.env['GITHUB_WORKSPACE']
|
||||||
|
if (originalGitHubWorkspace) {
|
||||||
|
process.env['GITHUB_WORKSPACE'] = originalGitHubWorkspace
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('successfully executes a git command', 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()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('determines that a config option exists', async () => {
|
||||||
|
const repoPath = getRepoPath()
|
||||||
|
const result = await configOptionExists(repoPath, 'remote.origin.url')
|
||||||
|
expect(result).toBeTruthy()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('determines that a config option does not exist', 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('')
|
||||||
|
})
|
||||||
|
})
|
26
__test__/git.unit.test.ts
Normal file
26
__test__/git.unit.test.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import * as path from 'path'
|
||||||
|
import {getRepoPath} 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')
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
23
__test__/integration-tests.sh
Executable file
23
__test__/integration-tests.sh
Executable file
@@ -0,0 +1,23 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
IMAGE="cpr-integration-tests:latest"
|
||||||
|
ARG1=${1:-}
|
||||||
|
|
||||||
|
if [[ "$(docker images -q $IMAGE 2> /dev/null)" == "" || $ARG1 == "build" ]]; then
|
||||||
|
echo "Building Docker image $IMAGE ..."
|
||||||
|
|
||||||
|
cat > Dockerfile << EOF
|
||||||
|
FROM node:12-alpine
|
||||||
|
RUN apk --no-cache add git git-daemon
|
||||||
|
RUN npm install jest --global
|
||||||
|
WORKDIR /cpr
|
||||||
|
COPY __test__/entrypoint.sh /entrypoint.sh
|
||||||
|
ENTRYPOINT ["/entrypoint.sh"]
|
||||||
|
EOF
|
||||||
|
|
||||||
|
docker build -t $IMAGE .
|
||||||
|
rm Dockerfile
|
||||||
|
fi
|
||||||
|
|
||||||
|
docker run -v $PWD:/cpr $IMAGE
|
@@ -30,6 +30,8 @@ inputs:
|
|||||||
description: 'Deprecated. See README for details.'
|
description: 'Deprecated. See README for details.'
|
||||||
project-column:
|
project-column:
|
||||||
description: 'Deprecated. See README for details.'
|
description: 'Deprecated. See README for details.'
|
||||||
|
draft:
|
||||||
|
description: 'Create a draft pull request'
|
||||||
branch:
|
branch:
|
||||||
description: 'The pull request branch name.'
|
description: 'The pull request branch name.'
|
||||||
request-to-parent:
|
request-to-parent:
|
||||||
|
2
dist/cpr/common.py
vendored
2
dist/cpr/common.py
vendored
@@ -11,7 +11,7 @@ def get_random_string(length=7, chars=string.ascii_lowercase + string.digits):
|
|||||||
def parse_github_repository(url):
|
def parse_github_repository(url):
|
||||||
# Parse the protocol and github repository from a URL
|
# Parse the protocol and github repository from a URL
|
||||||
# e.g. HTTPS, peter-evans/create-pull-request
|
# e.g. HTTPS, peter-evans/create-pull-request
|
||||||
https_pattern = re.compile(r"^https://github.com/(.+/.+)$")
|
https_pattern = re.compile(r"^https://.*@?github.com/(.+/.+)$")
|
||||||
ssh_pattern = re.compile(r"^git@github.com:(.+/.+).git$")
|
ssh_pattern = re.compile(r"^git@github.com:(.+/.+).git$")
|
||||||
|
|
||||||
match = https_pattern.match(url)
|
match = https_pattern.match(url)
|
||||||
|
0
dist/cpr/create_pull_request.py
vendored
Executable file → Normal file
0
dist/cpr/create_pull_request.py
vendored
Executable file → Normal file
2
dist/cpr/requirements.txt
vendored
2
dist/cpr/requirements.txt
vendored
@@ -1,4 +1,4 @@
|
|||||||
setuptools==46.2.0
|
setuptools==46.4.0
|
||||||
wheel==0.34.2
|
wheel==0.34.2
|
||||||
GitPython==3.1.2
|
GitPython==3.1.2
|
||||||
PyGithub==1.51
|
PyGithub==1.51
|
||||||
|
6
dist/cpr/test_common.py
vendored
6
dist/cpr/test_common.py
vendored
@@ -16,6 +16,12 @@ def test_parse_github_repository_success():
|
|||||||
assert protocol == "HTTPS"
|
assert protocol == "HTTPS"
|
||||||
assert repository == "peter-evans/create-pull-request"
|
assert repository == "peter-evans/create-pull-request"
|
||||||
|
|
||||||
|
protocol, repository = cmn.parse_github_repository(
|
||||||
|
"https://xxx:x-oauth-basic@github.com/peter-evans/create-pull-request"
|
||||||
|
)
|
||||||
|
assert protocol == "HTTPS"
|
||||||
|
assert repository == "peter-evans/create-pull-request"
|
||||||
|
|
||||||
protocol, repository = cmn.parse_github_repository(
|
protocol, repository = cmn.parse_github_repository(
|
||||||
"git@github.com:peter-evans/create-pull-request.git"
|
"git@github.com:peter-evans/create-pull-request.git"
|
||||||
)
|
)
|
||||||
|
751
dist/index.js
vendored
751
dist/index.js
vendored
@@ -34,7 +34,7 @@ module.exports =
|
|||||||
/******/ // the startup function
|
/******/ // the startup function
|
||||||
/******/ function startup() {
|
/******/ function startup() {
|
||||||
/******/ // Load entry module and return exports
|
/******/ // Load entry module and return exports
|
||||||
/******/ return __webpack_require__(676);
|
/******/ return __webpack_require__(198);
|
||||||
/******/ };
|
/******/ };
|
||||||
/******/
|
/******/
|
||||||
/******/ // run startup
|
/******/ // run startup
|
||||||
@@ -952,6 +952,58 @@ class ExecState extends events.EventEmitter {
|
|||||||
|
|
||||||
module.exports = require("tls");
|
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:
|
/***/ 87:
|
||||||
@@ -959,65 +1011,6 @@ module.exports = require("tls");
|
|||||||
|
|
||||||
module.exports = require("os");
|
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:
|
/***/ 129:
|
||||||
@@ -1314,39 +1307,165 @@ exports.debug = debug; // for test
|
|||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
||||||
/***/ 160:
|
/***/ 198:
|
||||||
/***/ (function(module, __unusedexports, __webpack_require__) {
|
/***/ (function(__unusedmodule, exports, __webpack_require__) {
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const fs = __webpack_require__(747);
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||||
|
if (k2 === undefined) k2 = k;
|
||||||
let isDocker;
|
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
||||||
|
}) : (function(o, m, k, k2) {
|
||||||
function hasDockerEnv() {
|
if (k2 === undefined) k2 = k;
|
||||||
try {
|
o[k2] = m[k];
|
||||||
fs.statSync('/.dockerenv');
|
}));
|
||||||
return true;
|
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||||
} catch (_) {
|
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||||
return false;
|
}) : function(o, v) {
|
||||||
}
|
o["default"] = v;
|
||||||
}
|
});
|
||||||
|
var __importStar = (this && this.__importStar) || function (mod) {
|
||||||
function hasDockerCGroup() {
|
if (mod && mod.__esModule) return mod;
|
||||||
try {
|
var result = {};
|
||||||
return fs.readFileSync('/proc/self/cgroup', 'utf8').includes('docker');
|
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||||
} catch (_) {
|
__setModuleDefault(result, mod);
|
||||||
return false;
|
return result;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = () => {
|
|
||||||
if (isDocker === undefined) {
|
|
||||||
isDocker = hasDockerEnv() || hasDockerCGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
return isDocker;
|
|
||||||
};
|
};
|
||||||
|
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
|
//# 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:
|
/***/ 470:
|
||||||
@@ -4592,239 +4843,6 @@ function isUnixExecutable(stats) {
|
|||||||
}
|
}
|
||||||
//# sourceMappingURL=io-util.js.map
|
//# 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:
|
/***/ 722:
|
||||||
@@ -4843,14 +4861,16 @@ function bytesToUuid(buf, offset) {
|
|||||||
var i = offset || 0;
|
var i = offset || 0;
|
||||||
var bth = byteToHex;
|
var bth = byteToHex;
|
||||||
// join used to fix memory issue caused by concatenation: https://bugs.chromium.org/p/v8/issues/detail?id=3175#c4
|
// join used to fix memory issue caused by concatenation: https://bugs.chromium.org/p/v8/issues/detail?id=3175#c4
|
||||||
return ([bth[buf[i++]], bth[buf[i++]],
|
return ([
|
||||||
bth[buf[i++]], bth[buf[i++]], '-',
|
bth[buf[i++]], bth[buf[i++]],
|
||||||
bth[buf[i++]], bth[buf[i++]], '-',
|
bth[buf[i++]], bth[buf[i++]], '-',
|
||||||
bth[buf[i++]], bth[buf[i++]], '-',
|
bth[buf[i++]], bth[buf[i++]], '-',
|
||||||
bth[buf[i++]], bth[buf[i++]], '-',
|
bth[buf[i++]], bth[buf[i++]], '-',
|
||||||
bth[buf[i++]], bth[buf[i++]],
|
bth[buf[i++]], bth[buf[i++]], '-',
|
||||||
bth[buf[i++]], bth[buf[i++]],
|
bth[buf[i++]], bth[buf[i++]],
|
||||||
bth[buf[i++]], bth[buf[i++]]]).join('');
|
bth[buf[i++]], bth[buf[i++]],
|
||||||
|
bth[buf[i++]], bth[buf[i++]]
|
||||||
|
]).join('');
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = bytesToUuid;
|
module.exports = bytesToUuid;
|
||||||
@@ -4979,6 +4999,77 @@ function checkBypass(reqUrl) {
|
|||||||
exports.checkBypass = checkBypass;
|
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:
|
/***/ 979:
|
||||||
|
BIN
dist/vendor/Deprecated-1.2.10.tar.gz
vendored
Normal file
BIN
dist/vendor/Deprecated-1.2.10.tar.gz
vendored
Normal file
Binary file not shown.
BIN
dist/vendor/Deprecated-1.2.9.tar.gz
vendored
BIN
dist/vendor/Deprecated-1.2.9.tar.gz
vendored
Binary file not shown.
BIN
dist/vendor/GitPython-3.1.1.tar.gz
vendored
BIN
dist/vendor/GitPython-3.1.1.tar.gz
vendored
Binary file not shown.
BIN
dist/vendor/PyGithub-1.50.tar.gz
vendored
BIN
dist/vendor/PyGithub-1.50.tar.gz
vendored
Binary file not shown.
BIN
dist/vendor/certifi-2020.4.5.1.tar.gz
vendored
BIN
dist/vendor/certifi-2020.4.5.1.tar.gz
vendored
Binary file not shown.
BIN
dist/vendor/certifi-2020.6.20.tar.gz
vendored
Normal file
BIN
dist/vendor/certifi-2020.6.20.tar.gz
vendored
Normal file
Binary file not shown.
BIN
dist/vendor/gitdb-4.0.4.tar.gz
vendored
BIN
dist/vendor/gitdb-4.0.4.tar.gz
vendored
Binary file not shown.
BIN
dist/vendor/requests-2.23.0.tar.gz
vendored
BIN
dist/vendor/requests-2.23.0.tar.gz
vendored
Binary file not shown.
BIN
dist/vendor/requests-2.24.0.tar.gz
vendored
Normal file
BIN
dist/vendor/requests-2.24.0.tar.gz
vendored
Normal file
Binary file not shown.
BIN
dist/vendor/setuptools-46.1.3.zip
vendored
BIN
dist/vendor/setuptools-46.1.3.zip
vendored
Binary file not shown.
Binary file not shown.
BIN
dist/vendor/smmap-3.0.2.tar.gz
vendored
BIN
dist/vendor/smmap-3.0.2.tar.gz
vendored
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 414 KiB After Width: | Height: | Size: 126 KiB |
@@ -90,7 +90,7 @@ Workflows triggered by `pull_request` events will by default check out a [merge
|
|||||||
|
|
||||||
### Restrictions on forked repositories
|
### 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`.
|
- 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.
|
> 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)
|
[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.
|
A job condition can be added to prevent workflows from executing when triggered by a repository fork.
|
||||||
|
|
||||||
@@ -241,7 +241,9 @@ jobs:
|
|||||||
image: alpine
|
image: alpine
|
||||||
steps:
|
steps:
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: apk --no-cache add git python3
|
run: |
|
||||||
|
apk --no-cache add git python3
|
||||||
|
python3 -m ensurepip
|
||||||
|
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
@@ -5,6 +5,7 @@
|
|||||||
- [Keep a branch up-to-date with another](#keep-a-branch-up-to-date-with-another)
|
- [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)
|
- [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 NPM dependencies](#update-npm-dependencies)
|
||||||
|
- [Update Gradle dependencies](#update-gradle-dependencies)
|
||||||
- [Update SwaggerUI for GitHub Pages](#update-swaggerui-for-github-pages)
|
- [Update SwaggerUI for GitHub Pages](#update-swaggerui-for-github-pages)
|
||||||
- [Spider and download a website](#spider-and-download-a-website)
|
- [Spider and download a website](#spider-and-download-a-website)
|
||||||
- [Use case: Create a pull request to update X by calling the GitHub API](#use-case-create-a-pull-request-to-update-x-by-calling-the-github-api)
|
- [Use case: Create a pull request to update X by calling the GitHub API](#use-case-create-a-pull-request-to-update-x-by-calling-the-github-api)
|
||||||
@@ -144,6 +145,44 @@ jobs:
|
|||||||
- run: npm run build
|
- run: npm run build
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Update Gradle dependencies
|
||||||
|
|
||||||
|
The following workflow will create a pull request for Gradle dependencies.
|
||||||
|
It requires first configuring your project to use Gradle lockfiles.
|
||||||
|
See [here](https://github.com/peter-evans/gradle-auto-dependency-updates) for how to configure your project and use the following workflow.
|
||||||
|
|
||||||
|
```yml
|
||||||
|
name: Update Dependencies
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 1 * * 1'
|
||||||
|
jobs:
|
||||||
|
update-dep:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: actions/setup-java@v1
|
||||||
|
with:
|
||||||
|
java-version: 1.8
|
||||||
|
- name: Grant execute permission for gradlew
|
||||||
|
run: chmod +x gradlew
|
||||||
|
- name: Perform dependency resolution and write new lockfiles
|
||||||
|
run: ./gradlew dependencies --write-locks
|
||||||
|
- name: Create Pull Request
|
||||||
|
uses: peter-evans/create-pull-request@v2
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.PAT }}
|
||||||
|
commit-message: Update dependencies
|
||||||
|
title: Update dependencies
|
||||||
|
body: |
|
||||||
|
- Dependency updates
|
||||||
|
|
||||||
|
Auto-generated by [create-pull-request][1]
|
||||||
|
|
||||||
|
[1]: https://github.com/peter-evans/create-pull-request
|
||||||
|
branch: update-dependencies
|
||||||
|
```
|
||||||
|
|
||||||
### Update SwaggerUI for GitHub Pages
|
### Update SwaggerUI for GitHub Pages
|
||||||
|
|
||||||
When using [GitHub Pages to host Swagger documentation](https://github.com/peter-evans/swagger-github-pages), this workflow updates the repository with the latest distribution of [SwaggerUI](https://github.com/swagger-api/swagger-ui).
|
When using [GitHub Pages to host Swagger documentation](https://github.com/peter-evans/swagger-github-pages), this workflow updates the repository with the latest distribution of [SwaggerUI](https://github.com/swagger-api/swagger-ui).
|
||||||
|
@@ -1,3 +1,11 @@
|
|||||||
process.env = Object.assign(process.env, {
|
module.exports = {
|
||||||
GITHUB_WORKSPACE: __dirname
|
clearMocks: true,
|
||||||
});
|
moduleFileExtensions: ['js', 'ts'],
|
||||||
|
testEnvironment: 'node',
|
||||||
|
testMatch: ['**/*.test.ts'],
|
||||||
|
testRunner: 'jest-circus/runner',
|
||||||
|
transform: {
|
||||||
|
'^.+\\.ts$': 'ts-jest'
|
||||||
|
},
|
||||||
|
verbose: true
|
||||||
|
}
|
||||||
|
4325
package-lock.json
generated
4325
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
36
package.json
36
package.json
@@ -1,21 +1,31 @@
|
|||||||
{
|
{
|
||||||
"name": "create-pull-request",
|
"name": "create-pull-request",
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
|
"private": true,
|
||||||
"description": "Creates a pull request for changes to your repository in the actions workspace",
|
"description": "Creates a pull request for changes to your repository in the actions workspace",
|
||||||
"main": "index.js",
|
"main": "lib/main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"clean": "rm -rf dist",
|
"clean": "rm -rf dist",
|
||||||
"lint": "eslint src/index.js",
|
"build": "tsc && ncc build",
|
||||||
"test": "eslint src/index.js && jest",
|
"format": "prettier --write '**/*.ts'",
|
||||||
"build": "ncc build src/index.js -o dist",
|
"format-check": "prettier --check '**/*.ts'",
|
||||||
|
"lint": "eslint src/**/*.ts",
|
||||||
|
"test:unit": "jest unit",
|
||||||
|
"test:int": "__test__/integration-tests.sh",
|
||||||
|
"test": "npm run test:unit && npm run test:int",
|
||||||
|
"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",
|
"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": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+https://github.com/peter-evans/create-pull-request.git"
|
"url": "git+https://github.com/peter-evans/create-pull-request.git"
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [
|
||||||
|
"actions",
|
||||||
|
"pull",
|
||||||
|
"request"
|
||||||
|
],
|
||||||
"author": "Peter Evans",
|
"author": "Peter Evans",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
@@ -29,8 +39,18 @@
|
|||||||
"is-docker": "2.0.0"
|
"is-docker": "2.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/jest": "25.2.2",
|
||||||
|
"@types/node": "14.0.1",
|
||||||
|
"@typescript-eslint/parser": "2.33.0",
|
||||||
"@zeit/ncc": "0.22.1",
|
"@zeit/ncc": "0.22.1",
|
||||||
"eslint": "6.8.0",
|
"eslint": "7.0.0",
|
||||||
"jest": "26.0.1"
|
"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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -11,7 +11,7 @@ def get_random_string(length=7, chars=string.ascii_lowercase + string.digits):
|
|||||||
def parse_github_repository(url):
|
def parse_github_repository(url):
|
||||||
# Parse the protocol and github repository from a URL
|
# Parse the protocol and github repository from a URL
|
||||||
# e.g. HTTPS, peter-evans/create-pull-request
|
# e.g. HTTPS, peter-evans/create-pull-request
|
||||||
https_pattern = re.compile(r"^https://github.com/(.+/.+)$")
|
https_pattern = re.compile(r"^https://.*@?github.com/(.+/.+)$")
|
||||||
ssh_pattern = re.compile(r"^git@github.com:(.+/.+).git$")
|
ssh_pattern = re.compile(r"^git@github.com:(.+/.+).git$")
|
||||||
|
|
||||||
match = https_pattern.match(url)
|
match = https_pattern.match(url)
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
setuptools==46.2.0
|
setuptools==46.4.0
|
||||||
wheel==0.34.2
|
wheel==0.34.2
|
||||||
GitPython==3.1.2
|
GitPython==3.1.2
|
||||||
PyGithub==1.51
|
PyGithub==1.51
|
||||||
|
@@ -16,6 +16,12 @@ def test_parse_github_repository_success():
|
|||||||
assert protocol == "HTTPS"
|
assert protocol == "HTTPS"
|
||||||
assert repository == "peter-evans/create-pull-request"
|
assert repository == "peter-evans/create-pull-request"
|
||||||
|
|
||||||
|
protocol, repository = cmn.parse_github_repository(
|
||||||
|
"https://xxx:x-oauth-basic@github.com/peter-evans/create-pull-request"
|
||||||
|
)
|
||||||
|
assert protocol == "HTTPS"
|
||||||
|
assert repository == "peter-evans/create-pull-request"
|
||||||
|
|
||||||
protocol, repository = cmn.parse_github_repository(
|
protocol, repository = cmn.parse_github_repository(
|
||||||
"git@github.com:peter-evans/create-pull-request.git"
|
"git@github.com:peter-evans/create-pull-request.git"
|
||||||
)
|
)
|
||||||
|
97
src/git.js
97
src/git.js
@@ -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
|
|
||||||
};
|
|
@@ -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();
|
|
||||||
});
|
|
121
src/git.ts
Normal file
121
src/git.ts
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
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: string,
|
||||||
|
name: string,
|
||||||
|
value: string
|
||||||
|
): Promise<boolean> {
|
||||||
|
const result = await execGit(
|
||||||
|
repoPath,
|
||||||
|
['config', '--local', '--add', name, value],
|
||||||
|
true
|
||||||
|
)
|
||||||
|
return result.exitCode === 0
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function unsetConfigOption(
|
||||||
|
repoPath: string,
|
||||||
|
name: string,
|
||||||
|
valueRegex = '.'
|
||||||
|
): Promise<boolean> {
|
||||||
|
const result = await execGit(
|
||||||
|
repoPath,
|
||||||
|
['config', '--local', '--unset', name, valueRegex],
|
||||||
|
true
|
||||||
|
)
|
||||||
|
return result.exitCode === 0
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function configOptionExists(
|
||||||
|
repoPath: string,
|
||||||
|
name: string,
|
||||||
|
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: string,
|
||||||
|
name: string,
|
||||||
|
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: string,
|
||||||
|
name: string,
|
||||||
|
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()
|
||||||
|
}
|
122
src/index.js
122
src/index.js
@@ -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
22
src/isDocker.ts
Normal 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
129
src/main.ts
Normal 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()
|
@@ -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
50
src/setupPython.ts
Normal 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: string, arch: string): 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
16
tsconfig.json
Normal 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"]
|
||||||
|
}
|
Reference in New Issue
Block a user