Skip to content

Add a real dist build, and generate the POT from it - #56

Open
pattonwebz wants to merge 3 commits into
mainfrom
add-dist-build-and-make-pot
Open

Add a real dist build, and generate the POT from it#56
pattonwebz wants to merge 3 commits into
mainfrom
add-dist-build-and-make-pot

Conversation

@pattonwebz

@pattonwebz pattonwebz commented Jul 25, 2026

Copy link
Copy Markdown
Member

Replaces the manual packaging recipe in .claude/skills/package-plugins with a build script matching accessibility-checker and its add-ons, then bolts the POT workflow onto it.

The dist build

npm run dist                     # -> dist/boardscribe-1.0.0.zip
npm run dist:keep-build-folder   # same, but leaves dist/boardscribe/ for CI to scan

scripts/dist.sh is the same shape as the sibling plugins: wp-scripts plugin-zip against a new files allowlist in package.json, unpacked to dist/boardscribe/, then rezipped with the version in the name and a single top-level directory named for the slug.

The allowlist encodes the manifest the skill had verified by hand, and a real run reproduces it exactly — same 26 shipped files, vendor/ reduced to autoload.php + composer/.

Two things the allowlist can't express

  • npm force-packs package.json and README.md whatever files says. The first zip I built shipped both. Found by running the build and reading unzip -l, not by reasoning about it — this is why the sibling dist.sh scripts carry two rm lines that look redundant until you hit this. (LICENSE is force-packed the same way, and that one belongs in the zip.)
  • .DS_Store stripping, previously a manual step in the skill.

A guard, not just a script

dist.sh refuses to package when vendor/ holds anything beyond autoload.php and composer/ — the failure the skill warned about in prose. Verified by running it with dev dependencies installed:

ERROR: unexpected entries in vendor/ - run 'composer install --no-dev --optimize-autoloader' first:
sirbrillig / dealerdirect / mockery / sebastian / automattic / php-parallel-lint
exit=1

The POT workflow

.github/workflows/make-pot.yml is the same file the six sibling repos now run, differing only by slug: manual dispatch only, no WordPress or MySQL (make-pot is static analysis and needs neither), wp-cli from setup-php, the generated POT diffed against the committed one while ignoring only #: reference locations, and a PR raised against base — which also drives the checkout, so the tree it builds and the branch it targets can't disagree.

Two consequences worth knowing before merging

Where POT references point changes. It scans dist/boardscribe/, so references move from src/js/* to assets/build/*src/ doesn't ship, the bundles do. The strings themselves are unaffected; wp-scripts' default Terser config already preserves translators: comments (comments: /translators:/i, extractComments: false in its webpack config), and I confirmed they're present in a POT generated from the built bundles.

The first dispatch will raise a translations PR. The committed POT dates from 2026-07-16 and yields 88 msgids; the current tree yields 122. That's the workflow working, not a fault.

The skill

Its free-plugin recipe is now "run npm run dist". The invariants it documented are kept — why vendor/ ships, the deliberate choice to leave composer.json out and accept the Plugin Check warning (PRO-1196), the single-top-level-directory rule — because those are decisions, not procedure. Pro keeps its manual recipe until it gets a dist.sh of its own; deleting it would have left Pro with no documented packaging at all.

Also corrects the manifest's assets/images/logo.png to logo.svg, which the real build shows is what actually ships, and repoints .distignore's header comment at the allowlist as the canonical source.

Testing

  • npm run dist run end to end; manifest compared against the skill's known-good list; vendor/ confirmed to be autoloader-only; dev tooling confirmed restored afterwards.
  • The vendor guard's failure path exercised deliberately (above).
  • bash -n scripts/dist.sh, actionlint and YAML parse all clean.
  • Workflow diffed against the merged multisite one — identical bar the slug and one comment.
  • The workflow itself hasn't run yet — it's dispatch-only, so nothing triggers it from a PR. Worth one dispatch from main with base empty after merge, expecting the translations PR described above.

🤖 Generated with Claude Code

https://claude.ai/code/session_019LoLgW7oFjBPxGea9kiZJ2

Summary by CodeRabbit

  • New Features
    • Added automated distribution packaging for the free plugin, including optimized production dependencies and validated release contents.
    • Added an option to retain the extracted build folder for inspection.
    • Added a manually triggered workflow to generate and propose updated translation files.
  • Documentation
    • Updated packaging guidance and release manifests for free and Pro plugins.
    • Clarified included files, vendor requirements, and post-build verification steps.
  • Chores
    • Restricted published package contents to approved plugin files.
    • Updated distribution ignore-file guidance.

Replaces the manual packaging recipe in .claude/skills/package-plugins with a
build script, matching accessibility-checker and its add-ons, then bolts the
POT workflow onto it.

## The dist build

`npm run dist` -> dist/boardscribe-<version>.zip, via scripts/dist.sh, the same
shape as the other plugins: wp-scripts plugin-zip against package.json's new
`files` allowlist, unpacked to dist/boardscribe/, then rezipped with the
version in the name and a single top-level directory named for the slug.
`dist:keep-build-folder` leaves dist/boardscribe/ behind for CI to scan.

The allowlist encodes the manifest the skill had verified by hand, and a real
run reproduces that manifest exactly - same 26 shipped files, with vendor/
reduced to autoload.php + composer/.

Two things the allowlist cannot express, so the script handles them:

- npm force-packs package.json and README.md whatever `files` says. Caught by
  running the build and reading `unzip -l`, not by reasoning about it - the
  first zip shipped both. (LICENSE is force-packed the same way, and that one
  belongs in the zip.)
- .DS_Store stripping, previously a manual step in the skill.

The script also refuses to package when vendor/ holds anything beyond
autoload.php and composer/, which is the failure the skill warned about in
prose: a zip built from a dev vendor/ is both bloated and wrong. Verified by
running dist.sh with dev dependencies installed - it exits 1 and names them.

## The POT workflow

.github/workflows/make-pot.yml is the same file the six sibling repos now run,
differing only by slug: manual dispatch only, no WordPress or MySQL (make-pot
is static analysis and needs neither), wp-cli from setup-php, the generated POT
diffed against the committed one while ignoring only `#:` reference locations,
and a PR raised against `base` - which also drives the checkout, so the tree it
builds and the branch it targets can never disagree.

It scans dist/boardscribe/, which changes where the POT's references point:
src/js/* today, assets/build/* once this runs, because src/ does not ship and
the bundles do. The strings themselves are unaffected - wp-scripts' default
Terser config already preserves `translators:` comments, confirmed present in
the POT generated from the built bundles.

Expect the first dispatch to raise a translations PR: the committed POT dates
from 2026-07-16 and yields 88 msgids, while the current tree yields 122.

## The skill

Its free-plugin recipe is now "run npm run dist". The invariants it documented
are kept - why vendor/ ships, the deliberate choice to leave composer.json out
and accept the Plugin Check warning (PRO-1196), the single-top-level-directory
rule - since those are decisions, not procedure. Pro keeps its manual recipe
until it gets a dist.sh of its own.

Also corrects the manifest's assets/images/logo.png to logo.svg, which the real
build shows is what actually ships.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019LoLgW7oFjBPxGea9kiZJ2
@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 38 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0426cd7b-9f22-4dbb-a772-9c862ae51fdc

📥 Commits

Reviewing files that changed from the base of the PR and between 7b57645 and bcde115.

📒 Files selected for processing (4)
  • .claude/skills/package-plugins/SKILL.md
  • .github/workflows/make-pot.yml
  • package.json
  • scripts/dist.sh

Walkthrough

The PR adds a scripted plugin distribution pipeline, restricts packaged contents, updates free and Pro release guidance, and introduces a manually triggered GitHub Actions workflow for generating and proposing POT file updates.

Changes

Release automation

Layer / File(s) Summary
Packaging contracts and commands
.claude/skills/package-plugins/SKILL.md, .distignore, package.json
Defines the package allowlist, distribution commands, denylist guidance, and updated free and Pro release manifests.
Distribution staging and archive validation
scripts/dist.sh
Builds, stages, validates, and finalizes the versioned plugin archive while enforcing vendor contents and optional staging retention.
POT generation and pull request flow
.github/workflows/make-pot.yml
Adds a manual workflow that builds the plugin, generates a POT file, detects meaningful changes, uploads artifacts, and opens or updates a pull request.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Maintainer
  participant Actions as GitHub Actions
  participant Build as npm run dist:keep-build-folder
  participant WPCLI as wp i18n make-pot
  participant PR as create-pull-request
  Maintainer->>Actions: Dispatch workflow with optional base
  Actions->>Build: Build plugin and retain staging folder
  Build-->>Actions: Provide generated plugin tree
  Actions->>WPCLI: Generate boardscribe.pot
  WPCLI-->>Actions: Return generated POT
  Actions->>PR: Create or update POT pull request when changed
Loading

Possibly related PRs

Suggested reviewers: stevejonesdev

Poem

A rabbit packs the zip up tight,
With vendor folders trimmed just right.
POT blooms beneath the moon,
GitHub carries it soon.
Hop, ship, and merge—what a delight!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly captures the two main changes: a real distribution build and POT generation from that build.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch add-dist-build-and-make-pot

Comment @coderabbitai help to get the list of available commands.

Pro gets the same scripts/dist.sh in equalizedigital/boardscribe-pro#35, so the
skill no longer carries a manual bash recipe for it - both plugins are now
`npm run dist`.

Its Pro manifest was also out of date, which the real build exposed: includes/
has gained DocumentPicker, DocumentCPT, MeetingDocumentRelationship and
MeetingType, assets/css has gained admin-document-picker.css and lost
calendar-templates.css, and src/js/front-end/calendarTemplates.js is gone.

Rules 6 and 7 described the hand-run bash block (the mktemp/trap footgun) and
go with it. In their place, a note that both plugins keep a committed
languages/<slug>.pot, since make-pot.yml diffs against it and raises a PR on
every run without one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019LoLgW7oFjBPxGea9kiZJ2

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.distignore:
- Around line 2-5: Add composer.json to the exclusion entries in .distignore so
the denylist matches the release manifest’s forbidden files and the documented
packaging contract.

In @.github/workflows/make-pot.yml:
- Around line 14-16: Update the make-pot workflow’s make-pot job permissions to
explicitly grant contents: write and pull-requests: write, enabling
peter-evans/create-pull-request to push changes and create or update the pull
request with GITHUB_TOKEN.

In `@package.json`:
- Line 23: Update the package.json dist script so the final composer install
restoration step runs regardless of scripts/dist.sh success, while preserving
and returning the packaging command’s failure status. Keep the initial composer
install --no-dev --optimize-autoloader prerequisite and existing build/package
sequence intact.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 76235f6b-382a-4197-a35c-f2a3ccdf5660

📥 Commits

Reviewing files that changed from the base of the PR and between 2cf5a3a and 7b57645.

📒 Files selected for processing (5)
  • .claude/skills/package-plugins/SKILL.md
  • .distignore
  • .github/workflows/make-pot.yml
  • package.json
  • scripts/dist.sh

Comment thread .distignore
Comment thread .github/workflows/make-pot.yml
Comment thread package.json Outdated
…failure

Addresses the review on this PR, plus a mistake of my own that it surfaced.

I read the packaging skill while the repo was still checked out on an older
feature branch, then rewrote it after switching to main - silently reverting
two decisions that had landed in between:

- d8113f7 ships composer.json (reversing PRO-1196) so Plugin Check's
  missing_composer_json_file finding is clear for the WP.org submission. My
  rewrite put the old "keep it out" text back, and my `files` allowlist left
  composer.json out of the zip, which would have reintroduced the warning.
- 13214ed's rule 5 records that guideline 4 is answered by keeping
  equalizedigital/boardscribe public and linking it from readme.txt, and that
  src/, webpack.config.js and package.json must start shipping if it ever goes
  private again. My rewrite deleted that paragraph.

The skill is now rebuilt from main's copy with the dist-build changes applied
on top, so both decisions survive verbatim. composer.json is in the allowlist
and confirmed in the zip; composer.lock stays out, as that note requires.

The vendor guard used GNU `find -printf` with stderr sent to /dev/null. On
macOS or BSD that option does not exist, so the command fails, the output is
empty and the guard passes silently - the exact failure it exists to catch, on
the platform this script already strips .DS_Store for. Replaced with a portable
glob-and-case loop, verified to still fail on a dev vendor/ and to name the
offending packages.

`npm run dist` chained the restoring `composer install` with &&, so a packaging
failure skipped it and left the working tree without phpcs/phpunit. It now runs
unconditionally and the packaging exit status is preserved.

Also declares contents/pull-requests write on the workflow. create-pull-request
pushes with GITHUB_TOKEN, this repo has never had a bot-authored PR to prove the
default is write, and I cannot read the repository default with my token -
wp-version-checker.yml already declares its permissions, so this matches local
convention rather than relying on an unverifiable default.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019LoLgW7oFjBPxGea9kiZJ2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant