From f07e8394af92966a0add46eba30900e346edf31d Mon Sep 17 00:00:00 2001 From: Emilien Escalle Date: Thu, 6 Aug 2026 10:59:19 +0200 Subject: [PATCH] feat(create-and-merge-pull-request): support configurable merge methods Signed-off-by: Emilien Escalle --- README.md | 2 +- .../create-and-merge-pull-request/README.md | 16 ++++- .../create-and-merge-pull-request/action.yml | 63 +++++++++++++++---- 3 files changed, 64 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index cb37fc52..9dba2439 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Opinionated GitHub Actions and reusable workflows for foundational continuous-in ### Workflow & repository automation - [Checkout](actions/checkout/README.md) - event-aware drop-in replacement for `actions/checkout` that supports issue comment triggers. -- [Create and merge pull request](actions/create-and-merge-pull-request/README.md) - opens a pull request, rebases, and merges it with the GitHub Actions bot identity. +- [Create and merge pull request](actions/create-and-merge-pull-request/README.md) - opens a pull request and merges it with the configured strategy and GitHub Actions bot identity. - [Create or update comment](actions/create-or-update-comment/README.md) - adds or updates comments on issues and pull requests idempotently. - [Get GitHub Actions bot user](actions/get-github-actions-bot-user/README.md) - retrieves the profile information for the GitHub Actions bot. - [Get issue number](actions/get-issue-number/README.md) - extracts the relevant issue number from the current workflow context. diff --git a/actions/create-and-merge-pull-request/README.md b/actions/create-and-merge-pull-request/README.md index 4dabd506..08c61611 100644 --- a/actions/create-and-merge-pull-request/README.md +++ b/actions/create-and-merge-pull-request/README.md @@ -26,7 +26,7 @@ ## Overview Action to create and merge Pull Request. -Opinionated, set GitHub Actions bot as author, then rebase and merge. +Opinionated, set GitHub Actions bot as author, then merge with the configured strategy. For this action to work you must explicitly allow GitHub Actions to create pull requests. See . @@ -50,7 +50,7 @@ See @@ -75,8 +81,12 @@ See . | | | | **`branch`** | The pull request branch name | **true** | - | | **`title`** | The pull request title | **true** | - | +| | Also used as the merged commit title for `merge` and `squash`. | | | | **`body`** | The pull request body | **true** | - | | **`commit-message`** | The commit message for the pull request | **true** | - | +| | Also used as the merged commit body for `merge` and `squash`. | | | +| **`merge-method`** | Merge strategy for the created pull request. | **false** | `rebase` | +| | Valid values: `merge`, `rebase`, `squash`. | | | diff --git a/actions/create-and-merge-pull-request/action.yml b/actions/create-and-merge-pull-request/action.yml index 22c5322b..a3346033 100644 --- a/actions/create-and-merge-pull-request/action.yml +++ b/actions/create-and-merge-pull-request/action.yml @@ -3,7 +3,7 @@ name: "Create and merge Pull Request" description: | Action to create and merge Pull Request. - Opinionated, set GitHub Actions bot as author, then rebase and merge. + Opinionated, set GitHub Actions bot as author, then merge with the configured strategy. author: hoverkraft branding: icon: git-pull-request @@ -20,14 +20,20 @@ inputs: description: "The pull request branch name" required: true title: - description: "The pull request title" + description: "The pull request title and, for merge/squash merges, the merged commit title" required: true body: description: "The pull request body" required: true commit-message: - description: "The commit message for the pull request" + description: "The commit message for the pull request and, for merge/squash merges, the merged commit body" required: true + merge-method: + description: | + Merge strategy for the created pull request. + Valid values: `merge`, `rebase`, `squash`. + default: rebase + required: false outputs: merged-ref: @@ -82,16 +88,33 @@ runs: env: GH_TOKEN: ${{ inputs.github-token }} PULL_REQUEST_NUMBER: ${{ steps.create-pull-request.outputs.pull-request-number }} + MERGE_METHOD: ${{ inputs.merge-method }} + PULL_REQUEST_TITLE: ${{ inputs.title }} + PULL_REQUEST_COMMIT_MESSAGE: ${{ inputs.commit-message }} with: github-token: ${{ inputs.github-token }} script: | const maxAttempts = 10; const requiredWorkflowsError = 'Required workflow'; const repository = `${context.repo.owner}/${context.repo.repo}`; + const mergeMethod = (process.env.MERGE_METHOD ?? 'rebase').trim(); + const mergeCommitTitle = (process.env.PULL_REQUEST_TITLE ?? '').trim(); + const mergeCommitMessage = process.env.PULL_REQUEST_COMMIT_MESSAGE ?? ''; + const mergeMethodFlags = { + merge: '--merge', + rebase: '--rebase', + squash: '--squash', + }; const getRetryDelayMs = attempt => Math.min(1000 * (2 ** attempt), 10000); const sleep = delayMs => new Promise(resolve => setTimeout(resolve, delayMs)); + if (!(mergeMethod in mergeMethodFlags)) { + throw new Error( + `Invalid merge method: ${mergeMethod}. Expected one of: ${Object.keys(mergeMethodFlags).join(', ')}`, + ); + } + const waitFor = async ({ run, isComplete, @@ -154,20 +177,34 @@ runs: getTimeoutMessage: () => `Pull request #${pullNumber} is not mergeable after ${maxAttempts} attempts`, }); + const getMergeArguments = pullNumber => { + const args = [ + 'pr', + 'merge', + '-R', + repository, + mergeMethodFlags[mergeMethod], + '--admin', + String(pullNumber), + ]; + + if (mergeMethod !== 'rebase' && mergeCommitTitle) { + args.push('--subject', mergeCommitTitle); + } + + if (mergeMethod !== 'rebase' && mergeCommitMessage.trim()) { + args.push('--body', mergeCommitMessage); + } + + return args; + }; + const mergePullRequest = async pullNumber => { - core.debug(`Merging pull request #${pullNumber} for repository ${repository}...`); + core.debug(`Merging pull request #${pullNumber} for repository ${repository} with method ${mergeMethod}...`); const { exitCode, stdout, stderr } = await exec.getExecOutput( 'gh', - [ - 'pr', - 'merge', - '-R', - repository, - '--rebase', - '--admin', - String(pullNumber), - ], + getMergeArguments(pullNumber), { env: process.env, ignoreReturnCode: true,