A github bot for merging & updating pull requests with a label.
This bot can merge and keep your branches up to date with the latest changes from base (master/main).
Place merge-with-label.yml in .github repository:
version: 1
merge:
# specify a list of labels that indicate whether a pull request is eligible
# for merging (regex)
# (or-list, only one label must be present on a pull request)
# (leave empty to disable the merge feature)
labels:
- "merge"
# strategy to merge (can be "commit", "squash" or "rebase")
strategy: "squash"
# amount of required approvals before merging
#requiredApprovals: 1
# specify a list of users that are required for review (regex)
# (and-list, all users need to approve)
#requireApprovalsFrom:
# -
# names of the checks that are need to pass before merging (regex)
# (and-list, all checks need to pass)
requiredChecks:
- ".*"
# require a linear history
requireLinearHistory: false
# delete branch after merging
deleteBranch: true
# never merge pull requests that were created by these users (regex)
#ignoreFromUsers:
# - "dependabot"
# never merge pull requests that match one of these titles (regex)
#ignoreWithTitles:
# - "chore:.+"
# never merge pull requests that match one of these labels (regex)
#ignoreWithLabels:
# - "dont-merge"
update:
# specify a list of labels that indicate whether a pull request is eligible
# for updating (regex)
# (or-list, only one label must be present on a pull request)
# (leave empty to disable the update feature)
labels:
- "update-branch"
# never update pull requests that were created by these users (regex)
ignoreFromUsers:
- "dependabot"
# never update pull requests that match one of these titles (regex)
#ignoreWithTitles:
# - "chore:.+"
# never update pull requests that match one of these labels (regex)
#ignoreWithLabels:
# - "dont-update"-
Create a new github app with following permissions & events
Permission Level Actions Read Checks Read and write Commit statuses Read-Only Contents Read and write Metadata Read-Only Pull requests Read and write Workflows Read and write - Check run
- Pull request
- Pull request review
- Push
- Status
-
Create a private key and save it
-
Note down the app id
-
Spin up the instance somewhere using
docker composeservices: postgres: image: supabase/postgres:17.6.1.151 restart: unless-stopped volumes: - ./pg_data:/var/lib/postgresql/data environment: POSTGRES_USER: supabase_admin POSTGRES_PASSWORD: postgres POSTGRES_DB: postgres healthcheck: test: ["CMD-SHELL", "pg_isready -U supabase_admin -d postgres"] interval: 5s timeout: 5s retries: 10 server: image: ghcr.io/eun/merge-with-label-server:latest restart: unless-stopped command: "/server" ports: - "8000:8000" environment: PORT: 8000 PostgresDSN: "postgres://supabase_admin:postgres@postgres:5432/postgres?sslmode=disable" depends_on: postgres: condition: service_healthy healthcheck: test: ["CMD", "/server", "--healthcheck"] interval: 5s timeout: 5s retries: 12 worker: image: ghcr.io/eun/merge-with-label-worker:latest restart: unless-stopped command: "/worker" volumes: - "./private-key.pem:/private-key.pem:ro" environment: PostgresDSN: "postgres://supabase_admin:postgres@postgres:5432/postgres?sslmode=disable" APP_ID: <your app id> PRIVATE_KEY: /private-key.pem HEALTH_PORT: 8001 depends_on: postgres: condition: service_healthy server: condition: service_healthy healthcheck: test: ["CMD", "/worker", "--healthcheck"] interval: 5s timeout: 5s retries: 12 deploy: replicas: 1
Make sure you fill in your app id, provide the private-key.pem file and set a secure Postgres password
-
Point the webhook url to the deployment
The following environment variables are available:
| Variable | Default Value | Description |
|---|---|---|
PostgresDSN |
(required) | PostgreSQL connection string |
AllowedRepositories |
.* |
Comma-separated list of repository patterns to allow (regex) |
AllowOnlyPublicRepositories |
false |
When true, ignore events from private repositories |
RateLimitInterval |
30s |
Minimum interval between processing the same repository |
DEBUG |
(unset) | Set to any non-empty value to enable debug logging |
TRACE |
(unset) | Set to any non-empty value to enable trace logging |
| Variable | Default Value | Description |
|---|---|---|
PostgresDSN |
(required) | PostgreSQL connection string |
AllowedRepositories |
.* |
Regex of repositories the bot may act on |
AllowOnlyPublicRepositories |
false |
Ignore events from private repositories |
RateLimitInterval |
30s |
Minimum interval between merges for the same PR |
DEBUG |
false |
Enable debug logging |
TRACE |
false |
Enable trace-level logging |
| Variable | Default Value | Description |
|---|---|---|
ADDRESS |
(unset) | Full listen address (e.g. 0.0.0.0:8000); overrides PORT |
PORT |
8000 |
Port to listen on (used when ADDRESS is not set) |
| Variable | Default Value | Description |
|---|---|---|
APP_ID |
(required) | GitHub App ID |
PRIVATE_KEY |
(required) | Path to the GitHub App private key PEM file |
HEALTH_ADDRESS |
(unset) | Full listen address for the health server (e.g. 0.0.0.0:8001); overrides HEALTH_PORT |
HEALTH_PORT |
8001 |
Port for the worker health server (used by --healthcheck and Docker health checks) |
BotName |
merge-with-label |
GitHub App bot username |
MessageRetryAttempts |
5 |
Number of times to retry a failed job |
MessageRetryWait |
15s |
Wait duration between retries |
MaxConcurrentJobs |
10 |
Maximum number of parallel worker jobs |
DurationBeforeMergeAfterCheck |
10s |
Wait after a check passes before merging |
DurationToWaitAfterUpdateBranch |
30s |
Wait after updating a branch before re-checking |
MessageChannelSizePerSubject |
64 |
Internal channel buffer size per queue subject |
