Skip to content

Commit

Permalink
Merge pull request #420 from korthout/korthout-elevate-detect-merge-m…
Browse files Browse the repository at this point in the history
…ethod-input

[Breaking] Use merge method to cherry-pick by default
  • Loading branch information
korthout authored May 26, 2024
2 parents 8e95300 + 54c4bc6 commit 5ff61e2
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 39 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/backport.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Create backport pull requests
uses: korthout/backport-action@v2
uses: korthout/backport-action@v3
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,5 @@ jobs:
startsWith(github.event.pull_request.base.ref, 'release')
)
run: |
git tag v2.next-preview --force
git push origin v2.next-preview --force
git tag v3.next-preview --force
git push origin v3.next-preview --force
35 changes: 21 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,12 @@ You can select the branches to backport merged pull requests in two ways:

For each selected branch, the backport action takes the following steps:
1. fetch and checkout a new branch from the target branch
2. cherry-pick the merged pull request's commits
2. cherry-pick commits containing the merged pull request's changes, using the [`cherry_picking`](#cherry_picking) input
3. create a pull request to merge the new branch into the target branch
4. comment on the original pull request about its success

The commits are cherry-picked with the [`-x`](https://git-scm.com/docs/git-cherry-pick#Documentation/git-cherry-pick.txt--x) flag.

## Usage

Add the following workflow configuration to your repository's `.github/workflows` folder.
Expand All @@ -48,7 +50,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Create backport pull requests
uses: korthout/backport-action@v2
uses: korthout/backport-action@v3
```
> **Note**
Expand Down Expand Up @@ -95,7 +97,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Create backport pull requests
uses: korthout/backport-action@v2
uses: korthout/backport-action@v3
```
</p>
Expand All @@ -115,6 +117,22 @@ Placeholders can be used to define variable values.
These are indicated by a dollar sign and curly braces (`${placeholder}`).
Please refer to this action's README for all available [placeholders](#placeholders).

### `cherry_picking`

Default: `auto`

Determines which commits are cherry-picked.

When set to `auto`, the action cherry-picks the commits based on the method used to merge the pull request.
- For "Squash and merge", the action cherry-picks the squashed commit.
- For "Rebase and merge", the action cherry-picks the rebased commits.
- For "Merged as a merge commit", the action cherry-picks the commits from the pull request.

When set to `pull_request_head`, the action cherry-picks the commits from the pull request.
Specifically, those reachable from the pull request's head and not reachable from the pull request's base.

By default, the action cherry-picks the commits based on the method used to merge the pull request.

### `copy_assignees`

Default: `false` (disabled)
Expand Down Expand Up @@ -171,17 +189,6 @@ Behavior is defined by the option selected.

Instructions are provided on the original pull request on how to resolve the conflict and continue the cherry-pick.

#### `detect_merge_method`

Default: `false`

When enabled, the action detects the method used to merge the pull request.
- For "Squash and merge", the action cherry-picks the squashed commit.
- For "Rebase and merge", the action cherry-picks the rebased commits.
- For "Merged as a merge commit", the action cherry-picks the commits from the pull request.

By default, the action always cherry-picks the commits from the pull request.

#### `downstream_repo`

Define if you want to backport to a repository other than where the workflow runs.
Expand Down
24 changes: 14 additions & 10 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,20 @@ inputs:
These are indicated by a dollar sign and curly braces (`${placeholder}`).
Please refer to this action's README for all available placeholders.
default: backport-${pull_number}-to-${target_branch}
cherry_picking:
description:
Determines which commits are cherry-picked.

When set to `auto`, the action cherry-picks the commits based on the method used to merge the pull request.
- For "Squash and merge", the action cherry-picks the squashed commit.
- For "Rebase and merge", the action cherry-picks the rebased commits.
- For "Merged as a merge commit", the action cherry-picks the commits from the pull request.

When set to `pull_request_head`, the action cherry-picks the commits from the pull request.
Specifically, those reachable from the pull request's head and not reachable from the pull request's base.

By default, the action cherry-picks the commits based on the method used to merge the pull request.
default: auto
copy_assignees:
description: >
Controls whether to copy the assignees from the original pull request to the backport pull request.
Expand Down Expand Up @@ -46,15 +60,6 @@ inputs:
- When set to `draft_commit_conflicts` the backport will always create a draft pull request with the first conflict encountered committed.
Instructions are provided on the original pull request on how to resolve the conflict and continue the cherry-pick.
#### `detect_merge_method`
When enabled, the action detects the method used to merge the pull request.
- For "Squash and merge", the action cherry-picks the squashed commit.
- For "Rebase and merge", the action cherry-picks the rebased commits.
- For "Merged as a merge commit", the action cherry-picks the commits from the pull request.
By default, the action always cherry-picks the commits from the pull request.
#### `downstream_repo`
Expand All @@ -70,7 +75,6 @@ inputs:
By default, uses the owner of the repository in which the workflow runs.
default: >
{
"detect_merge_method": false,
"conflict_resolution": "fail"
}
github_token:
Expand Down
22 changes: 18 additions & 4 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,16 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.findTargetBranches = exports.Backport = exports.experimentalDefaults = void 0;
exports.findTargetBranches = exports.Backport = exports.deprecatedExperimental = exports.experimentalDefaults = void 0;
const core = __importStar(__nccwpck_require__(2186));
const dedent_1 = __importDefault(__nccwpck_require__(8333));
const github_1 = __nccwpck_require__(5928);
const git_1 = __nccwpck_require__(3374);
const utils = __importStar(__nccwpck_require__(918));
const deprecatedExperimental = {};
exports.deprecatedExperimental = deprecatedExperimental;
const experimentalDefaults = {
detect_merge_method: false,
detect_merge_method: undefined,
conflict_resolution: `fail`,
downstream_repo: undefined,
downstream_owner: undefined,
Expand Down Expand Up @@ -113,7 +115,7 @@ class Backport {
yield this.git.fetch(`refs/pull/${pull_number}/head`, this.config.pwd, mainpr.commits + 1);
const commitShas = yield this.github.getCommits(mainpr);
let commitShasToCherryPick;
if (this.config.experimental.detect_merge_method) {
if (this.config.commits.cherry_picking === "auto") {
const merge_commit_sha = yield this.github.getMergeCommitSha(mainpr);
// switch case to check if it is a squash, rebase, or merge commit
switch (yield this.github.mergeStrategy(mainpr, merge_commit_sha)) {
Expand Down Expand Up @@ -1071,11 +1073,18 @@ function run() {
const branch_name = core.getInput("branch_name");
const copy_labels_pattern = core.getInput("copy_labels_pattern");
const target_branches = core.getInput("target_branches");
const cherry_picking = core.getInput("cherry_picking");
const merge_commits = core.getInput("merge_commits");
const copy_assignees = core.getInput("copy_assignees");
const copy_milestone = core.getInput("copy_milestone");
const copy_requested_reviewers = core.getInput("copy_requested_reviewers");
const experimental = JSON.parse(core.getInput("experimental"));
if (cherry_picking !== "auto" && cherry_picking !== "pull_request_head") {
const message = `Expected input 'cherry_picking' to be either 'auto' or 'pull_request_head', but was '${cherry_picking}'`;
console.error(message);
core.setFailed(message);
return;
}
if (merge_commits != "fail" && merge_commits != "skip") {
const message = `Expected input 'merge_commits' to be either 'fail' or 'skip', but was '${merge_commits}'`;
console.error(message);
Expand All @@ -1087,6 +1096,11 @@ function run() {
console.warn((0, dedent_1.default) `Encountered unexpected key in input 'experimental'.\
No experimental config options known for key '${key}'.\
Please check the documentation for details about experimental features.`);
}
if (key in backport_1.deprecatedExperimental) {
console.warn((0, dedent_1.default) `Encountered deprecated key in input 'experimental'.\
Key '${key}' is no longer used. You should remove it from your workflow.\
Please check the release notes or the documentation for more details.`);
}
if (key == "conflict_resolution") {
if (experimental[key] !== "fail" &&
Expand All @@ -1106,7 +1120,7 @@ function run() {
pull: { description, title, branch_name },
copy_labels_pattern: copy_labels_pattern === "" ? undefined : new RegExp(copy_labels_pattern),
target_branches: target_branches === "" ? undefined : target_branches,
commits: { merge_commits },
commits: { cherry_picking, merge_commits },
copy_assignees: copy_assignees === "true",
copy_milestone: copy_milestone === "true",
copy_requested_reviewers: copy_requested_reviewers === "true",
Expand Down
2 changes: 1 addition & 1 deletion dist/index.js.map

Large diffs are not rendered by default.

14 changes: 9 additions & 5 deletions src/backport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export type Config = {
copy_labels_pattern?: RegExp;
target_branches?: string;
commits: {
cherry_picking: "auto" | "pull_request_head";
merge_commits: "fail" | "skip";
};
copy_milestone: boolean;
Expand All @@ -36,19 +37,22 @@ export type Config = {
experimental: Experimental;
};

type DeprecatedExperimental = {
detect_merge_method?: boolean;
};
const deprecatedExperimental: DeprecatedExperimental = {};
type Experimental = {
detect_merge_method: boolean;
conflict_resolution: "fail" | "draft_commit_conflicts";
downstream_repo?: string;
downstream_owner?: string;
};
} & DeprecatedExperimental;
const experimentalDefaults: Experimental = {
detect_merge_method: false,
detect_merge_method: undefined,
conflict_resolution: `fail`,
downstream_repo: undefined,
downstream_owner: undefined,
};
export { experimentalDefaults };
export { experimentalDefaults, deprecatedExperimental };

enum Output {
wasSuccessful = "was_successful",
Expand Down Expand Up @@ -135,7 +139,7 @@ export class Backport {

let commitShasToCherryPick;

if (this.config.experimental.detect_merge_method) {
if (this.config.commits.cherry_picking === "auto") {
const merge_commit_sha = await this.github.getMergeCommitSha(mainpr);

// switch case to check if it is a squash, rebase, or merge commit
Expand Down
23 changes: 21 additions & 2 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import * as core from "@actions/core";
import { Backport, Config, experimentalDefaults } from "./backport";
import {
Backport,
Config,
experimentalDefaults,
deprecatedExperimental,
} from "./backport";
import { Github } from "./github";
import { Git } from "./git";
import { execa } from "execa";
Expand All @@ -19,12 +24,20 @@ async function run(): Promise<void> {
const branch_name = core.getInput("branch_name");
const copy_labels_pattern = core.getInput("copy_labels_pattern");
const target_branches = core.getInput("target_branches");
const cherry_picking = core.getInput("cherry_picking");
const merge_commits = core.getInput("merge_commits");
const copy_assignees = core.getInput("copy_assignees");
const copy_milestone = core.getInput("copy_milestone");
const copy_requested_reviewers = core.getInput("copy_requested_reviewers");
const experimental = JSON.parse(core.getInput("experimental"));

if (cherry_picking !== "auto" && cherry_picking !== "pull_request_head") {
const message = `Expected input 'cherry_picking' to be either 'auto' or 'pull_request_head', but was '${cherry_picking}'`;
console.error(message);
core.setFailed(message);
return;
}

if (merge_commits != "fail" && merge_commits != "skip") {
const message = `Expected input 'merge_commits' to be either 'fail' or 'skip', but was '${merge_commits}'`;
console.error(message);
Expand All @@ -39,6 +52,12 @@ async function run(): Promise<void> {
Please check the documentation for details about experimental features.`);
}

if (key in deprecatedExperimental) {
console.warn(dedent`Encountered deprecated key in input 'experimental'.\
Key '${key}' is no longer used. You should remove it from your workflow.\
Please check the release notes or the documentation for more details.`);
}

if (key == "conflict_resolution") {
if (
experimental[key] !== "fail" &&
Expand All @@ -61,7 +80,7 @@ async function run(): Promise<void> {
copy_labels_pattern:
copy_labels_pattern === "" ? undefined : new RegExp(copy_labels_pattern),
target_branches: target_branches === "" ? undefined : target_branches,
commits: { merge_commits },
commits: { cherry_picking, merge_commits },
copy_assignees: copy_assignees === "true",
copy_milestone: copy_milestone === "true",
copy_requested_reviewers: copy_requested_reviewers === "true",
Expand Down

0 comments on commit 5ff61e2

Please sign in to comment.