Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions .github/workflows/check-plcc-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,32 @@ on:
- cron: '0 9 * * 1' # Every Monday at 09:00 UTC
workflow_dispatch: # Allow manual trigger for testing

permissions:
contents: write
pull-requests: write
# Nothing here uses GITHUB_TOKEN any more: checkout and gh both authenticate
# with the App installation token, so GITHUB_TOKEN needs no scopes at all.
permissions: {}

jobs:
check:
runs-on: ubuntu-latest
permissions: {}
steps:
# Minted per run and short-lived, so it cannot go stale between the
# weekly runs this workflow depends on.
- name: Generate release bot token
id: app-token
uses: actions/create-github-app-token@v3
Comment on lines +21 to +23
with:
app-id: ${{ secrets.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}

- name: Checkout
uses: actions/checkout@v4
with:
token: ${{ secrets.RELEASE_TOKEN }}
token: ${{ steps.app-token.outputs.token }}

- name: Check for new PLCC release
env:
GH_TOKEN: ${{ secrets.RELEASE_TOKEN }}
GH_TOKEN: ${{ steps.app-token.outputs.token }}
run: |
# Fetch the latest PLCC release tag
LATEST=$(gh api repos/ourPLCC/plcc/releases/latest --jq '.tag_name')
Expand Down
26 changes: 19 additions & 7 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,33 @@ on:
push:
branches: [main]

permissions:
contents: write
packages: write
pull-requests: write
issues: write
# These grants applied to GITHUB_TOKEN, which semantic-release no longer
# uses — it authenticates with the App token now. The only remaining use of
# GITHUB_TOKEN is the GHCR login, so packages:write is all that is needed.
permissions: {}

jobs:
release:
runs-on: ubuntu-latest
permissions:
packages: write
steps:
# A static PAT rots silently: this one expired and only surfaced months
# later, failing checkout on the next push to main. App installation
# tokens are minted per run and expire in about an hour, so there is
# nothing long-lived to go stale.
- name: Generate release bot token
id: app-token
uses: actions/create-github-app-token@v3
with:
app-id: ${{ secrets.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}
Comment on lines +24 to +29

- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.RELEASE_TOKEN }}
token: ${{ steps.app-token.outputs.token }}

- name: Log in to GHCR
uses: docker/login-action@v3
Expand All @@ -40,7 +52,7 @@ jobs:
id: semantic
uses: cycjimmy/semantic-release-action@v4
env:
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
GITHUB_TOKEN: ${{ steps.app-token.outputs.token }}

- name: Read PLCC version
if: steps.semantic.outputs.new_release_published == 'true'
Expand Down
21 changes: 19 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,29 @@ Commands available: `plccmk`, `scan`, `parse`, `rep`
Use [Conventional Commits](https://www.conventionalcommits.org/) in your commit messages:
- `fix:` — patch release
- `feat:` — minor release
- `feat!:` or `BREAKING CHANGE:` — major release
- `feat:` **with a `BREAKING CHANGE:` footer** — major release
- `ci:`, `docs:`, `chore:`, `test:`, `refactor:` — no release

Write the footer, not `feat!:`. semantic-release uses the Angular preset,
which does not parse the `!` shorthand: a `feat!:` subject with no footer
matches nothing and produces **no release at all**, which is easy to miss
because the pipeline still goes green. The `BREAKING CHANGE:` footer is what
actually triggers a major.

If you squash-merge a major, make sure the footer survives into the squash
commit body — with it dropped, the release silently downgrades to a minor.

### Automated PLCC updates

A weekly workflow checks for new PLCC releases and opens a PR automatically. If you see a PR like `fix: update PLCC to vX.Y.Z`, review the CI results and merge if green.

### Release setup

The release workflow requires a `RELEASE_TOKEN` repository secret with a GitHub App token (preferred) or a classic PAT. Classic PAT scopes required: `repo`, `write:packages`. This is required because `GITHUB_TOKEN` cannot push to the protected `main` branch.
The release and PLCC-update workflows need two repository secrets, `APP_ID` and `APP_PRIVATE_KEY`, belonging to the **ourPLCC Release Bot** GitHub App. Each run mints its own short-lived installation token. This is required because `GITHUB_TOKEN` cannot push to the protected `main` branch.

The App also needs, per repository:
- Contents and Pull requests set to **Read and write**
- Installation access granted to this repository — org-level installation does not cover new repos automatically
- A place in the `main` ruleset's bypass list, which only becomes selectable once repository access is granted

An earlier setup used a static `RELEASE_TOKEN` PAT. That is no longer referenced by any workflow and can be deleted. It is worth knowing why it was replaced: a PAT gives no expiry signal, so when it lapsed nothing surfaced until the next push to main failed at checkout, months later.
Loading