Merge open, mergeable GitHub PRs across a fixed list of repositories, either manually or on a weekly schedule (Sunday 02:00 UTC via GitHub Actions).
- Add repos to
config/repos.txt(owner/repoorowner/repo:main). Seeconfig/repos.example.txt. - Put your token in a
.envfile at the repo root:make init-envthen edit.env(see GitHub token). - Preview:
make dry-run— then run:make merge.
Run make help for all Makefile targets.
The merge script loads GITHUB_TOKEN first, then GH_TOKEN, from:
- Existing environment variables (already set in the shell or by CI), then
- A
.envfile at the repo root (values from.envare not applied if the variable is already set).
If neither variable ends up set, the script exits with a message that includes the path it checked.
- Copy the template:
make init-envorcp .env.example .env. - Edit
.envand setGITHUB_TOKEN=ghp_...(orGH_TOKEN=...). Optional:MERGE_METHOD=merge|squash|rebase. - Run
make dry-runormake merge..envis listed in.gitignore— do not commit it.
Use another file path: python scripts/merge_open_prs.py --env-file /path/to/secrets.env.
- GitHub → Settings → Developer settings → Personal access tokens.
- Classic: generate a token with the
reposcope (full control of private repositories) if you need private repos; for public-only repos, narrower scopes may suffice, but merging almost always needs write access to pull requests. - Fine-grained: create a token with Pull requests read/write (and Contents as required by your org) for each repository (or parent organization) you list in
config/repos.txt. - If the org uses SAML SSO, authorize the token for that org after creation.
To force a one-off token without editing .env, set the variable in the shell before running; environment wins over .env for that variable.
GITHUB_TOKEN=ghp_xxx make mergeWith GitHub CLI: GITHUB_TOKEN="$(gh auth token)" make dry-run (still no need to export if you prefix the command).
- GitHub Actions: store the token as the
MERGE_REPOS_TOKENrepository secret (the workflow sets the environment for the job; it does not use.envfrom the repo). - Vercel: set
GITHUB_TOKENorGH_TOKENin Project → Environment Variables.
Never commit real tokens. .env.example is safe to commit; .env is not.
Enable .github/workflows/weekly-merge-prs.yml by pushing this repo to GitHub and adding the MERGE_REPOS_TOKEN secret. Cron is UTC; adjust the workflow if you need another timezone.
This repo is a small Python API + cron, not a full web app. Vercel can call api/weekly_merge.py on a schedule; long runs or many repos may hit function duration limits, so GitHub Actions is usually a better fit for heavy merges.
-
Prerequisites
- Vercel account and Vercel CLI (
npm i -g vercel) optional but useful.
- Vercel account and Vercel CLI (
-
Import the project
- Dashboard: Add New… → Project, import this Git repository.
- Framework preset: Other (no Next.js). Root directory: repo root.
-
Environment variables (Project → Settings → Environment Variables, apply to Production at minimum):
Name Value GITHUB_TOKENorGH_TOKENPAT with permission to list and merge PRs on every repo in config/repos.txt.CRON_SECRETRandom string (16+ chars). Vercel sends it as Authorization: Bearer …on cron requests; the handler rejects other callers. See Securing cron jobs.MERGE_METHODOptional: merge(default),squash, orrebase. -
Cron schedule
vercel.jsonregisters0 2 * * 0(Sunday 02:00 UTC), same idea as the GitHub workflow. Vercel cron is always UTC. On the Hobby plan, scheduled jobs run at most once per day and may fire any time within that hour (accuracy). -
Deploy
- Push to the connected branch, or run
vercel --prodfrom the repo root aftervercel link.
- Push to the connected branch, or run
-
Verify
-
Settings → Cron Jobs: confirm
/api/weekly_mergeis listed. -
Manual test (replace host and secret):
curl -sS -H "Authorization: Bearer YOUR_CRON_SECRET" \ "https://YOUR_PROJECT.vercel.app/api/weekly_merge"
-
Logs: Deployments → select deployment → Logs, or Cron Jobs → View Logs.
-
Caveats: The serverless route must finish within your plan’s max duration (maxDuration in vercel.json is capped by plan). If merges are slow or numerous, keep using GitHub Actions instead.
- Agent / Claude context: claude.md
- Agent workflow (tool-agnostic): docs/skill-weekly-merge.md
The merge script uses Python 3 and the standard library only.