Compare commits
95 Commits
Author | SHA1 | Date | |
---|---|---|---|
271a8d0340 | |||
6f7efd1c24 | |||
13c47c5747 | |||
63e58290d7 | |||
a92c90fcab | |||
b23b62d487 | |||
dd2324fc52 | |||
367180cbdf | |||
25575a12f3 | |||
a56e7a56e9 | |||
eac17dc6a3 | |||
a2e685f814 | |||
6cfd146ec9 | |||
b38e8d38a1 | |||
8a41570d99 | |||
2e9b4cc10e | |||
1681a83d43 | |||
ba5b4b46a5 | |||
479e1068be | |||
15ab4d71d8 | |||
a39470890e | |||
9821aed555 | |||
49cf7e9854 | |||
176fdd231e | |||
842a5fb093 | |||
9965b9dd5e | |||
e23e628200 | |||
16bbacf50f | |||
c4623efb09 | |||
2539354181 | |||
c52b9e2028 | |||
ae3093d7e8 | |||
8606317131 | |||
a302671c1f | |||
67ccf781d6 | |||
bb88e27d3f | |||
b378ed537a | |||
fa9200e5b4 | |||
16e0059bfd | |||
5bffd5ae80 | |||
a22a0ddc21 | |||
b27ce378c8 | |||
4e0cc19e22 | |||
25b6871a4e | |||
507d0a9edf | |||
5474387748 | |||
fd327677a6 | |||
2d6e2b85ac | |||
059edeb68d | |||
c8c4196500 | |||
28b3f122d6 | |||
fb9d3b16d6 | |||
ce71ba0ccb | |||
48e05473b3 | |||
56c2d957df | |||
0c478ad1a0 | |||
6d751ce675 | |||
2aadff01a4 | |||
5da4e80e7b | |||
f3328ea675 | |||
2b17eaf819 | |||
dcbbee9996 | |||
36234c3f4b | |||
7f04a931a2 | |||
41fe70dee0 | |||
fecb38a4ba | |||
31f0a785ee | |||
6a95549605 | |||
91d9b1abea | |||
e60c9f9016 | |||
5fb55cc7c4 | |||
4a018ca361 | |||
f495c14b47 | |||
6d225c24a0 | |||
7920c48d6a | |||
d24ced9c1f | |||
5e914681df | |||
2f38cd26bf | |||
7a8aeac749 | |||
d39d596a77 | |||
f6f978fd3d | |||
6cd32fd936 | |||
d121e62763 | |||
f4d66f4d5a | |||
488c869d17 | |||
5354f85616 | |||
8867c4aba1 | |||
6073f5434b | |||
6d01b5601c | |||
25cf8451c3 | |||
d87b980a0e | |||
119d131ea9 | |||
73e6230af4 | |||
c0348e860f | |||
4320041ed3 |
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@ -124,7 +124,7 @@ jobs:
|
|||||||
name: dist
|
name: dist
|
||||||
path: dist
|
path: dist
|
||||||
- name: Create Pull Request
|
- name: Create Pull Request
|
||||||
uses: peter-evans/create-pull-request@v6
|
uses: peter-evans/create-pull-request@v7
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.ACTIONS_BOT_TOKEN }}
|
token: ${{ secrets.ACTIONS_BOT_TOKEN }}
|
||||||
commit-message: 'build: update distribution'
|
commit-message: 'build: update distribution'
|
||||||
|
4
.github/workflows/cpr-example-command.yml
vendored
4
.github/workflows/cpr-example-command.yml
vendored
@ -29,8 +29,8 @@ jobs:
|
|||||||
labels: |
|
labels: |
|
||||||
report
|
report
|
||||||
automated pr
|
automated pr
|
||||||
assignees: peter-evans
|
assignees: retepsnave
|
||||||
reviewers: peter-evans
|
reviewers: retepsnave
|
||||||
milestone: 1
|
milestone: 1
|
||||||
draft: false
|
draft: false
|
||||||
branch: example-patches
|
branch: example-patches
|
||||||
|
6
.github/workflows/slash-command-dispatch.yml
vendored
6
.github/workflows/slash-command-dispatch.yml
vendored
@ -18,12 +18,6 @@ jobs:
|
|||||||
"repository": "peter-evans/create-pull-request-tests",
|
"repository": "peter-evans/create-pull-request-tests",
|
||||||
"named_args": true
|
"named_args": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"command": "testv5",
|
|
||||||
"permission": "admin",
|
|
||||||
"repository": "peter-evans/create-pull-request-tests",
|
|
||||||
"named_args": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"command": "clean",
|
"command": "clean",
|
||||||
"permission": "admin",
|
"permission": "admin",
|
||||||
|
2
.github/workflows/update-major-version.yml
vendored
2
.github/workflows/update-major-version.yml
vendored
@ -11,8 +11,8 @@ on:
|
|||||||
type: choice
|
type: choice
|
||||||
description: The major version tag to update
|
description: The major version tag to update
|
||||||
options:
|
options:
|
||||||
- v5
|
|
||||||
- v6
|
- v6
|
||||||
|
- v7
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
tag:
|
tag:
|
||||||
|
24
README.md
24
README.md
@ -15,13 +15,13 @@ Create Pull Request action will:
|
|||||||
- tracked (modified) files
|
- tracked (modified) files
|
||||||
- commits made during the workflow that have not been pushed
|
- commits made during the workflow that have not been pushed
|
||||||
2. Commit all changes to a new branch, or update an existing pull request branch.
|
2. Commit all changes to a new branch, or update an existing pull request branch.
|
||||||
3. Create a pull request to merge the new branch into the base—the branch checked out in the workflow.
|
3. Create or update a pull request to merge the branch into the base—the branch checked out in the workflow.
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
- [Concepts, guidelines and advanced usage](docs/concepts-guidelines.md)
|
- [Concepts, guidelines and advanced usage](docs/concepts-guidelines.md)
|
||||||
- [Examples](docs/examples.md)
|
- [Examples](docs/examples.md)
|
||||||
- [Updating to v6](docs/updating.md)
|
- [Updating to v7](docs/updating.md)
|
||||||
- [Common issues](docs/common-issues.md)
|
- [Common issues](docs/common-issues.md)
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
@ -99,7 +99,7 @@ Other token options:
|
|||||||
#### branch-token
|
#### branch-token
|
||||||
|
|
||||||
The action first creates a branch, and then creates a pull request for the branch.
|
The action first creates a branch, and then creates a pull request for the branch.
|
||||||
For some rare use cases it can be useful, or even neccessary, to use different tokens for these operations.
|
For some rare use cases it can be useful, or even necessary, to use different tokens for these operations.
|
||||||
It is not advisable to use this input unless you know you need to.
|
It is not advisable to use this input unless you know you need to.
|
||||||
|
|
||||||
#### commit-message
|
#### commit-message
|
||||||
@ -246,24 +246,6 @@ Note that the repository must be checked out on a branch with a remote, it won't
|
|||||||
uses: peter-evans/create-pull-request@v7
|
uses: peter-evans/create-pull-request@v7
|
||||||
```
|
```
|
||||||
|
|
||||||
### Create a project card
|
|
||||||
|
|
||||||
To create a project card for the pull request, pass the `pull-request-number` step output to [create-or-update-project-card](https://github.com/peter-evans/create-or-update-project-card) action.
|
|
||||||
|
|
||||||
```yml
|
|
||||||
- name: Create Pull Request
|
|
||||||
id: cpr
|
|
||||||
uses: peter-evans/create-pull-request@v7
|
|
||||||
|
|
||||||
- name: Create or Update Project Card
|
|
||||||
if: ${{ steps.cpr.outputs.pull-request-number }}
|
|
||||||
uses: peter-evans/create-or-update-project-card@v2
|
|
||||||
with:
|
|
||||||
project-name: My project
|
|
||||||
column-name: My column
|
|
||||||
issue-number: ${{ steps.cpr.outputs.pull-request-number }}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Auto-merge
|
### Auto-merge
|
||||||
|
|
||||||
Auto-merge can be enabled on a pull request allowing it to be automatically merged once requirements have been satisfied.
|
Auto-merge can be enabled on a pull request allowing it to be automatically merged once requirements have been satisfied.
|
||||||
|
@ -250,11 +250,15 @@ describe('create-or-update-branch tests', () => {
|
|||||||
expect(branchCommits.length).toEqual(1)
|
expect(branchCommits.length).toEqual(1)
|
||||||
expect(branchCommits[0].subject).toEqual('Test changes')
|
expect(branchCommits[0].subject).toEqual('Test changes')
|
||||||
expect(branchCommits[0].changes.length).toEqual(3)
|
expect(branchCommits[0].changes.length).toEqual(3)
|
||||||
expect(branchCommits[0].changes).toEqual([
|
expect(branchCommits[0].changes[0].mode).toEqual('100755')
|
||||||
{mode: '100755', path: UNTRACKED_EXE_FILE, status: 'A'},
|
expect(branchCommits[0].changes[0].path).toEqual(UNTRACKED_EXE_FILE)
|
||||||
{mode: '100644', path: TRACKED_FILE, status: 'M'},
|
expect(branchCommits[0].changes[0].status).toEqual('A')
|
||||||
{mode: '100644', path: UNTRACKED_FILE, status: 'A'}
|
expect(branchCommits[0].changes[1].mode).toEqual('100644')
|
||||||
])
|
expect(branchCommits[0].changes[1].path).toEqual(TRACKED_FILE)
|
||||||
|
expect(branchCommits[0].changes[1].status).toEqual('M')
|
||||||
|
expect(branchCommits[0].changes[2].mode).toEqual('100644')
|
||||||
|
expect(branchCommits[0].changes[2].path).toEqual(UNTRACKED_FILE)
|
||||||
|
expect(branchCommits[0].changes[2].status).toEqual('A')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('tests buildBranchCommits with addition and deletion', async () => {
|
it('tests buildBranchCommits with addition and deletion', async () => {
|
||||||
@ -272,11 +276,15 @@ describe('create-or-update-branch tests', () => {
|
|||||||
expect(branchCommits.length).toEqual(1)
|
expect(branchCommits.length).toEqual(1)
|
||||||
expect(branchCommits[0].subject).toEqual('Test changes')
|
expect(branchCommits[0].subject).toEqual('Test changes')
|
||||||
expect(branchCommits[0].changes.length).toEqual(3)
|
expect(branchCommits[0].changes.length).toEqual(3)
|
||||||
expect(branchCommits[0].changes).toEqual([
|
expect(branchCommits[0].changes[0].mode).toEqual('100644')
|
||||||
{mode: '100644', path: TRACKED_FILE, status: 'D'},
|
expect(branchCommits[0].changes[0].path).toEqual(TRACKED_FILE)
|
||||||
{mode: '100644', path: UNTRACKED_FILE, status: 'A'},
|
expect(branchCommits[0].changes[0].status).toEqual('D')
|
||||||
{mode: '100644', path: TRACKED_FILE_NEW_PATH, status: 'A'}
|
expect(branchCommits[0].changes[1].mode).toEqual('100644')
|
||||||
])
|
expect(branchCommits[0].changes[1].path).toEqual(UNTRACKED_FILE)
|
||||||
|
expect(branchCommits[0].changes[1].status).toEqual('A')
|
||||||
|
expect(branchCommits[0].changes[2].mode).toEqual('100644')
|
||||||
|
expect(branchCommits[0].changes[2].path).toEqual(TRACKED_FILE_NEW_PATH)
|
||||||
|
expect(branchCommits[0].changes[2].status).toEqual('A')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('tests buildBranchCommits with multiple commits', async () => {
|
it('tests buildBranchCommits with multiple commits', async () => {
|
||||||
@ -294,10 +302,13 @@ describe('create-or-update-branch tests', () => {
|
|||||||
expect(branchCommits[i].subject).toEqual(`Test changes ${i}`)
|
expect(branchCommits[i].subject).toEqual(`Test changes ${i}`)
|
||||||
expect(branchCommits[i].changes.length).toEqual(2)
|
expect(branchCommits[i].changes.length).toEqual(2)
|
||||||
const untrackedFileStatus = i == 0 ? 'A' : 'M'
|
const untrackedFileStatus = i == 0 ? 'A' : 'M'
|
||||||
expect(branchCommits[i].changes).toEqual([
|
|
||||||
{mode: '100644', path: TRACKED_FILE, status: 'M'},
|
expect(branchCommits[i].changes[0].mode).toEqual('100644')
|
||||||
{mode: '100644', path: UNTRACKED_FILE, status: untrackedFileStatus}
|
expect(branchCommits[i].changes[0].path).toEqual(TRACKED_FILE)
|
||||||
])
|
expect(branchCommits[i].changes[0].status).toEqual('M')
|
||||||
|
expect(branchCommits[i].changes[1].mode).toEqual('100644')
|
||||||
|
expect(branchCommits[i].changes[1].path).toEqual(UNTRACKED_FILE)
|
||||||
|
expect(branchCommits[i].changes[1].status).toEqual(untrackedFileStatus)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -19,14 +19,17 @@ git clone git://127.0.0.1/repos/test-base.git /git/local/repos/test-base
|
|||||||
cd /git/local/repos/test-base
|
cd /git/local/repos/test-base
|
||||||
git config --global user.email "you@example.com"
|
git config --global user.email "you@example.com"
|
||||||
git config --global user.name "Your Name"
|
git config --global user.name "Your Name"
|
||||||
echo "#test-base" > README.md
|
echo "#test-base" > README→TEMP.md
|
||||||
git add .
|
git add .
|
||||||
git commit -m "initial commit"
|
git commit -m "initial commit"
|
||||||
git commit --allow-empty -m "empty commit for tests"
|
git commit --allow-empty -m "empty commit for tests"
|
||||||
echo "#test-base :sparkles:" > README.md
|
echo "#test-base :sparkles:" > README→TEMP.md
|
||||||
git add .
|
git add .
|
||||||
git commit -m "add sparkles" -m "Change description:
|
git commit -m "add sparkles" -m "Change description:
|
||||||
- updates README.md to add sparkles to the title"
|
- updates README→TEMP.md to add sparkles to the title"
|
||||||
|
mv README→TEMP.md README.md
|
||||||
|
git add .
|
||||||
|
git commit -m "rename readme"
|
||||||
git push -u
|
git push -u
|
||||||
git log -1 --pretty=oneline
|
git log -1 --pretty=oneline
|
||||||
git config --global --unset user.email
|
git config --global --unset user.email
|
||||||
|
@ -11,15 +11,16 @@ describe('git-command-manager integration tests', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('tests getCommit', async () => {
|
it('tests getCommit', async () => {
|
||||||
const initialCommit = await git.getCommit('HEAD^^')
|
const initialCommit = await git.getCommit('HEAD^^^')
|
||||||
const emptyCommit = await git.getCommit('HEAD^')
|
const emptyCommit = await git.getCommit('HEAD^^')
|
||||||
|
const modifiedCommit = await git.getCommit('HEAD^')
|
||||||
const headCommit = await git.getCommit('HEAD')
|
const headCommit = await git.getCommit('HEAD')
|
||||||
|
|
||||||
expect(initialCommit.subject).toEqual('initial commit')
|
expect(initialCommit.subject).toEqual('initial commit')
|
||||||
expect(initialCommit.signed).toBeFalsy()
|
expect(initialCommit.signed).toBeFalsy()
|
||||||
expect(initialCommit.changes).toEqual([
|
expect(initialCommit.changes[0].mode).toEqual('100644')
|
||||||
{mode: '100644', status: 'A', path: 'README.md'}
|
expect(initialCommit.changes[0].status).toEqual('A')
|
||||||
])
|
expect(initialCommit.changes[0].path).toEqual('README→TEMP.md') // filename contains unicode
|
||||||
|
|
||||||
expect(emptyCommit.subject).toEqual('empty commit for tests')
|
expect(emptyCommit.subject).toEqual('empty commit for tests')
|
||||||
expect(emptyCommit.tree).toEqual(initialCommit.tree) // empty commits have no tree and reference the parent's
|
expect(emptyCommit.tree).toEqual(initialCommit.tree) // empty commits have no tree and reference the parent's
|
||||||
@ -27,11 +28,21 @@ describe('git-command-manager integration tests', () => {
|
|||||||
expect(emptyCommit.signed).toBeFalsy()
|
expect(emptyCommit.signed).toBeFalsy()
|
||||||
expect(emptyCommit.changes).toEqual([])
|
expect(emptyCommit.changes).toEqual([])
|
||||||
|
|
||||||
expect(headCommit.subject).toEqual('add sparkles')
|
expect(modifiedCommit.subject).toEqual('add sparkles')
|
||||||
expect(headCommit.parents[0]).toEqual(emptyCommit.sha)
|
expect(modifiedCommit.parents[0]).toEqual(emptyCommit.sha)
|
||||||
|
expect(modifiedCommit.signed).toBeFalsy()
|
||||||
|
expect(modifiedCommit.changes[0].mode).toEqual('100644')
|
||||||
|
expect(modifiedCommit.changes[0].status).toEqual('M')
|
||||||
|
expect(modifiedCommit.changes[0].path).toEqual('README→TEMP.md')
|
||||||
|
|
||||||
|
expect(headCommit.subject).toEqual('rename readme')
|
||||||
|
expect(headCommit.parents[0]).toEqual(modifiedCommit.sha)
|
||||||
expect(headCommit.signed).toBeFalsy()
|
expect(headCommit.signed).toBeFalsy()
|
||||||
expect(headCommit.changes).toEqual([
|
expect(headCommit.changes[0].mode).toEqual('100644')
|
||||||
{mode: '100644', status: 'M', path: 'README.md'}
|
expect(headCommit.changes[0].status).toEqual('A')
|
||||||
])
|
expect(headCommit.changes[0].path).toEqual('README.md')
|
||||||
|
expect(headCommit.changes[1].mode).toEqual('100644')
|
||||||
|
expect(headCommit.changes[1].status).toEqual('D')
|
||||||
|
expect(headCommit.changes[1].path).toEqual('README→TEMP.md')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
16
dist/790.index.js
vendored
Normal file
16
dist/790.index.js
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
"use strict";
|
||||||
|
exports.id = 790;
|
||||||
|
exports.ids = [790];
|
||||||
|
exports.modules = {
|
||||||
|
|
||||||
|
/***/ 790:
|
||||||
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
||||||
|
|
||||||
|
var N=Object.defineProperty;var c=(_,a)=>N(_,"name",{value:a,configurable:!0});__webpack_require__(3024),__webpack_require__(6760);const node=__webpack_require__(117);__webpack_require__(7067),__webpack_require__(4708),__webpack_require__(8522),__webpack_require__(7075),__webpack_require__(4573),__webpack_require__(7975),__webpack_require__(3465),__webpack_require__(3136),__webpack_require__(7030);let s=0;const S={START_BOUNDARY:s++,HEADER_FIELD_START:s++,HEADER_FIELD:s++,HEADER_VALUE_START:s++,HEADER_VALUE:s++,HEADER_VALUE_ALMOST_DONE:s++,HEADERS_ALMOST_DONE:s++,PART_DATA_START:s++,PART_DATA:s++,END:s++};let f=1;const F={PART_BOUNDARY:f,LAST_BOUNDARY:f*=2},LF=10,CR=13,SPACE=32,HYPHEN=45,COLON=58,A=97,Z=122,lower=c(_=>_|32,"lower"),noop=c(()=>{},"noop");class MultipartParser{static{c(this,"MultipartParser")}constructor(a){this.index=0,this.flags=0,this.onHeaderEnd=noop,this.onHeaderField=noop,this.onHeadersEnd=noop,this.onHeaderValue=noop,this.onPartBegin=noop,this.onPartData=noop,this.onPartEnd=noop,this.boundaryChars={},a=`\r
|
||||||
|
--`+a;const t=new Uint8Array(a.length);for(let n=0;n<a.length;n++)t[n]=a.charCodeAt(n),this.boundaryChars[t[n]]=!0;this.boundary=t,this.lookbehind=new Uint8Array(this.boundary.length+8),this.state=S.START_BOUNDARY}write(a){let t=0;const n=a.length;let E=this.index,{lookbehind:d,boundary:h,boundaryChars:H,index:e,state:o,flags:l}=this;const b=this.boundary.length,m=b-1,O=a.length;let r,P;const u=c(D=>{this[D+"Mark"]=t},"mark"),i=c(D=>{delete this[D+"Mark"]},"clear"),T=c((D,p,R,g)=>{(p===void 0||p!==R)&&this[D](g&&g.subarray(p,R))},"callback"),L=c((D,p)=>{const R=D+"Mark";R in this&&(p?(T(D,this[R],t,a),delete this[R]):(T(D,this[R],a.length,a),this[R]=0))},"dataCallback");for(t=0;t<n;t++)switch(r=a[t],o){case S.START_BOUNDARY:if(e===h.length-2){if(r===HYPHEN)l|=F.LAST_BOUNDARY;else if(r!==CR)return;e++;break}else if(e-1===h.length-2){if(l&F.LAST_BOUNDARY&&r===HYPHEN)o=S.END,l=0;else if(!(l&F.LAST_BOUNDARY)&&r===LF)e=0,T("onPartBegin"),o=S.HEADER_FIELD_START;else return;break}r!==h[e+2]&&(e=-2),r===h[e+2]&&e++;break;case S.HEADER_FIELD_START:o=S.HEADER_FIELD,u("onHeaderField"),e=0;case S.HEADER_FIELD:if(r===CR){i("onHeaderField"),o=S.HEADERS_ALMOST_DONE;break}if(e++,r===HYPHEN)break;if(r===COLON){if(e===1)return;L("onHeaderField",!0),o=S.HEADER_VALUE_START;break}if(P=lower(r),P<A||P>Z)return;break;case S.HEADER_VALUE_START:if(r===SPACE)break;u("onHeaderValue"),o=S.HEADER_VALUE;case S.HEADER_VALUE:r===CR&&(L("onHeaderValue",!0),T("onHeaderEnd"),o=S.HEADER_VALUE_ALMOST_DONE);break;case S.HEADER_VALUE_ALMOST_DONE:if(r!==LF)return;o=S.HEADER_FIELD_START;break;case S.HEADERS_ALMOST_DONE:if(r!==LF)return;T("onHeadersEnd"),o=S.PART_DATA_START;break;case S.PART_DATA_START:o=S.PART_DATA,u("onPartData");case S.PART_DATA:if(E=e,e===0){for(t+=m;t<O&&!(a[t]in H);)t+=b;t-=m,r=a[t]}if(e<h.length)h[e]===r?(e===0&&L("onPartData",!0),e++):e=0;else if(e===h.length)e++,r===CR?l|=F.PART_BOUNDARY:r===HYPHEN?l|=F.LAST_BOUNDARY:e=0;else if(e-1===h.length)if(l&F.PART_BOUNDARY){if(e=0,r===LF){l&=~F.PART_BOUNDARY,T("onPartEnd"),T("onPartBegin"),o=S.HEADER_FIELD_START;break}}else l&F.LAST_BOUNDARY&&r===HYPHEN?(T("onPartEnd"),o=S.END,l=0):e=0;if(e>0)d[e-1]=r;else if(E>0){const D=new Uint8Array(d.buffer,d.byteOffset,d.byteLength);T("onPartData",0,E,D),E=0,u("onPartData"),t--}break;case S.END:break;default:throw new Error(`Unexpected state entered: ${o}`)}L("onHeaderField"),L("onHeaderValue"),L("onPartData"),this.index=e,this.state=o,this.flags=l}end(){if(this.state===S.HEADER_FIELD_START&&this.index===0||this.state===S.PART_DATA&&this.index===this.boundary.length)this.onPartEnd();else if(this.state!==S.END)throw new Error("MultipartParser.end(): stream ended unexpectedly")}}function _fileName(_){const a=_.match(/\bfilename=("(.*?)"|([^()<>@,;:\\"/[\]?={}\s\t]+))($|;\s)/i);if(!a)return;const t=a[2]||a[3]||"";let n=t.slice(t.lastIndexOf("\\")+1);return n=n.replace(/%22/g,'"'),n=n.replace(/&#(\d{4});/g,(E,d)=>String.fromCharCode(d)),n}c(_fileName,"_fileName");async function toFormData(_,a){if(!/multipart/i.test(a))throw new TypeError("Failed to fetch");const t=a.match(/boundary=(?:"([^"]+)"|([^;]+))/i);if(!t)throw new TypeError("no or bad content-type header, no multipart boundary");const n=new MultipartParser(t[1]||t[2]);let E,d,h,H,e,o;const l=[],b=new node.FormData,m=c(i=>{h+=u.decode(i,{stream:!0})},"onPartData"),O=c(i=>{l.push(i)},"appendToFile"),r=c(()=>{const i=new node.File(l,o,{type:e});b.append(H,i)},"appendFileToFormData"),P=c(()=>{b.append(H,h)},"appendEntryToFormData"),u=new TextDecoder("utf-8");u.decode(),n.onPartBegin=function(){n.onPartData=m,n.onPartEnd=P,E="",d="",h="",H="",e="",o=null,l.length=0},n.onHeaderField=function(i){E+=u.decode(i,{stream:!0})},n.onHeaderValue=function(i){d+=u.decode(i,{stream:!0})},n.onHeaderEnd=function(){if(d+=u.decode(),E=E.toLowerCase(),E==="content-disposition"){const i=d.match(/\bname=("([^"]*)"|([^()<>@,;:\\"/[\]?={}\s\t]+))/i);i&&(H=i[2]||i[3]||""),o=_fileName(d),o&&(n.onPartData=O,n.onPartEnd=r)}else E==="content-type"&&(e=d);d="",E=""};for await(const i of _)n.write(i);return n.end(),b}c(toFormData,"toFormData"),exports.toFormData=toFormData;
|
||||||
|
|
||||||
|
|
||||||
|
/***/ })
|
||||||
|
|
||||||
|
};
|
||||||
|
;
|
29511
dist/index.js
vendored
29511
dist/index.js
vendored
File diff suppressed because it is too large
Load Diff
@ -231,7 +231,7 @@ It will use their own fork to push code and create the pull request.
|
|||||||
|
|
||||||
1. Create a new GitHub user and login.
|
1. Create a new GitHub user and login.
|
||||||
2. Fork the repository that you will be creating pull requests in.
|
2. Fork the repository that you will be creating pull requests in.
|
||||||
3. Create a Classic [Personal Access Token (PAT)](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token) with `repo` scope.
|
3. Create a Classic [Personal Access Token (PAT)](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token) with `repo` and `workflow` scopes.
|
||||||
4. Logout and log back into your main user account.
|
4. Logout and log back into your main user account.
|
||||||
5. Add a secret to your repository containing the above PAT.
|
5. Add a secret to your repository containing the above PAT.
|
||||||
6. As shown in the following example workflow, set the `push-to-fork` input to the full repository name of the fork.
|
6. As shown in the following example workflow, set the `push-to-fork` input to the full repository name of the fork.
|
||||||
@ -303,7 +303,7 @@ GitHub App generated tokens can be configured with fine-grained permissions and
|
|||||||
- Uncheck `Active` under `Webhook`. You do not need to enter a `Webhook URL`.
|
- Uncheck `Active` under `Webhook`. You do not need to enter a `Webhook URL`.
|
||||||
- Under `Repository permissions: Contents` select `Access: Read & write`.
|
- Under `Repository permissions: Contents` select `Access: Read & write`.
|
||||||
- Under `Repository permissions: Pull requests` select `Access: Read & write`.
|
- Under `Repository permissions: Pull requests` select `Access: Read & write`.
|
||||||
- Under `Repository permissions: Workflows` select `Access: Read-only`.
|
- Under `Repository permissions: Workflows` select `Access: Read & write`.
|
||||||
- **NOTE**: Only needed if pull requests could contain changes to Actions workflows.
|
- **NOTE**: Only needed if pull requests could contain changes to Actions workflows.
|
||||||
- Under `Organization permissions: Members` select `Access: Read-only`.
|
- Under `Organization permissions: Members` select `Access: Read-only`.
|
||||||
- **NOTE**: Only needed if you would like add teams as reviewers to PRs.
|
- **NOTE**: Only needed if you would like add teams as reviewers to PRs.
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
- [Dynamic configuration using variables](#dynamic-configuration-using-variables)
|
- [Dynamic configuration using variables](#dynamic-configuration-using-variables)
|
||||||
- [Using a markdown template](#using-a-markdown-template)
|
- [Using a markdown template](#using-a-markdown-template)
|
||||||
- [Debugging GitHub Actions](#debugging-github-actions)
|
- [Debugging GitHub Actions](#debugging-github-actions)
|
||||||
|
- [Show an annotation message for a created pull request](#show-an-annotation-message-for-a-created-pull-request)
|
||||||
|
|
||||||
## Use case: Create a pull request to update X on push
|
## Use case: Create a pull request to update X on push
|
||||||
|
|
||||||
@ -324,7 +324,7 @@ jobs:
|
|||||||
|
|
||||||
### Keep a fork up-to-date with its upstream
|
### Keep a fork up-to-date with its upstream
|
||||||
|
|
||||||
This example is designed to be run in a seperate repository from the fork repository itself.
|
This example is designed to be run in a separate repository from the fork repository itself.
|
||||||
The aim of this is to prevent committing anything to the fork's default branch would cause it to differ from the upstream.
|
The aim of this is to prevent committing anything to the fork's default branch would cause it to differ from the upstream.
|
||||||
|
|
||||||
In the following example workflow, `owner/repo` is the upstream repository and `fork-owner/repo` is the fork. It assumes the default branch of the upstream repository is called `main`.
|
In the following example workflow, `owner/repo` is the upstream repository and `fork-owner/repo` is the fork. It assumes the default branch of the upstream repository is called `main`.
|
||||||
@ -612,3 +612,30 @@ To enable step debug logging set the secret `ACTIONS_STEP_DEBUG` to `true` in th
|
|||||||
MATRIX_CONTEXT: ${{ toJson(matrix) }}
|
MATRIX_CONTEXT: ${{ toJson(matrix) }}
|
||||||
run: echo "$MATRIX_CONTEXT"
|
run: echo "$MATRIX_CONTEXT"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Show an annotation message for a created pull request
|
||||||
|
|
||||||
|
Showing an annotation message for a created or updated pull request allows you to confirm the pull request easily, such as by visiting the link. This can be achieved by adding a step that uses the [`notice` workflow command](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/workflow-commands-for-github-actions?tool=bash#setting-a-notice-message).
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```yml
|
||||||
|
- name: Create Pull Request
|
||||||
|
id: cpr
|
||||||
|
uses: peter-evans/create-pull-request@v7
|
||||||
|
|
||||||
|
- name: Show message for created Pull Request
|
||||||
|
if: ${{ steps.cpr.outputs.pull-request-url && steps.cpr.outputs.pull-request-operation != 'none' }}
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
PR_URL: ${{ steps.cpr.outputs.pull-request-url }}
|
||||||
|
PR_OPERATION: ${{ steps.cpr.outputs.pull-request-operation }}
|
||||||
|
run: |
|
||||||
|
echo "::notice::${PR_URL} was ${PR_OPERATION}."
|
||||||
|
```
|
||||||
|
|
||||||
|
In this example, when a pull request is created, you will be able to see the following message on an action run page (e.g., `/actions/runs/12812393039`):
|
||||||
|
|
||||||
|
```
|
||||||
|
https://github.com/peter-evans/create-pull-request/pull/1 was created.
|
||||||
|
```
|
||||||
|
576
package-lock.json
generated
576
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
40
package.json
40
package.json
@ -29,35 +29,35 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/peter-evans/create-pull-request",
|
"homepage": "https://github.com/peter-evans/create-pull-request",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^1.10.1",
|
"@actions/core": "^1.11.1",
|
||||||
"@actions/exec": "^1.1.1",
|
"@actions/exec": "^1.1.1",
|
||||||
"@octokit/core": "^6.1.2",
|
"@octokit/core": "^6.1.4",
|
||||||
"@octokit/plugin-paginate-rest": "^11.3.3",
|
"@octokit/plugin-paginate-rest": "^11.4.3",
|
||||||
"@octokit/plugin-rest-endpoint-methods": "^13.2.4",
|
"@octokit/plugin-rest-endpoint-methods": "^13.3.1",
|
||||||
"@octokit/plugin-throttling": "^9.3.1",
|
"@octokit/plugin-throttling": "^9.4.0",
|
||||||
"p-limit": "^6.1.0",
|
"node-fetch-native": "^1.6.6",
|
||||||
"proxy-from-env": "^1.1.0",
|
"p-limit": "^6.2.0",
|
||||||
"undici": "^6.19.8",
|
|
||||||
"uuid": "^9.0.1"
|
"uuid": "^9.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/jest": "^29.5.12",
|
"@types/jest": "^29.5.14",
|
||||||
"@types/node": "^18.19.46",
|
"@types/node": "^18.19.76",
|
||||||
"@typescript-eslint/eslint-plugin": "^7.17.0",
|
"@typescript-eslint/eslint-plugin": "^7.18.0",
|
||||||
"@typescript-eslint/parser": "^7.17.0",
|
"@typescript-eslint/parser": "^7.18.0",
|
||||||
"@vercel/ncc": "^0.38.1",
|
"@vercel/ncc": "^0.38.3",
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^8.57.1",
|
||||||
"eslint-import-resolver-typescript": "^3.6.3",
|
"eslint-import-resolver-typescript": "^3.8.3",
|
||||||
"eslint-plugin-github": "^4.10.2",
|
"eslint-plugin-github": "^4.10.2",
|
||||||
"eslint-plugin-import": "^2.29.1",
|
"eslint-plugin-import": "^2.31.0",
|
||||||
"eslint-plugin-jest": "^27.9.0",
|
"eslint-plugin-jest": "^27.9.0",
|
||||||
"eslint-plugin-prettier": "^5.2.1",
|
"eslint-plugin-prettier": "^5.2.3",
|
||||||
"jest": "^29.7.0",
|
"jest": "^29.7.0",
|
||||||
"jest-circus": "^29.7.0",
|
"jest-circus": "^29.7.0",
|
||||||
"jest-environment-jsdom": "^29.7.0",
|
"jest-environment-jsdom": "^29.7.0",
|
||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
"prettier": "^3.3.3",
|
"prettier": "^3.5.2",
|
||||||
"ts-jest": "^29.2.5",
|
"ts-jest": "^29.2.6",
|
||||||
"typescript": "^5.5.4"
|
"typescript": "^5.7.3",
|
||||||
|
"undici": "^6.21.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import * as core from '@actions/core'
|
import * as core from '@actions/core'
|
||||||
import {GitCommandManager, Commit} from './git-command-manager'
|
import {GitCommandManager, Commit} from './git-command-manager'
|
||||||
import {v4 as uuidv4} from 'uuid'
|
import {v4 as uuidv4} from 'uuid'
|
||||||
|
import * as utils from './utils'
|
||||||
|
|
||||||
const CHERRYPICK_EMPTY =
|
const CHERRYPICK_EMPTY =
|
||||||
'The previous cherry-pick is now empty, possibly due to conflict resolution.'
|
'The previous cherry-pick is now empty, possibly due to conflict resolution.'
|
||||||
@ -18,7 +19,7 @@ export async function getWorkingBaseAndType(
|
|||||||
): Promise<[string, WorkingBaseType]> {
|
): Promise<[string, WorkingBaseType]> {
|
||||||
const symbolicRefResult = await git.exec(
|
const symbolicRefResult = await git.exec(
|
||||||
['symbolic-ref', 'HEAD', '--short'],
|
['symbolic-ref', 'HEAD', '--short'],
|
||||||
true
|
{allowAllExitCodes: true}
|
||||||
)
|
)
|
||||||
if (symbolicRefResult.exitCode == 0) {
|
if (symbolicRefResult.exitCode == 0) {
|
||||||
// A ref is checked out
|
// A ref is checked out
|
||||||
@ -131,6 +132,10 @@ async function commitsHaveDiff(
|
|||||||
branch2: string,
|
branch2: string,
|
||||||
depth: number
|
depth: number
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
|
// Some action use cases lead to the depth being a very large number and the diff fails.
|
||||||
|
// I've made this check optional for now because it was a fix for an edge case that is
|
||||||
|
// very rare, anyway.
|
||||||
|
try {
|
||||||
const diff1 = (
|
const diff1 = (
|
||||||
await git.exec(['diff', '--stat', `${branch1}..${branch1}~${depth}`])
|
await git.exec(['diff', '--stat', `${branch1}..${branch1}~${depth}`])
|
||||||
).stdout.trim()
|
).stdout.trim()
|
||||||
@ -138,6 +143,11 @@ async function commitsHaveDiff(
|
|||||||
await git.exec(['diff', '--stat', `${branch2}..${branch2}~${depth}`])
|
await git.exec(['diff', '--stat', `${branch2}..${branch2}~${depth}`])
|
||||||
).stdout.trim()
|
).stdout.trim()
|
||||||
return diff1 !== diff2
|
return diff1 !== diff2
|
||||||
|
} catch (error) {
|
||||||
|
core.info('Failed optional check of commits diff; Skipping.')
|
||||||
|
core.debug(utils.getErrorMessage(error))
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function splitLines(multilineString: string): string[] {
|
function splitLines(multilineString: string): string[] {
|
||||||
@ -190,7 +200,7 @@ export async function createOrUpdateBranch(
|
|||||||
} else {
|
} else {
|
||||||
aopts.push('-A')
|
aopts.push('-A')
|
||||||
}
|
}
|
||||||
await git.exec(aopts, true)
|
await git.exec(aopts, {allowAllExitCodes: true})
|
||||||
const popts = ['-m', commitMessage]
|
const popts = ['-m', commitMessage]
|
||||||
if (signoff) {
|
if (signoff) {
|
||||||
popts.push('--signoff')
|
popts.push('--signoff')
|
||||||
|
@ -211,6 +211,7 @@ export async function createPullRequest(inputs: Inputs): Promise<void> {
|
|||||||
const stashed = await git.stashPush(['--include-untracked'])
|
const stashed = await git.stashPush(['--include-untracked'])
|
||||||
await git.checkout(inputs.branch)
|
await git.checkout(inputs.branch)
|
||||||
const pushSignedCommitsResult = await ghBranch.pushSignedCommits(
|
const pushSignedCommitsResult = await ghBranch.pushSignedCommits(
|
||||||
|
git,
|
||||||
result.branchCommits,
|
result.branchCommits,
|
||||||
result.baseCommit,
|
result.baseCommit,
|
||||||
repoPath,
|
repoPath,
|
||||||
|
@ -2,6 +2,7 @@ import * as exec from '@actions/exec'
|
|||||||
import * as io from '@actions/io'
|
import * as io from '@actions/io'
|
||||||
import * as utils from './utils'
|
import * as utils from './utils'
|
||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
|
import stream, {Writable} from 'stream'
|
||||||
|
|
||||||
const tagsRefSpec = '+refs/tags/*:refs/tags/*'
|
const tagsRefSpec = '+refs/tags/*:refs/tags/*'
|
||||||
|
|
||||||
@ -14,12 +15,19 @@ export type Commit = {
|
|||||||
body: string
|
body: string
|
||||||
changes: {
|
changes: {
|
||||||
mode: string
|
mode: string
|
||||||
|
dstSha: string
|
||||||
status: 'A' | 'M' | 'D'
|
status: 'A' | 'M' | 'D'
|
||||||
path: string
|
path: string
|
||||||
}[]
|
}[]
|
||||||
unparsedChanges: string[]
|
unparsedChanges: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type ExecOpts = {
|
||||||
|
allowAllExitCodes?: boolean
|
||||||
|
encoding?: 'utf8' | 'base64'
|
||||||
|
suppressGitCmdOutput?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
export class GitCommandManager {
|
export class GitCommandManager {
|
||||||
private gitPath: string
|
private gitPath: string
|
||||||
private workingDirectory: string
|
private workingDirectory: string
|
||||||
@ -65,7 +73,7 @@ export class GitCommandManager {
|
|||||||
args.push(...options)
|
args.push(...options)
|
||||||
}
|
}
|
||||||
|
|
||||||
return await this.exec(args, allowAllExitCodes)
|
return await this.exec(args, {allowAllExitCodes: allowAllExitCodes})
|
||||||
}
|
}
|
||||||
|
|
||||||
async commit(
|
async commit(
|
||||||
@ -81,7 +89,7 @@ export class GitCommandManager {
|
|||||||
args.push(...options)
|
args.push(...options)
|
||||||
}
|
}
|
||||||
|
|
||||||
return await this.exec(args, allowAllExitCodes)
|
return await this.exec(args, {allowAllExitCodes: allowAllExitCodes})
|
||||||
}
|
}
|
||||||
|
|
||||||
async config(
|
async config(
|
||||||
@ -112,7 +120,7 @@ export class GitCommandManager {
|
|||||||
configKey,
|
configKey,
|
||||||
configValue
|
configValue
|
||||||
],
|
],
|
||||||
true
|
{allowAllExitCodes: true}
|
||||||
)
|
)
|
||||||
return output.exitCode === 0
|
return output.exitCode === 0
|
||||||
}
|
}
|
||||||
@ -155,13 +163,20 @@ export class GitCommandManager {
|
|||||||
|
|
||||||
async getCommit(ref: string): Promise<Commit> {
|
async getCommit(ref: string): Promise<Commit> {
|
||||||
const endOfBody = '###EOB###'
|
const endOfBody = '###EOB###'
|
||||||
const output = await this.exec([
|
const output = await this.exec(
|
||||||
|
[
|
||||||
|
'-c',
|
||||||
|
'core.quotePath=false',
|
||||||
'show',
|
'show',
|
||||||
'--raw',
|
'--raw',
|
||||||
'--cc',
|
'--cc',
|
||||||
|
'--no-renames',
|
||||||
|
'--no-abbrev',
|
||||||
`--format=%H%n%T%n%P%n%G?%n%s%n%b%n${endOfBody}`,
|
`--format=%H%n%T%n%P%n%G?%n%s%n%b%n${endOfBody}`,
|
||||||
ref
|
ref
|
||||||
])
|
],
|
||||||
|
{suppressGitCmdOutput: true}
|
||||||
|
)
|
||||||
const lines = output.stdout.split('\n')
|
const lines = output.stdout.split('\n')
|
||||||
const endOfBodyIndex = lines.lastIndexOf(endOfBody)
|
const endOfBodyIndex = lines.lastIndexOf(endOfBody)
|
||||||
const detailLines = lines.slice(0, endOfBodyIndex)
|
const detailLines = lines.slice(0, endOfBodyIndex)
|
||||||
@ -176,13 +191,14 @@ export class GitCommandManager {
|
|||||||
body: detailLines.slice(5, endOfBodyIndex).join('\n'),
|
body: detailLines.slice(5, endOfBodyIndex).join('\n'),
|
||||||
changes: lines.slice(endOfBodyIndex + 2, -1).map(line => {
|
changes: lines.slice(endOfBodyIndex + 2, -1).map(line => {
|
||||||
const change = line.match(
|
const change = line.match(
|
||||||
/^:(\d{6}) (\d{6}) \w{7} \w{7} ([AMD])\s+(.*)$/
|
/^:(\d{6}) (\d{6}) \w{40} (\w{40}) ([AMD])\s+(.*)$/
|
||||||
)
|
)
|
||||||
if (change) {
|
if (change) {
|
||||||
return {
|
return {
|
||||||
mode: change[3] === 'D' ? change[1] : change[2],
|
mode: change[4] === 'D' ? change[1] : change[2],
|
||||||
status: change[3],
|
dstSha: change[3],
|
||||||
path: change[4]
|
status: change[4],
|
||||||
|
path: change[5]
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unparsedChanges.push(line)
|
unparsedChanges.push(line)
|
||||||
@ -216,7 +232,7 @@ export class GitCommandManager {
|
|||||||
if (options) {
|
if (options) {
|
||||||
args.push(...options)
|
args.push(...options)
|
||||||
}
|
}
|
||||||
const output = await this.exec(args, true)
|
const output = await this.exec(args, {allowAllExitCodes: true})
|
||||||
return output.exitCode === 1
|
return output.exitCode === 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,6 +288,15 @@ export class GitCommandManager {
|
|||||||
return output.stdout.trim()
|
return output.stdout.trim()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async showFileAtRefBase64(ref: string, path: string): Promise<string> {
|
||||||
|
const args = ['show', `${ref}:${path}`]
|
||||||
|
const output = await this.exec(args, {
|
||||||
|
encoding: 'base64',
|
||||||
|
suppressGitCmdOutput: true
|
||||||
|
})
|
||||||
|
return output.stdout.trim()
|
||||||
|
}
|
||||||
|
|
||||||
async stashPush(options?: string[]): Promise<boolean> {
|
async stashPush(options?: string[]): Promise<boolean> {
|
||||||
const args = ['stash', 'push']
|
const args = ['stash', 'push']
|
||||||
if (options) {
|
if (options) {
|
||||||
@ -320,7 +345,7 @@ export class GitCommandManager {
|
|||||||
configKey,
|
configKey,
|
||||||
configValue
|
configValue
|
||||||
],
|
],
|
||||||
true
|
{allowAllExitCodes: true}
|
||||||
)
|
)
|
||||||
return output.exitCode === 0
|
return output.exitCode === 0
|
||||||
}
|
}
|
||||||
@ -328,7 +353,7 @@ export class GitCommandManager {
|
|||||||
async tryGetRemoteUrl(): Promise<string> {
|
async tryGetRemoteUrl(): Promise<string> {
|
||||||
const output = await this.exec(
|
const output = await this.exec(
|
||||||
['config', '--local', '--get', 'remote.origin.url'],
|
['config', '--local', '--get', 'remote.origin.url'],
|
||||||
true
|
{allowAllExitCodes: true}
|
||||||
)
|
)
|
||||||
|
|
||||||
if (output.exitCode !== 0) {
|
if (output.exitCode !== 0) {
|
||||||
@ -343,16 +368,30 @@ export class GitCommandManager {
|
|||||||
return stdout
|
return stdout
|
||||||
}
|
}
|
||||||
|
|
||||||
async exec(args: string[], allowAllExitCodes = false): Promise<GitOutput> {
|
async exec(
|
||||||
|
args: string[],
|
||||||
|
{
|
||||||
|
encoding = 'utf8',
|
||||||
|
allowAllExitCodes = false,
|
||||||
|
suppressGitCmdOutput = false
|
||||||
|
}: ExecOpts = {}
|
||||||
|
): Promise<GitOutput> {
|
||||||
const result = new GitOutput()
|
const result = new GitOutput()
|
||||||
|
|
||||||
|
if (process.env['CPR_SHOW_GIT_CMD_OUTPUT']) {
|
||||||
|
// debug mode overrides the suppressGitCmdOutput option
|
||||||
|
suppressGitCmdOutput = false
|
||||||
|
}
|
||||||
|
|
||||||
const env = {}
|
const env = {}
|
||||||
for (const key of Object.keys(process.env)) {
|
for (const key of Object.keys(process.env)) {
|
||||||
env[key] = process.env[key]
|
env[key] = process.env[key]
|
||||||
}
|
}
|
||||||
|
|
||||||
const stdout: string[] = []
|
const stdout: Buffer[] = []
|
||||||
const stderr: string[] = []
|
let stdoutLength = 0
|
||||||
|
const stderr: Buffer[] = []
|
||||||
|
let stderrLength = 0
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
cwd: this.workingDirectory,
|
cwd: this.workingDirectory,
|
||||||
@ -360,17 +399,21 @@ export class GitCommandManager {
|
|||||||
ignoreReturnCode: allowAllExitCodes,
|
ignoreReturnCode: allowAllExitCodes,
|
||||||
listeners: {
|
listeners: {
|
||||||
stdout: (data: Buffer) => {
|
stdout: (data: Buffer) => {
|
||||||
stdout.push(data.toString())
|
stdout.push(data)
|
||||||
|
stdoutLength += data.length
|
||||||
},
|
},
|
||||||
stderr: (data: Buffer) => {
|
stderr: (data: Buffer) => {
|
||||||
stderr.push(data.toString())
|
stderr.push(data)
|
||||||
}
|
stderrLength += data.length
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
outStream: outStreamHandler(process.stdout, suppressGitCmdOutput),
|
||||||
|
errStream: outStreamHandler(process.stderr, suppressGitCmdOutput)
|
||||||
}
|
}
|
||||||
|
|
||||||
result.exitCode = await exec.exec(`"${this.gitPath}"`, args, options)
|
result.exitCode = await exec.exec(`"${this.gitPath}"`, args, options)
|
||||||
result.stdout = stdout.join('')
|
result.stdout = Buffer.concat(stdout, stdoutLength).toString(encoding)
|
||||||
result.stderr = stderr.join('')
|
result.stderr = Buffer.concat(stderr, stderrLength).toString(encoding)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -380,3 +423,24 @@ class GitOutput {
|
|||||||
stderr = ''
|
stderr = ''
|
||||||
exitCode = 0
|
exitCode = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const outStreamHandler = (
|
||||||
|
outStream: Writable,
|
||||||
|
suppressGitCmdOutput: boolean
|
||||||
|
): Writable => {
|
||||||
|
return new stream.Writable({
|
||||||
|
write(chunk, _, next) {
|
||||||
|
if (suppressGitCmdOutput) {
|
||||||
|
const lines = chunk.toString().trimEnd().split('\n')
|
||||||
|
for (const line of lines) {
|
||||||
|
if (line.startsWith('[command]')) {
|
||||||
|
outStream.write(`${line}\n`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
outStream.write(chunk)
|
||||||
|
}
|
||||||
|
next()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import * as core from '@actions/core'
|
import * as core from '@actions/core'
|
||||||
import {Inputs} from './create-pull-request'
|
import {Inputs} from './create-pull-request'
|
||||||
import {Commit} from './git-command-manager'
|
import {Commit, GitCommandManager} from './git-command-manager'
|
||||||
import {Octokit, OctokitOptions, throttleOptions} from './octokit-client'
|
import {Octokit, OctokitOptions, throttleOptions} from './octokit-client'
|
||||||
import pLimit from 'p-limit'
|
import pLimit from 'p-limit'
|
||||||
import * as utils from './utils'
|
import * as utils from './utils'
|
||||||
@ -35,7 +35,7 @@ type TreeObject = {
|
|||||||
path: string
|
path: string
|
||||||
mode: '100644' | '100755' | '040000' | '160000' | '120000'
|
mode: '100644' | '100755' | '040000' | '160000' | '120000'
|
||||||
sha: string | null
|
sha: string | null
|
||||||
type: 'blob'
|
type: 'blob' | 'commit'
|
||||||
}
|
}
|
||||||
|
|
||||||
export class GitHubHelper {
|
export class GitHubHelper {
|
||||||
@ -220,6 +220,7 @@ export class GitHubHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async pushSignedCommits(
|
async pushSignedCommits(
|
||||||
|
git: GitCommandManager,
|
||||||
branchCommits: Commit[],
|
branchCommits: Commit[],
|
||||||
baseCommit: Commit,
|
baseCommit: Commit,
|
||||||
repoPath: string,
|
repoPath: string,
|
||||||
@ -233,6 +234,7 @@ export class GitHubHelper {
|
|||||||
}
|
}
|
||||||
for (const commit of branchCommits) {
|
for (const commit of branchCommits) {
|
||||||
headCommit = await this.createCommit(
|
headCommit = await this.createCommit(
|
||||||
|
git,
|
||||||
commit,
|
commit,
|
||||||
headCommit,
|
headCommit,
|
||||||
repoPath,
|
repoPath,
|
||||||
@ -244,6 +246,7 @@ export class GitHubHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async createCommit(
|
private async createCommit(
|
||||||
|
git: GitCommandManager,
|
||||||
commit: Commit,
|
commit: Commit,
|
||||||
parentCommit: CommitResponse,
|
parentCommit: CommitResponse,
|
||||||
repoPath: string,
|
repoPath: string,
|
||||||
@ -255,14 +258,24 @@ export class GitHubHelper {
|
|||||||
if (commit.changes.length > 0) {
|
if (commit.changes.length > 0) {
|
||||||
core.info(`Creating tree objects for local commit ${commit.sha}`)
|
core.info(`Creating tree objects for local commit ${commit.sha}`)
|
||||||
const treeObjects = await Promise.all(
|
const treeObjects = await Promise.all(
|
||||||
commit.changes.map(async ({path, mode, status}) => {
|
commit.changes.map(async ({path, mode, status, dstSha}) => {
|
||||||
|
if (mode === '160000') {
|
||||||
|
// submodule
|
||||||
|
core.info(`Creating tree object for submodule commit at '${path}'`)
|
||||||
|
return <TreeObject>{
|
||||||
|
path,
|
||||||
|
mode,
|
||||||
|
sha: dstSha,
|
||||||
|
type: 'commit'
|
||||||
|
}
|
||||||
|
} else {
|
||||||
let sha: string | null = null
|
let sha: string | null = null
|
||||||
if (status === 'A' || status === 'M') {
|
if (status === 'A' || status === 'M') {
|
||||||
try {
|
try {
|
||||||
const {data: blob} = await blobCreationLimit(() =>
|
const {data: blob} = await blobCreationLimit(async () =>
|
||||||
this.octokit.rest.git.createBlob({
|
this.octokit.rest.git.createBlob({
|
||||||
...repository,
|
...repository,
|
||||||
content: utils.readFileBase64([repoPath, path]),
|
content: await git.showFileAtRefBase64(commit.sha, path),
|
||||||
encoding: 'base64'
|
encoding: 'base64'
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
@ -274,13 +287,16 @@ export class GitHubHelper {
|
|||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
core.info(`Created blob for file '${path}'`)
|
core.info(
|
||||||
|
`Creating tree object for blob at '${path}' with status '${status}'`
|
||||||
|
)
|
||||||
return <TreeObject>{
|
return <TreeObject>{
|
||||||
path,
|
path,
|
||||||
mode,
|
mode,
|
||||||
sha,
|
sha,
|
||||||
type: 'blob'
|
type: 'blob'
|
||||||
}
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -3,8 +3,7 @@ import {Octokit as OctokitCore} from '@octokit/core'
|
|||||||
import {paginateRest} from '@octokit/plugin-paginate-rest'
|
import {paginateRest} from '@octokit/plugin-paginate-rest'
|
||||||
import {restEndpointMethods} from '@octokit/plugin-rest-endpoint-methods'
|
import {restEndpointMethods} from '@octokit/plugin-rest-endpoint-methods'
|
||||||
import {throttling} from '@octokit/plugin-throttling'
|
import {throttling} from '@octokit/plugin-throttling'
|
||||||
import {getProxyForUrl} from 'proxy-from-env'
|
import {fetch} from 'node-fetch-native/proxy'
|
||||||
import {ProxyAgent, fetch as undiciFetch} from 'undici'
|
|
||||||
export {RestEndpointMethodTypes} from '@octokit/plugin-rest-endpoint-methods'
|
export {RestEndpointMethodTypes} from '@octokit/plugin-rest-endpoint-methods'
|
||||||
// eslint-disable-next-line import/no-unresolved
|
// eslint-disable-next-line import/no-unresolved
|
||||||
export {OctokitOptions} from '@octokit/core/dist-types/types'
|
export {OctokitOptions} from '@octokit/core/dist-types/types'
|
||||||
@ -33,23 +32,9 @@ export const throttleOptions = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const proxyFetch =
|
|
||||||
(proxyUrl: string): typeof undiciFetch =>
|
|
||||||
(url, opts) => {
|
|
||||||
return undiciFetch(url, {
|
|
||||||
...opts,
|
|
||||||
dispatcher: new ProxyAgent({
|
|
||||||
uri: proxyUrl
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Octokit plugin to support the standard environment variables http_proxy, https_proxy and no_proxy
|
// Octokit plugin to support the standard environment variables http_proxy, https_proxy and no_proxy
|
||||||
function autoProxyAgent(octokit: OctokitCore) {
|
function autoProxyAgent(octokit: OctokitCore) {
|
||||||
octokit.hook.before('request', options => {
|
octokit.hook.before('request', options => {
|
||||||
const proxy = getProxyForUrl(options.baseUrl)
|
options.request.fetch = fetch
|
||||||
if (proxy) {
|
|
||||||
options.request.fetch = proxyFetch(proxy)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -126,10 +126,6 @@ export function readFile(path: string): string {
|
|||||||
return fs.readFileSync(path, 'utf-8')
|
return fs.readFileSync(path, 'utf-8')
|
||||||
}
|
}
|
||||||
|
|
||||||
export function readFileBase64(pathParts: string[]): string {
|
|
||||||
return fs.readFileSync(path.resolve(...pathParts)).toString('base64')
|
|
||||||
}
|
|
||||||
|
|
||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
function hasErrorCode(error: any): error is {code: string} {
|
function hasErrorCode(error: any): error is {code: string} {
|
||||||
return typeof (error && error.code) === 'string'
|
return typeof (error && error.code) === 'string'
|
||||||
|
Reference in New Issue
Block a user