Port of the 2.x change to 3.x, with the same extractor script.
Registration sent the GitHub release body to the updater, so the notes
every install sees were written at publish time — after review, outside
the repo, with nothing checking they existed or matched what shipped.
CHANGELOG.md becomes the source. It is written and reviewed alongside the
change itself, so what installs are offered cannot drift from what was
merged, and the release body can simply point at it.
A release with no section for its tag fails the job rather than
registering an empty changelog. A manual dispatch falls back to the
release body, since re-registering a release older than this file is
legitimate — which covers 3.0.0-alpha.1.
Backfilled with 3.0.0-alpha.1.
manual_docker_build fires on any workflow_dispatch, and pushes
invoiceshelf/invoiceshelf:${{ inputs.tag }} where tag is required and
defaults to "latest". Dispatching to re-register a release therefore also
rebuilt from the dispatched branch and overwrote the published :latest
image — from 3.x that would hand every :latest user a 3.0.0-alpha build.
The registration path added in #709 is meant to be a safe recovery route,
so triggering it must not have that side effect. A dispatch carrying
register_tag now runs registration only.
Port of #708 to 3.x. This branch carries the identical bug: the changelog
is written to /tmp/changelog.txt while curl is told to read
`changelog.txt`, a relative path resolved against the checkout. The next
3.x release would fail exactly as 2.4.2 did — published, zip uploaded,
images built, and never registered, so no install offered it.
It has not bitten here only because no 3.x release has been cut since the
automation landed; 3.0.0-alpha.1 predates it, the same reason 2.4.2 was
the first to hit it on 2.x.
Registration moves into its own job that downloads the published asset
rather than reusing the build job's working directory, so it can also be
re-run on demand for an existing tag instead of needing production shell
access to repair. A missing WEBSITE_RELEASE_TOKEN is now fatal on a real
release rather than a warning, and the registration is verified against
the download endpoint afterwards, which fails unless the row exists and
its zip is retrievable.
Both blocks are byte-identical to what merged on 2.x, so the two trees do
not drift and the next change ports cleanly.
Checked for this branch specifically: the verify probe returns 200 for
3.0.0-alpha.1, so it holds on the insider channel; that release ships the
same InvoiceShelf.zip asset name; and the "-" suffix already derives
CHANNEL=insider without change. LATEST_MAJOR stays "2" — 2.x owns the
moving :latest tags until 3.0.0 GA.
Append a step to the release_artifact_build job that POSTs the freshly built
InvoiceShelf.zip + metadata to the website updater's /api/releases endpoint
(Bearer WEBSITE_RELEASE_TOKEN) right after the asset upload, so deployed installs
are offered the release automatically instead of a manual kubectl+tinker import.
- Runs only on release events; skips with a warning if WEBSITE_RELEASE_TOKEN is unset
- Channel derived from the prerelease flag / "-" tag suffix (GA->stable, pre->insider)
- min_php + extensions read from config/installer.php; release fields passed via env
to avoid shell injection from the release body
- Idempotent (the endpoint upserts per version)
Claude-Session: https://claude.ai/code/session_012tpgisKcrC4D4mCbGTeTKz
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Multi-arch builds run composer (incl. the merge-plugin's update) twice and exhausted GitHub's unauthenticated API rate limit, failing with 'Could not authenticate against github.com'. Pass the Actions token as a build secret and feed it to composer via COMPOSER_AUTH (build-time only, never in the image).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Remove the scheduled nightly/alpha builds; gate :latest on a single LATEST_MAJOR; publish :beta/:next for pre-releases; keep a transitional :nightly alias on stable. Also fix the production Dockerfile so a stale host public/build can no longer clobber the freshly built frontend (reorder COPY, ignore public/build).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* build: migrate frontend tooling to pnpm (v3)
Rebuilds the stale #673 on current 3.x so it doesn't revert #657's test
split, the Node-24 action bumps, or composer-install@4.0.0.
- package.json: packageManager pnpm@11.6.0; drop dead 'resolutions'
- pnpm-workspace.yaml: nodeLinker hoisted, allowBuilds vue-demi,
overrides brace-expansion (replaces resolutions)
- pnpm-lock.yaml generated via 'pnpm import' from yarn.lock (keeps the
resolved versions, incl. vite 8.0.3 / rolldown rc.12); yarn.lock removed
- docker.yaml + release.yaml: pnpm/action-setup@v6 + cache pnpm + pnpm
install/build (action versions and the #657 split left intact; check.yaml
needs no change — its test job is PHP-only after #657)
- 3 Dockerfiles: node:24 + corepack + pnpm install --frozen-lockfile && pnpm build
- Makefile, composer 'dev' script, CLAUDE.md, .gitignore -> pnpm
* fix(deps): pin vite to 8.0.5 (security)
Now that 3.x is the default branch, Dependabot flags vite <8.0.5. Pin to
8.0.5 (the patched version), which keeps rolldown 1.0.0-rc.12 — still
below 8.0.15 where the broken rolldown 1.0.3 (the init_runtime_dom_esm_bundler
chunk regression) starts, so the build stays clean. Mirrors v2's #674.
* ci: speed up the test job (disable Xdebug, drop frontend build, run parallel)
The `tests` job in check.yaml carried three sources of wasted wall-clock,
none of which it actually used:
- `coverage: xdebug` loaded Xdebug into every PHP process, but no step ever
passes `--coverage` — so it was pure tax (~2-3x slower execution). Switch
to `coverage: none`. If coverage is wanted later, use pcov + `--coverage`.
- The job ran `npm install` + `npm run build` before the PHP tests. The
feature suite is API/JSON only (49/56 feature files use getJson/assertJson)
and nothing renders the Vite blade, so the built assets are never needed.
Drop the Node/Vite steps; release & docker workflows still build assets.
- Tests ran single-process. brianium/paratest is already installed and the
runner has 4 cores, so run `php artisan test --parallel`.
Validated locally: full suite passes in parallel (exit 0), including
repeated runs of the two filesystem-writing module tests — no races.
docker.yaml carries the same pattern but only runs on release/nightly cron,
so it is left for a follow-up.
* ci: apply the same test-job speedups to docker.yaml
The release/nightly `tests` job in docker.yaml carried the identical waste
that check.yaml had: Xdebug loaded but never used for coverage, an
unnecessary frontend build before the PHP tests, and serial execution.
Mirror the check.yaml fix: coverage: none, drop the Node/Vite steps
(the suite is API/JSON and the separate release_artifact_build job builds
its own assets), and run php artisan test --parallel.
* ci: run module-scaffolding tests serially under --parallel
The Modules/* tests (module:make ScaffoldProbe + modules_statuses.json
toggles) mutate shared on-disk module state. paratest isolates the DB
per worker but NOT the filesystem, so concurrent workers boot with
ScaffoldProbe enabled and fatal on the un-autoloaded ServiceProvider
(31 failures). Tag them 'modules' (Pest group on Feature/Company/Modules)
and split CI: parallel --exclude-group=modules, then serial --group=modules.
* ci: stub Vite in tests + bump all actions to Node 24 versions
Part A (fixes#657): the customer-portal entrypoint test renders the SPA
shell (app.blade.php → @vite). With the frontend build dropped from CI
there's no manifest, so it 500'd (ViteManifestNotFoundException). Call
$this->withoutVite() in TestCase::setUp() so SPA-shell renders work
without a built manifest; the build stays dropped.
Part B: bump every Node-20 action to its node24 release — checkout v4->v6,
setup-node v4->v6, paths-filter v3->v4, cancel-workflow-action 0.12.1->0.13.1,
softprops/action-gh-release v2->v3, docker/{setup-buildx v3->v4, login v3->v4,
metadata v5->v6, build-push v5->v7}. setup-php@v2, ramsey/composer-install@v2
(composite) and svenstaro/upload-release-action@v2 are already node24.
* ci: bump ramsey/composer-install v2 -> 4.0.0 (node24 internal cache)
composer-install@v2 is composite but internally calls actions/cache@v3
(Node 20), which still trips the deprecation. 4.0.0 uses actions/cache
v5.0.3 (Node 24) and keeps the composer-options input we use.
Update Node.js from 20 to 24 across CI workflows, Dockerfiles,
package.json engines field, and add .node-version file for consistent
local development.