Skip to content

Commit 5748433

Browse files
michalby24michsi24
andauthored
feat(auto-merge): create auto merge action MAPCO-9003 (#104)
* ci(auto-merge): add action to automatically merge PRs with 'auto-merge' label * ci: update action to include repository input and enhance authentication process * ci(auto-merge): update workflow to use dynamic PR number and improve label check logic * ci(auto-merge): refine installation and authentication steps for gh * ci(auto-merge): wait for required checks to pass before merging PRs * feat(auto-merge): add auto-merge action for labeled PRs with passing checks * ci(auto-merge): update test workflow to use dynamic repository input * docs(auto-merge): add README for auto-merge * ci: refine commit message format and update PR labels handling * ci: add merge_method input to configure merge strategy * fix: correct typo in installation message for gh * trigger CI * ci: add test action with labels for auto-merge workflow * ci: update checkout actions and repository references in auto-merge workflow * fix: update branch references from main to master in auto-merge workflow * ci: update GitHub token secret for auto-merge action * trigger CI * ci: update GitHub token secret from GITHUB_TOKEN to GH_PAT in auto-merge workflow * ci: add dependency on create_pr step for auto-merge action * ci: add dependency on create_pr step for auto-merge action * ci: update GitHub token secret to GH_PAT_TEST in auto-merge workflow * trigger CI * trigger CI * ci: update GitHub token secret from GH_PAT_TEST to GH_PAT in auto-merge workflow * trigger CI --------- Co-authored-by: michsi24 <michalby24@gmail.com>
1 parent a6dd0ef commit 5748433

4 files changed

Lines changed: 225 additions & 0 deletions

File tree

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
name: Test auto-merge action
2+
3+
on:
4+
pull_request:
5+
paths:
6+
- "actions/auto-merge/**"
7+
8+
jobs:
9+
test-action:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- name: Checkout this repo
13+
uses: actions/checkout@v6
14+
15+
- name: Run auto-merge action
16+
uses: ./actions/auto-merge
17+
with:
18+
pr_number: ${{ github.event.pull_request.number }}
19+
github_token: ${{ secrets.GH_PAT }}
20+
repository: ${{ github.repository }}
21+
22+
test-action-with-labels:
23+
runs-on: ubuntu-latest
24+
steps:
25+
- name: Checkout this repo
26+
uses: actions/checkout@v6
27+
28+
- name: Checkout test repo
29+
uses: actions/checkout@v6
30+
with:
31+
repository: MapColonies/test-site
32+
token: ${{ secrets.GH_PAT }}
33+
ref: master
34+
persist-credentials: false
35+
36+
- name: Create empty commit in test repo
37+
run: |
38+
git config user.name "GitHub Actions Bot"
39+
git config user.email "actions@github.com"
40+
git commit --allow-empty -m "chore: empty PR for auto-merge test (${GITHUB_SHA})"
41+
42+
- name: Create Pull Request
43+
id: create_pr
44+
uses: peter-evans/create-pull-request@v6
45+
with:
46+
token: ${{ secrets.GH_PAT }}
47+
repository: MapColonies/test-site
48+
branch: "auto-merge-e2e-${{ github.sha }}"
49+
base: master
50+
title: 'chore: auto-merge e2e test'
51+
body: |
52+
Trigger commit: https://github.com/${{ github.repository }}/commit/${{ github.sha }}
53+
54+
Empty commit PR for auto-merge test.
55+
labels: auto-merge
56+
57+
- name: Run auto-merge action
58+
uses: ./actions/auto-merge
59+
with:
60+
pr_number: ${{ steps.create_pr.outputs.pull-request-number }}
61+
github_token: ${{ secrets.GH_PAT }}
62+
repository: MapColonies/test-site

actions/auto-merge/README.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Auto-merge PR by label
2+
3+
Checks if a pull request has the `auto-merge` label, waits for all checks to pass, and then merges the PR.
4+
5+
---
6+
7+
## ✨ What It Does
8+
9+
- Verifies the PR has the `auto-merge` label
10+
- Waits for all PR checks to complete and pass
11+
- Merges the PR with a squash strategy
12+
- Skips merge if the label is missing or checks fail
13+
14+
---
15+
16+
## 🛠 Inputs
17+
18+
| Name | Description | Required | Default |
19+
|------|-------------|----------|---------|
20+
| `pr_number` | Pull Request number to check and merge | ✅ Yes | |
21+
| `github_token` | GitHub token with permissions to merge PRs | ✅ Yes | |
22+
| `repository` | Target repository in `owner/repo` format (typically `${{ github.repository }}`) | ✅ Yes | |
23+
| `merge_label` | Label that triggers auto-merge (if present on the PR) | ❌ No | `auto-merge` |
24+
| `merge_method` | Merge method to use (merge, squash, rebase). Defaults to `squash`. | ❌ No | `squash` |
25+
26+
27+
## 🚀 Usage
28+
29+
<!-- x-release-please-start-version -->
30+
31+
```yaml
32+
permissions:
33+
contents: write
34+
pull-requests: write
35+
36+
steps:
37+
- name: Auto-merge PR by label
38+
uses: MapColonies/shared-workflows/actions/auto-merge@auto-merge-v0.1.0
39+
with:
40+
pr_number: ${{ github.event.pull_request.number }}
41+
github_token: ${{ secrets.GH_PAT }}
42+
repository: ${{ github.repository }}
43+
```
44+
45+
<!-- x-release-please-end-version -->

actions/auto-merge/action.yaml

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
name: "Auto-merge PR by label"
2+
description: "Checks if a PR has the 'auto-merge' label and merges it using gh if present"
3+
4+
inputs:
5+
pr_number:
6+
description: "Pull Request number to check and merge"
7+
required: true
8+
github_token:
9+
description: "GitHub token with permissions to merge PRs (repo scope)"
10+
required: true
11+
repository:
12+
description: "Target repository (owner/repo). Defaults to the current repository."
13+
required: true
14+
merge_label:
15+
description: "Label that triggers auto-merge"
16+
required: false
17+
default: "auto-merge"
18+
merge_method:
19+
description: "Merge method to use (merge, squash, rebase). Defaults to 'squash'."
20+
required: false
21+
default: "squash"
22+
23+
runs:
24+
using: "composite"
25+
steps:
26+
- name: Install gh (for act)
27+
shell: bash
28+
run: |
29+
if command -v gh >/dev/null; then
30+
echo "gh already instlled"; exit 0;
31+
fi
32+
sudo apt-get update -y
33+
sudo apt-get install -y git curl
34+
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg \
35+
| sudo tee /usr/share/keyrings/githubcli-archive-keyring.gpg >/dev/null
36+
echo "deb [signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" \
37+
| sudo tee /etc/apt/sources.list.d/github-cli.list >/dev/null
38+
sudo apt-get update -y
39+
sudo apt-get install -y gh
40+
41+
- name: Authenticate gh with github_token
42+
shell: bash
43+
env:
44+
GITHUB_TOKEN: ${{ inputs.github_token }}
45+
GH_TOKEN: ${{ inputs.github_token }}
46+
run: |
47+
set -euo pipefail
48+
# If GH_TOKEN/GITHUB_TOKEN is set, gh uses it automatically; avoid forcing login.
49+
if gh auth status >/dev/null 2>&1; then
50+
echo "gh is already authenticated"
51+
else
52+
# Probe API to confirm token works; this avoids storing credentials when env vars are set.
53+
if gh api user >/dev/null 2>&1; then
54+
echo "gh authenticated via environment token"
55+
else
56+
echo "Environment token appears invalid; attempting login via --with-token"
57+
echo -n "$GITHUB_TOKEN" | gh auth login --with-token
58+
gh auth status
59+
fi
60+
fi
61+
62+
- name: Check for '${{ inputs.merge_label }}' label
63+
id: check_label
64+
shell: bash
65+
env:
66+
GH_TOKEN: ${{ inputs.github_token }}
67+
run: |
68+
set -euo pipefail
69+
labels=$(gh pr view "${{ inputs.pr_number }}" --repo "${{ inputs.repository }}" --json labels -q '.labels[].name')
70+
71+
if grep -qx "${{ inputs.merge_label }}" <<< "$labels"; then
72+
echo "has_label=true" >> "$GITHUB_OUTPUT"
73+
else
74+
echo "has_label=false" >> "$GITHUB_OUTPUT"
75+
fi
76+
77+
- name: Wait for PR checks
78+
id: wait_checks
79+
if: steps.check_label.outputs.has_label == 'true'
80+
shell: bash
81+
env:
82+
GH_TOKEN: ${{ inputs.github_token }}
83+
run: |
84+
set -euo pipefail
85+
echo "Waiting for all checks on PR #${{ inputs.pr_number }} to complete"
86+
if gh pr checks "${{ inputs.pr_number }}" \
87+
--repo "${{ inputs.repository }}" \
88+
--watch; then
89+
echo "All checks completed."
90+
echo "passed=true" >> "$GITHUB_OUTPUT"
91+
else
92+
echo "Checks did not complete successfully."
93+
echo "passed=false" >> "$GITHUB_OUTPUT"
94+
exit 1
95+
fi
96+
97+
- name: Merge PR if labeled
98+
if: steps.check_label.outputs.has_label == 'true' && steps.wait_checks.outputs.passed == 'true'
99+
shell: bash
100+
env:
101+
GH_TOKEN: ${{ inputs.github_token }}
102+
run: |
103+
set -euo pipefail
104+
echo "Merging PR #${{ inputs.pr_number }} in '${{ inputs.repository }}' (label '${{ inputs.merge_label }}' found)"
105+
gh pr merge "${{ inputs.pr_number }}" \
106+
--repo "${{ inputs.repository }}" \
107+
--${{ inputs.merge_method }} \
108+
109+
- name: Skip merge (label missing)
110+
if: steps.check_label.outputs.has_label != 'true'
111+
shell: bash
112+
run: |
113+
echo "Skipping merge: PR #${{ inputs.pr_number }} in repo '${{ inputs.repository }}' does not have label '${{ inputs.merge_label }}'"

release-please-config.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@
2828
"release-type": "simple",
2929
"package-name": "update-chart-version",
3030
"extra-files": ["README.md"]
31+
},
32+
"actions/auto-merge": {
33+
"release-type": "simple",
34+
"package-name": "auto-merge",
35+
"extra-files": ["README.md"]
3136
}
3237
}
3338
}

0 commit comments

Comments
 (0)