From 110f9d8fdb02cfa360ab6c76932dc54884dac25d Mon Sep 17 00:00:00 2001 From: Peter Evans <18365890+peter-evans@users.noreply.github.com> Date: Tue, 4 Apr 2023 15:16:56 +0900 Subject: [PATCH] feat: body-path --- README.md | 1 + action.yml | 2 ++ dist/index.js | 14 +++++++++++++- docs/examples.md | 20 -------------------- docs/updating.md | 1 + src/create-pull-request.ts | 8 ++++++++ src/main.ts | 1 + src/utils.ts | 4 ++++ 8 files changed, 30 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index f6c9ed7..507b4a3 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,7 @@ All inputs are **optional**. If not set, sensible defaults will be used. | `push-to-fork` | A fork of the checked-out parent repository to which the pull request branch will be pushed. e.g. `owner/repo-fork`. The pull request will be created to merge the fork's branch into the parent's base. See [push pull request branches to a fork](docs/concepts-guidelines.md#push-pull-request-branches-to-a-fork) for details. | | | `title` | The title of the pull request. | `Changes by create-pull-request action` | | `body` | The body of the pull request. | `Automated changes by [create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub action` | +| `body-path` | The path to a file containing the pull request body. Takes precedence over `body`. | | | `labels` | A comma or newline-separated list of labels. | | | `assignees` | A comma or newline-separated list of assignees (GitHub usernames). | | | `reviewers` | A comma or newline-separated list of reviewers (GitHub usernames) to request a review from. | | diff --git a/action.yml b/action.yml index 4cb37f6..d264e38 100644 --- a/action.yml +++ b/action.yml @@ -54,6 +54,8 @@ inputs: body: description: 'The body of the pull request.' default: 'Automated changes by [create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub action' + body-path: + description: 'The path to a file containing the pull request body. Takes precedence over `body`.' labels: description: 'A comma or newline separated list of labels.' assignees: diff --git a/dist/index.js b/dist/index.js index b3fdacb..c9735a6 100644 --- a/dist/index.js +++ b/dist/index.js @@ -327,6 +327,13 @@ function createPullRequest(inputs) { if (!inputs.token) { throw new Error(`Input 'token' not supplied. Unable to continue.`); } + if (inputs.bodyPath) { + if (!utils.fileExistsSync(inputs.bodyPath)) { + throw new Error(`File '${inputs.bodyPath}' does not exist.`); + } + // Update the body input with the contents of the file + inputs.body = utils.readFile(inputs.bodyPath); + } // Get the repository path const repoPath = utils.getRepoPath(inputs.path); // Create a git command manager @@ -1207,6 +1214,7 @@ function run() { pushToFork: core.getInput('push-to-fork'), title: core.getInput('title'), body: core.getInput('body'), + bodyPath: core.getInput('body-path'), labels: utils.getInputAsArray('labels'), assignees: utils.getInputAsArray('assignees'), reviewers: utils.getInputAsArray('reviewers'), @@ -1282,7 +1290,7 @@ var __importStar = (this && this.__importStar) || function (mod) { return result; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.getErrorMessage = exports.fileExistsSync = exports.parseDisplayNameEmail = exports.randomString = exports.secondsSinceEpoch = exports.getRemoteUrl = exports.getRemoteDetail = exports.getRepoPath = exports.stripOrgPrefixFromTeams = exports.getStringAsArray = exports.getInputAsArray = void 0; +exports.getErrorMessage = exports.readFile = exports.fileExistsSync = exports.parseDisplayNameEmail = exports.randomString = exports.secondsSinceEpoch = exports.getRemoteUrl = exports.getRemoteDetail = exports.getRepoPath = exports.stripOrgPrefixFromTeams = exports.getStringAsArray = exports.getInputAsArray = void 0; const core = __importStar(__nccwpck_require__(2186)); const fs = __importStar(__nccwpck_require__(7147)); const path = __importStar(__nccwpck_require__(1017)); @@ -1407,6 +1415,10 @@ function fileExistsSync(path) { return false; } exports.fileExistsSync = fileExistsSync; +function readFile(path) { + return fs.readFileSync(path, 'utf-8'); +} +exports.readFile = readFile; /* eslint-disable @typescript-eslint/no-explicit-any */ function hasErrorCode(error) { return typeof (error && error.code) === 'string'; diff --git a/docs/examples.md b/docs/examples.md index f291525..0737c2b 100644 --- a/docs/examples.md +++ b/docs/examples.md @@ -21,7 +21,6 @@ - [Filtering push events](#filtering-push-events) - [Bypassing git hooks](#bypassing-git-hooks) - [Dynamic configuration using variables](#dynamic-configuration-using-variables) - - [Setting the pull request body from a file](#setting-the-pull-request-body-from-a-file) - [Using a markdown template](#using-a-markdown-template) - [Debugging GitHub Actions](#debugging-github-actions) @@ -560,25 +559,6 @@ Note that the step where output variables are defined must have an id. body: ${{ steps.vars.outputs.pr_body }} ``` -### Setting the pull request body from a file - -This example shows how file content can be read into a variable and passed to the action. - -```yml - - id: get-pr-body - run: | - body=$(cat pr-body.txt) - delimiter="$(openssl rand -hex 8)" - echo "body<<$delimiter" >> $GITHUB_OUTPUT - echo "$body" >> $GITHUB_OUTPUT - echo "$delimiter" >> $GITHUB_OUTPUT - - - name: Create Pull Request - uses: peter-evans/create-pull-request@v4 - with: - body: ${{ steps.get-pr-body.outputs.body }} -``` - ### Using a markdown template In this example, a markdown template file is added to the repository at `.github/pull-request-template.md` with the following content. diff --git a/docs/updating.md b/docs/updating.md index 820321a..10c0741 100644 --- a/docs/updating.md +++ b/docs/updating.md @@ -7,6 +7,7 @@ ### What's new +- Adds input `body-path`, the path to a file containing the pull request body. - At the end of the action run the local repository is now checked out on the branch or commit that it was when the action started. - Any uncommitted tracked or untracked changes are now stashed and restored at the end of the action run. Currently, this can only occur when using the `add-paths` input, which allows for changes to not be committed. Previously, any uncommitted changes would be destroyed. - The proxy implementation has been revised but is not expected to have any change in behaviour. It continues to support the standard environment variables `http_proxy`, `https_proxy` and `no_proxy`. diff --git a/src/create-pull-request.ts b/src/create-pull-request.ts index 6613ea7..309bb67 100644 --- a/src/create-pull-request.ts +++ b/src/create-pull-request.ts @@ -24,6 +24,7 @@ export interface Inputs { pushToFork: string title: string body: string + bodyPath: string labels: string[] assignees: string[] reviewers: string[] @@ -38,6 +39,13 @@ export async function createPullRequest(inputs: Inputs): Promise { if (!inputs.token) { throw new Error(`Input 'token' not supplied. Unable to continue.`) } + if (inputs.bodyPath) { + if (!utils.fileExistsSync(inputs.bodyPath)) { + throw new Error(`File '${inputs.bodyPath}' does not exist.`) + } + // Update the body input with the contents of the file + inputs.body = utils.readFile(inputs.bodyPath) + } // Get the repository path const repoPath = utils.getRepoPath(inputs.path) diff --git a/src/main.ts b/src/main.ts index 6fb350a..711d0c3 100644 --- a/src/main.ts +++ b/src/main.ts @@ -20,6 +20,7 @@ async function run(): Promise { pushToFork: core.getInput('push-to-fork'), title: core.getInput('title'), body: core.getInput('body'), + bodyPath: core.getInput('body-path'), labels: utils.getInputAsArray('labels'), assignees: utils.getInputAsArray('assignees'), reviewers: utils.getInputAsArray('reviewers'), diff --git a/src/utils.ts b/src/utils.ts index f5bed07..9188bee 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -169,6 +169,10 @@ export function fileExistsSync(path: string): boolean { return false } +export function readFile(path: string): string { + return fs.readFileSync(path, 'utf-8') +} + /* eslint-disable @typescript-eslint/no-explicit-any */ function hasErrorCode(error: any): error is {code: string} { return typeof (error && error.code) === 'string'