Skip to content

Commit

Permalink
feat: v6 (#2717)
Browse files Browse the repository at this point in the history
* feat: update author and committer input defaults

* Update github-actions[bot]

* Update author to new email format

* feat: optional input for git ops token

* feat: allow push-to-fork to push to sibling repos (#2414)

Fixes #2412.

* build: update dist

* feat: update action runtime to node 20 (#2340)

* feat: add truncate warning to pull request body

* perf: unshallow only when necessary

* fix: remove the remote for the fork on completion

* feat: infer github server and api urls

* test: integration test fixes

* build: bump major version

* docs: update to v6

---------

Co-authored-by: Teko <112829523+Teko012@users.noreply.github.com>
Co-authored-by: Benjamin Gilbert <bgilbert@backtick.net>
  • Loading branch information
3 people committed Jan 31, 2024
1 parent bb80902 commit b1ddad2
Show file tree
Hide file tree
Showing 24 changed files with 619 additions and 490 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 16.x
node-version: 20.x
cache: npm
- run: npm ci
- run: npm run build
Expand Down Expand Up @@ -68,8 +68,8 @@ jobs:
uses: ./
with:
commit-message: '[CI] test ${{ matrix.target }}'
committer: GitHub <noreply@github.com>
author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
committer: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
author: ${{ github.actor }} <${{ github.actor_id }}+${{ github.actor }}@users.noreply.github.com>
title: '[CI] test ${{ matrix.target }}'
body: |
- CI test case for target '${{ matrix.target }}'
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/cpr-example-command.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ jobs:
uses: ./
with:
commit-message: Update report
committer: GitHub <noreply@github.com>
author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
committer: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
author: ${{ github.actor }} <${{ github.actor_id }}+${{ github.actor }}@users.noreply.github.com>
signoff: false
title: '[Example] Update report'
body: |
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/update-major-version.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ on:
type: choice
description: The major version tag to update
options:
- v4
- v5
- v6

jobs:
tag:
Expand Down
27 changes: 14 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Create Pull Request action will:

- [Concepts, guidelines and advanced usage](docs/concepts-guidelines.md)
- [Examples](docs/examples.md)
- [Updating to v5](docs/updating.md)
- [Updating to v6](docs/updating.md)
- [Common issues](docs/common-issues.md)

## Usage
Expand All @@ -32,10 +32,10 @@ Create Pull Request action will:
# Make changes to pull request here

- name: Create Pull Request
uses: peter-evans/create-pull-request@v5
uses: peter-evans/create-pull-request@v6
```
You can also pin to a [specific release](https://github.com/peter-evans/create-pull-request/releases) version in the format `@v5.x.x`
You can also pin to a [specific release](https://github.com/peter-evans/create-pull-request/releases) version in the format `@v6.x.x`

### Workflow permissions

Expand All @@ -53,11 +53,12 @@ All inputs are **optional**. If not set, sensible defaults will be used.
| Name | Description | Default |
| --- | --- | --- |
| `token` | `GITHUB_TOKEN` (permissions `contents: write` and `pull-requests: write`) or a `repo` scoped [Personal Access Token (PAT)](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token). | `GITHUB_TOKEN` |
| `git-token` | The [Personal Access Token (PAT)](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token) that the action will use for git operations. | Defaults to the value of `token` |
| `path` | Relative path under `GITHUB_WORKSPACE` to the repository. | `GITHUB_WORKSPACE` |
| `add-paths` | A comma or newline-separated list of file paths to commit. Paths should follow git's [pathspec](https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefpathspecapathspec) syntax. If no paths are specified, all new and modified files are added. See [Add specific paths](#add-specific-paths). | |
| `commit-message` | The message to use when committing changes. See [commit-message](#commit-message). | `[create-pull-request] automated change` |
| `committer` | The committer name and email address in the format `Display Name <email@address.com>`. Defaults to the GitHub Actions bot user. | `GitHub <noreply@github.com>` |
| `author` | The author name and email address in the format `Display Name <email@address.com>`. Defaults to the user who triggered the workflow run. | `${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>` |
| `committer` | The committer name and email address in the format `Display Name <email@address.com>`. Defaults to the GitHub Actions bot user. | `github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>` |
| `author` | The author name and email address in the format `Display Name <email@address.com>`. Defaults to the user who triggered the workflow run. | `${{ github.actor }} <${{ github.actor_id }}+${{ github.actor }}@users.noreply.github.com>` |
| `signoff` | Add [`Signed-off-by`](https://git-scm.com/docs/git-commit#Documentation/git-commit.txt---signoff) line by the committer at the end of the commit log message. | `false` |
| `branch` | The pull request branch name. | `create-pull-request/patch` |
| `delete-branch` | Delete the `branch` if it doesn't have an active pull request associated with it. See [delete-branch](#delete-branch). | `false` |
Expand Down Expand Up @@ -99,7 +100,7 @@ If you want branches to be deleted immediately on merge then you should use GitH
For self-hosted runners behind a corporate proxy set the `https_proxy` environment variable.
```yml
- name: Create Pull Request
uses: peter-evans/create-pull-request@v5
uses: peter-evans/create-pull-request@v6
env:
https_proxy: http://<proxy_address>:<port>
```
Expand All @@ -119,7 +120,7 @@ Note that in order to read the step outputs the action step must have an id.
```yml
- name: Create Pull Request
id: cpr
uses: peter-evans/create-pull-request@v5
uses: peter-evans/create-pull-request@v6
- name: Check outputs
if: ${{ steps.cpr.outputs.pull-request-number }}
run: |
Expand Down Expand Up @@ -182,7 +183,7 @@ File changes that do not match one of the paths will be stashed and restored aft

```yml
- name: Create Pull Request
uses: peter-evans/create-pull-request@v5
uses: peter-evans/create-pull-request@v6
with:
add-paths: |
*.java
Expand All @@ -209,7 +210,7 @@ Note that the repository must be checked out on a branch with a remote, it won't
- name: Uncommitted change
run: date +%s > report.txt
- name: Create Pull Request
uses: peter-evans/create-pull-request@v5
uses: peter-evans/create-pull-request@v6
```

### Create a project card
Expand All @@ -219,7 +220,7 @@ To create a project card for the pull request, pass the `pull-request-number` st
```yml
- name: Create Pull Request
id: cpr
uses: peter-evans/create-pull-request@v5
uses: peter-evans/create-pull-request@v6
- name: Create or Update Project Card
if: ${{ steps.cpr.outputs.pull-request-number }}
Expand Down Expand Up @@ -254,12 +255,12 @@ jobs:
- name: Create Pull Request
id: cpr
uses: peter-evans/create-pull-request@v5
uses: peter-evans/create-pull-request@v6
with:
token: ${{ secrets.PAT }}
commit-message: Update report
committer: GitHub <noreply@github.com>
author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
committer: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
author: ${{ github.actor }} <${{ github.actor_id }}+${{ github.actor }}@users.noreply.github.com>
signoff: false
branch: example-patches
delete-branch: true
Expand Down
4 changes: 2 additions & 2 deletions __test__/create-or-update-branch.int.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {GitCommandManager} from '../lib/git-command-manager'
import * as path from 'path'
import {v4 as uuidv4} from 'uuid'

const REPO_PATH = '/git/local/test-base'
const REPO_PATH = '/git/local/repos/test-base'
const REMOTE_NAME = 'origin'

const TRACKED_FILE = 'a/tracked-file.txt'
Expand All @@ -22,7 +22,7 @@ const INIT_COMMIT_MESSAGE = 'Add file to be a tracked file for tests'
const BRANCH = 'tests/create-pull-request/patch'
const BASE = DEFAULT_BRANCH

const FORK_REMOTE_URL = 'git://127.0.0.1/test-fork.git'
const FORK_REMOTE_URL = 'git://127.0.0.1/repos/test-fork.git'
const FORK_REMOTE_NAME = 'fork'

const ADD_PATHS_DEFAULT = []
Expand Down
14 changes: 7 additions & 7 deletions __test__/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@ set -euo pipefail
WORKINGDIR=$PWD

# Create and serve a remote repo
mkdir -p /git/remote
mkdir -p /git/remote/repos
git config --global init.defaultBranch main
git init --bare /git/remote/test-base.git
git init --bare /git/remote/repos/test-base.git
git daemon --verbose --enable=receive-pack --base-path=/git/remote --export-all /git/remote &>/dev/null &

# Give the daemon time to start
sleep 2

# Create a local clone and make an initial commit
mkdir -p /git/local
git clone git://127.0.0.1/test-base.git /git/local/test-base
cd /git/local/test-base
mkdir -p /git/local/repos
git clone git://127.0.0.1/repos/test-base.git /git/local/repos/test-base
cd /git/local/repos/test-base
git config --global user.email "you@example.com"
git config --global user.name "Your Name"
echo "#test-base" > README.md
Expand All @@ -30,8 +30,8 @@ git config -l

# Clone a server-side fork of the base repo
cd $WORKINGDIR
git clone --mirror git://127.0.0.1/test-base.git /git/remote/test-fork.git
cd /git/remote/test-fork.git
git clone --mirror git://127.0.0.1/repos/test-base.git /git/remote/repos/test-fork.git
cd /git/remote/repos/test-fork.git
git log -1 --pretty=oneline

# Restore the working directory
Expand Down
Original file line number Diff line number Diff line change
@@ -1,70 +1,86 @@
import {GitCommandManager} from '../lib/git-command-manager'
import {GitAuthHelper} from '../lib/git-auth-helper'
import {GitConfigHelper} from '../lib/git-config-helper'

const REPO_PATH = '/git/local/test-base'
const REPO_PATH = '/git/local/repos/test-base'

const extraheaderConfigKey = 'http.https://github.com/.extraheader'
const extraheaderConfigKey = 'http.https://127.0.0.1/.extraheader'

describe('git-auth-helper tests', () => {
describe('git-config-helper integration tests', () => {
let git: GitCommandManager
let gitAuthHelper: GitAuthHelper
let gitConfigHelper: GitConfigHelper

beforeAll(async () => {
git = await GitCommandManager.create(REPO_PATH)
gitAuthHelper = new GitAuthHelper(git)
})

it('tests save and restore with no persisted auth', async () => {
await gitAuthHelper.savePersistedAuth()
await gitAuthHelper.restorePersistedAuth()
const gitConfigHelper = await GitConfigHelper.create(git)
await gitConfigHelper.close()
})

it('tests configure and removal of auth', async () => {
await gitAuthHelper.configureToken('github-token')
const gitConfigHelper = await GitConfigHelper.create(git)
await gitConfigHelper.configureToken('github-token')
expect(await git.configExists(extraheaderConfigKey)).toBeTruthy()
expect(await git.getConfigValue(extraheaderConfigKey)).toEqual(
'AUTHORIZATION: basic eC1hY2Nlc3MtdG9rZW46Z2l0aHViLXRva2Vu'
)

await gitAuthHelper.removeAuth()
await gitConfigHelper.close()
expect(await git.configExists(extraheaderConfigKey)).toBeFalsy()
})

it('tests save and restore of persisted auth', async () => {
const extraheaderConfigValue = 'AUTHORIZATION: basic ***persisted-auth***'
await git.config(extraheaderConfigKey, extraheaderConfigValue)

await gitAuthHelper.savePersistedAuth()
const gitConfigHelper = await GitConfigHelper.create(git)

const exists = await git.configExists(extraheaderConfigKey)
expect(exists).toBeFalsy()

await gitAuthHelper.restorePersistedAuth()
await gitConfigHelper.close()

const configValue = await git.getConfigValue(extraheaderConfigKey)
expect(configValue).toEqual(extraheaderConfigValue)

await gitAuthHelper.removeAuth()
const unset = await git.tryConfigUnset(
extraheaderConfigKey,
'^AUTHORIZATION:'
)
expect(unset).toBeTruthy()
})

it('tests adding and removing the safe.directory config', async () => {
it('tests not adding/removing the safe.directory config when it already exists', async () => {
await git.config('safe.directory', '/another-value', true, true)

await gitAuthHelper.removeSafeDirectory()
await gitAuthHelper.addSafeDirectory()
const gitConfigHelper = await GitConfigHelper.create(git)

expect(
await git.configExists('safe.directory', '/another-value', true)
).toBeTruthy()

await gitConfigHelper.close()

const unset = await git.tryConfigUnset(
'safe.directory',
'/another-value',
true
)
expect(unset).toBeTruthy()
})

it('tests adding and removing the safe.directory config', async () => {
const gitConfigHelper = await GitConfigHelper.create(git)

expect(
await git.configExists('safe.directory', REPO_PATH, true)
).toBeTruthy()

await gitAuthHelper.addSafeDirectory()
await gitAuthHelper.removeSafeDirectory()
await gitConfigHelper.close()

expect(
await git.configExists('safe.directory', REPO_PATH, true)
).toBeFalsy()
expect(
await git.configExists('safe.directory', '/another-value', true)
).toBeTruthy()
})
})
93 changes: 93 additions & 0 deletions __test__/git-config-helper.unit.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import {GitConfigHelper} from '../lib/git-config-helper'

describe('git-config-helper unit tests', () => {
test('parseGitRemote successfully parses HTTPS remote URLs', async () => {
const remote1 = GitConfigHelper.parseGitRemote(
'https://github.com/peter-evans/create-pull-request'
)
expect(remote1.hostname).toEqual('github.com')
expect(remote1.protocol).toEqual('HTTPS')
expect(remote1.repository).toEqual('peter-evans/create-pull-request')

const remote2 = GitConfigHelper.parseGitRemote(
'https://xxx:x-oauth-basic@github.com/peter-evans/create-pull-request'
)
expect(remote2.hostname).toEqual('github.com')
expect(remote2.protocol).toEqual('HTTPS')
expect(remote2.repository).toEqual('peter-evans/create-pull-request')

const remote3 = GitConfigHelper.parseGitRemote(
'https://github.com/peter-evans/create-pull-request.git'
)
expect(remote3.hostname).toEqual('github.com')
expect(remote3.protocol).toEqual('HTTPS')
expect(remote3.repository).toEqual('peter-evans/create-pull-request')

const remote4 = GitConfigHelper.parseGitRemote(
'https://github.com/peter-evans/ungit'
)
expect(remote4.hostname).toEqual('github.com')
expect(remote4.protocol).toEqual('HTTPS')
expect(remote4.repository).toEqual('peter-evans/ungit')

const remote5 = GitConfigHelper.parseGitRemote(
'https://github.com/peter-evans/ungit.git'
)
expect(remote5.hostname).toEqual('github.com')
expect(remote5.protocol).toEqual('HTTPS')
expect(remote5.repository).toEqual('peter-evans/ungit')

const remote6 = GitConfigHelper.parseGitRemote(
'https://github.internal.company/peter-evans/create-pull-request'
)
expect(remote6.hostname).toEqual('github.internal.company')
expect(remote6.protocol).toEqual('HTTPS')
expect(remote6.repository).toEqual('peter-evans/create-pull-request')
})

test('parseGitRemote successfully parses SSH remote URLs', async () => {
const remote1 = GitConfigHelper.parseGitRemote(
'git@github.com:peter-evans/create-pull-request.git'
)
expect(remote1.hostname).toEqual('github.com')
expect(remote1.protocol).toEqual('SSH')
expect(remote1.repository).toEqual('peter-evans/create-pull-request')

const remote2 = GitConfigHelper.parseGitRemote(
'git@github.com:peter-evans/ungit.git'
)
expect(remote2.hostname).toEqual('github.com')
expect(remote2.protocol).toEqual('SSH')
expect(remote2.repository).toEqual('peter-evans/ungit')

const remote3 = GitConfigHelper.parseGitRemote(
'git@github.internal.company:peter-evans/create-pull-request.git'
)
expect(remote3.hostname).toEqual('github.internal.company')
expect(remote3.protocol).toEqual('SSH')
expect(remote3.repository).toEqual('peter-evans/create-pull-request')
})

test('parseGitRemote successfully parses GIT remote URLs', async () => {
// Unauthenticated git protocol for integration tests only
const remote1 = GitConfigHelper.parseGitRemote(
'git://127.0.0.1/repos/test-base.git'
)
expect(remote1.hostname).toEqual('127.0.0.1')
expect(remote1.protocol).toEqual('GIT')
expect(remote1.repository).toEqual('repos/test-base')
})

test('parseGitRemote fails to parse a remote URL', async () => {
const remoteUrl = 'https://github.com/peter-evans'
try {
GitConfigHelper.parseGitRemote(remoteUrl)
// Fail the test if an error wasn't thrown
expect(true).toEqual(false)
} catch (e: any) {
expect(e.message).toEqual(
`The format of '${remoteUrl}' is not a valid GitHub repository URL`
)
}
})
})
Loading

0 comments on commit b1ddad2

Please sign in to comment.