No description
  • TypeScript 98.3%
  • JavaScript 1.7%
Find a file
Thibaut Cholley 37d7c98777
Some checks failed
Self-test / Test prune deletes an orphaned branch (push) Failing after 5s
Self-test / Test dry-run reports orphans without deleting (push) Failing after 6s
Check dist/ / Check committed dist/ is up to date (push) Successful in 23s
fix: stop branch pagination only on an empty page
Forgejo (unlike GitHub) silently clamps per_page to a server-side max,
so a page smaller than PER_PAGE no longer means "last page". Stopping
on that condition caused branches beyond the clamp to be missed and
treated as orphaned/deleted on Amplify.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-03 11:52:27 +02:00
.forgejo/workflows feat: initial release 2026-09-02 09:13:51 +02:00
__tests__ fix: stop branch pagination only on an empty page 2026-09-03 11:52:27 +02:00
dist fix: stop branch pagination only on an empty page 2026-09-03 11:52:27 +02:00
src fix: stop branch pagination only on an empty page 2026-09-03 11:52:27 +02:00
.eslintignore feat: initial release 2026-09-02 09:13:51 +02:00
.eslintrc.json feat: initial release 2026-09-02 09:13:51 +02:00
.gitattributes feat: initial release 2026-09-02 09:13:51 +02:00
.gitignore feat: initial release 2026-09-02 09:13:51 +02:00
.prettierignore feat: initial release 2026-09-02 09:13:51 +02:00
.prettierrc.json feat: initial release 2026-09-02 09:13:51 +02:00
action.yml feat: initial release 2026-09-02 09:13:51 +02:00
jest.config.js feat: initial release 2026-09-02 09:13:51 +02:00
LICENSE feat: initial release 2026-09-02 09:13:51 +02:00
package-lock.json feat: initial release 2026-09-02 09:13:51 +02:00
package.json feat: initial release 2026-09-02 09:13:51 +02:00
README.md feat: initial release 2026-09-02 09:13:51 +02:00
tsconfig.json feat: initial release 2026-09-02 09:13:51 +02:00

actions-amplify-prune-branches

Forgejo/GitHub action that deletes AWS Amplify branches which no longer have a matching branch (or open pull request) in the repository. Written in TypeScript using the AWS SDK for JavaScript v3 and @actions/github, distributed as a Node.js action — no aws/gh CLI required on the runner.

Typical use case: an Amplify app has pull-request previews enabled, and a branch gets created on Amplify for every open PR. When a PR is merged or closed outside of the usual PR-closed webhook flow (or the webhook is missing/misconfigured), the Amplify branch is left behind. This action compares what's on Amplify against what's actually in the repo and removes the leftovers.

How it works

  1. Lists the "expected" branch names from the repository, either:
    • every branch (source: branches), or
    • the head branch of every open pull request (source: pull-requests, the default).
  2. For each configured Amplify app, lists all of its branches.
  3. Any Amplify branch whose name is not in the expected set and not in the whitelist is considered an orphan.
  4. In dry-run mode (the default), orphans are only reported. Otherwise, they are deleted with amplify:DeleteBranch.

Requirements

  • AWS credentials with amplify:ListBranches and (outside dry-run) amplify:DeleteBranch permission on every target app, available through the standard AWS SDK credential chain. Typically configured upstream in the workflow with aws-actions/configure-aws-credentials.
  • A repo-token with read access to the repository's branches or pull requests (github.token works for both GitHub Actions and Forgejo Actions).

Usage

- name: Configure AWS credentials
  uses: aws-actions/configure-aws-credentials@v4
  with:
    aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
    aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
    aws-region: eu-west-1

- name: Prune orphaned Amplify branches
  uses: forge.app-cp.fr/Elsie/actions-amplify-prune-branches@v1
  with:
    repo-token: ${{ secrets.GITHUB_TOKEN }}
    source: pull-requests
    apps: |
      d1234abcd5678,eu-west-1
      d8765dcba4321,us-east-1
    whitelist: |
      main
      staging
      production
    dry-run: 'false'

Running it on a schedule (e.g. nightly) rather than only on PR events is recommended, so branches orphaned by a missed webhook still get cleaned up:

on:
  schedule:
    - cron: '0 3 * * *'
  workflow_dispatch: {}

Inputs

Name Required Default Description
repo-token yes — Token to read branches/pull requests from the repository API
apps yes — One app-id,aws-region pair per line. Blank lines and # comments are ignored
source no pull-requests branches (all repo branches) or pull-requests (head branch of open PRs)
whitelist no '' Branch names to never delete on Amplify, one per line and/or comma-separated
dry-run no true If true, only report orphans without deleting anything
owner no current repo owner Override the repository owner
repo no current repo name Override the repository name
api-url no runner-provided URL Override the Git hosting REST API base URL

Outputs

Name Description
orphan-count Number of Amplify branches found without a matching repository branch/PR
deleted-count Number of Amplify branches actually deleted (always "0" in dry-run mode)
orphans JSON array: [{"appId","region","branchName","deleted"}]

Development

# Install dependencies
npm install

# Run the test suite
npm test

# Lint and format
npm run lint
npm run format

# Build the bundle (must be committed)
npm run build

# Run everything before pushing
npm run all

The dist/ directory must be committed — Forgejo runners execute it directly without running npm install. The check-dist.yml workflow ensures the committed bundle is always in sync with the sources.

License

See LICENSE. Internal Elsie use only.