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
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,18 @@ this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm

## [Unreleased]

## [3.16.0] - 2026-07-05

### Added

- **The scaffolded PR workflow prunes its own report branch, out of the box.**
`styleproof-init`'s `.github/workflows/styleproof.yml` now also runs on
`pull_request: closed`: when a PR closes, a `prune` job removes that PR's `pr-<n>/`
folder from the report branch (`styleproof-reports`), so the branch no longer grows
without bound as PRs come and go — no adopter has to remember to garbage-collect it.
The report job is unchanged, only guarded to skip the close event. Covered by the
`styleproof-init` workflow test.

## [3.15.0] - 2026-07-05

### Changed
Expand Down
2 changes: 1 addition & 1 deletion action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ inputs:
description: 'Directory with restored or freshly captured PR-head maps to compare (.json.gz + .png).'
required: true
report-branch:
description: 'Orphan branch that stores reports (created on first run). One pr-<n>/ folder per PR; never pruned.'
description: 'Orphan branch that stores reports (created on first run). One pr-<n>/ folder per PR; the styleproof-init workflow prunes each on PR close.'
default: 'styleproof-reports'
github-token:
description: 'Token used to push the report branch and post the PR comment.'
Expand Down
41 changes: 40 additions & 1 deletion bin/styleproof-init.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,9 @@ const CI_WORKFLOW = `name: StyleProof
# report without a browser;
# - on cache miss, CI recaptures both sides in one pinned environment so the
# comparison stays valid.
on: pull_request
on:
pull_request:
types: [opened, synchronize, reopened, closed]

permissions:
contents: write
Expand All @@ -355,6 +357,8 @@ permissions:

jobs:
styleproof:
# Report on open/update; the prune job below handles close.
if: github.event.action != 'closed'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand Down Expand Up @@ -408,6 +412,41 @@ ${PM.setup}
baseline-dir: __stylemaps__/base
fresh-dir: __stylemaps__/head
require-approval: true

prune:
# PR closed: drop its pr-<n>/ folder from the report branch so the branch
# never grows without bound. Keep BRANCH in sync with the report-branch
# input above (default: styleproof-reports).
if: github.event.action == 'closed'
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Prune this PR's report folder
shell: bash
env:
GH_TOKEN: \${{ github.token }}
BRANCH: styleproof-reports
PR: \${{ github.event.pull_request.number }}
run: |
set -euo pipefail
REMOTE="https://x-access-token:\${GH_TOKEN}@github.com/\${{ github.repository }}.git"
if ! git ls-remote --exit-code "$REMOTE" "refs/heads/$BRANCH" >/dev/null 2>&1; then
echo "No $BRANCH branch yet — nothing to prune."; exit 0
fi
TMP="$(mktemp -d)"
# Blobless clone keeps this fast; a very large report branch may prefer
# a --no-checkout plumbing rewrite instead.
git clone --filter=blob:none --single-branch --branch "$BRANCH" "$REMOTE" "$TMP"
cd "$TMP"
if [ ! -d "pr-$PR" ]; then
echo "No pr-$PR/ folder — nothing to prune."; exit 0
fi
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git rm -r --quiet "pr-$PR"
git commit -m "chore(styleproof): prune report for closed PR #$PR"
git push origin "$BRANCH"
`;

function writeFileSafe(file, contents, { force: f } = {}) {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "styleproof",
"version": "3.15.0",
"version": "3.16.0",
"description": "Catch every CSS change before it ships — review PRs and certify refactors by the browser's computed styles, not pixels. Works with any styling system.",
"keywords": [
"playwright",
Expand Down
7 changes: 7 additions & 0 deletions test/init.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,13 @@ for (const manager of [
const workflow = readFile(root, '.github/workflows/styleproof.yml');
for (const pattern of manager.workflow) assert.match(workflow, pattern);
for (const pattern of manager.absent ?? []) assert.doesNotMatch(workflow, pattern);

// Report branch self-prunes on PR close (out of the box) — manager-independent.
assert.match(workflow, /types: \[opened, synchronize, reopened, closed\]/);
assert.match(workflow, /if: github\.event\.action != 'closed'/); // report skips close
assert.match(workflow, /^\s{2}prune:/m);
assert.match(workflow, /if: github\.event\.action == 'closed'/);
assert.match(workflow, /git rm -r --quiet "pr-\$PR"/);
} finally {
rmTmp(root);
}
Expand Down
Loading