Run 536 proved the cache works -- ACTIONS_CACHE_URL is now populated, no
GHES warning, "Cache saved with key: apt-php-builder-deps-ARM64-v1" -- and
in doing so showed the key was wrong. The jobs that saved it were 8.1 and
8.2.
They take the ondrej PPA path, a handful of runtime packages, while 8.3
takes php-builder and its ~70 -dev packages. One shared key therefore lets
whichever job finishes first decide what every other job restores, and 8.1
is always first, at ~30s against 8.3's several minutes. 8.3 would have
restored a few runtime .debs it has no use for and then downloaded all 70
anyway. My "the dep list is the same for every PHP version" comment was
true only among the builder versions.
Keyed per version now, so each path caches what it actually installs. That
also picks up a small win on 8.1 and 8.2 rather than only avoiding harm.
Both temporary steps are gone. Report restored .debs was there to show the
cache URL arriving and the restore landing; both are established, so it
goes. Keep downloaded .debs stays -- it is not instrumentation, it disables
Ubuntu's docker-clean, without which there are no .debs left to cache.
Refs #178.
Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Uw545F1vveNJKjzLxdi2ks
thatguygriff/infra#1 turned the runner cache server on, so actions/cache
has an endpoint for the first time. v4 rather than v3 because v4.2+ can
speak the cache service v2 API, which is what the runner serves.
The instrumentation step now also prints ACTIONS_CACHE_URL, so a single
run shows the endpoint arriving and the cache being read in one log
rather than needing a separate probe.
Refs #178.
Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Uw545F1vveNJKjzLxdi2ks
Experiment for #178. On self-hosted runners setup-php installs PHP 8.3+
through php-builder, whose install.sh apt-installs ~70 -dev packages
before unpacking the build. The build tarball itself is only 19MB, so
that apt work is the whole cost, not the download.
Ubuntu's image drops the .debs after install, so every job fetches them
from the archive again. This keeps them and restores them through the
cache server, which lives in the cluster, so a WAN download becomes a
local one. The dependency list does not vary by PHP version, so a single
key serves 8.3 and 8.5 and the quality and build jobs alike.
Only the .debs are cached. /var/lib/apt/lists is deliberately left alone,
since a stale index is how apt starts 404ing mid-install, and reducing
flakiness is the entire point.
The Report restored .debs step is temporary instrumentation to show
whether the cache is actually being read. Baseline to beat, from run 526:
8.1 30s, 8.2 53s, 8.3 454s, quality 151s, 8.5 733s and a hard failure.
Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Uw545F1vveNJKjzLxdi2ks
8.5 lands on setup-php's php-builder path, same as 8.3, so it pays for
~70 apt -dev packages on every run. It timed out in run 526 and passed in
527 on identical code, which is a coin toss, and merging it would mean
intermittent red for a version nothing ships on yet.
The code is fine on 8.5 — verified locally on 8.5.9: 915 tests, PHPStan
and PHPCS clean, check-platform-reqs satisfied. This is purely about the
runners, so 8.5 comes back once #178 is fixed and the matrix is cheap
again. This PR is now just the PHPCS/PHPStan consolidation.
Refs #178.
Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Uw545F1vveNJKjzLxdi2ks
Tested and the hypothesis is dead. actions/cache@v4 resolved properly
(SHA 0057852) and printed the same GHES warning as v3, so the action
version was not what was closing the gate.
That points at the runner rather than the action. Gitea's docs say the
runner patches the GHES check out of the action's bundle only when it
recognises it, and that a bundle it does not recognise "is left alone".
No patching for either v3 or v4, and no ACTIONS_CACHE_URL to patch it
towards, is what you get when cache is simply off in the runner config.
So the fix is cache.enabled in act_runner's config.yaml, with host set to
an address job containers can reach. Nothing in this repository unblocks
it, and inert steps are what let the Composer cache rot unnoticed, so the
experiment comes out again. Both halves — the apt cache and the move to
v4 — should land together once the runner serves a cache.
Refs #178.
Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Uw545F1vveNJKjzLxdi2ks
My last conclusion was wrong. The GHES warning is not evidence that the
runner has no cache server; it is actions/cache v3 disabling itself.
v3's isGhes() reads GITHUB_SERVER_URL, and anything that is not
github.com reads as GitHub Enterprise, so on Gitea it always trips and
the action returns before touching the cache. That explains the 0.2s
save perfectly well without any runner setting being off.
Gitea's runner 3.0.0 release notes say every runner starts its own cache
server and that the runner "patches action bundles at load time to open
the GHES gate and read the cache endpoint from ACTIONS_CACHE_URL", with
actions/cache supported unforked. Our runners report v3.0.0, so the
server should be there and the gate should be open — but the patching
evidently does not reach a v3 bundle.
So this reapplies the apt cache and moves every actions/cache to v4. If
the hypothesis holds the GHES warning disappears, the save step actually
takes time, and a second run restores the .debs. The Composer cache gets
the bump too, since it has been silently doing nothing for the same
reason.
Refs #178.
Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Uw545F1vveNJKjzLxdi2ks
Measured on run 527 and it cannot work. Every actions/cache step on these
runners prints
Cache action is only supported on GHES version >= 3.5 ... check with
GHES admin if Actions cache service is enabled or not
and then no-ops. The save step finishes in 0.19-0.31s, which is not a
few hundred megabytes of .debs going anywhere. setup-php timings were
unchanged against the run 526 baseline, within the usual variance:
8.3 454s then 148s, 8.5 733s then 446s, both noise rather than signal.
The same warning appears on the Composer cache this workflow has carried
all along, including run 523 and earlier, so that step has never cached
anything either. Worth fixing, but in the runner config rather than here.
Leaving dead steps in the workflow is how the Composer cache went years
without anyone noticing it did nothing, so the experiment comes out until
act_runner has its cache service enabled. It is in the history when that
happens. Detail in #178.
Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Uw545F1vveNJKjzLxdi2ks
Experiment for #178. On self-hosted runners setup-php installs PHP 8.3+
through php-builder, whose install.sh apt-installs ~70 -dev packages
before unpacking the build. The build tarball itself is only 19MB, so
that apt work is the whole cost, not the download.
Ubuntu's image drops the .debs after install, so every job fetches them
from the archive again. This keeps them and restores them through the
cache server, which lives in the cluster, so a WAN download becomes a
local one. The dependency list does not vary by PHP version, so a single
key serves 8.3 and 8.5 and the quality and build jobs alike.
Only the .debs are cached. /var/lib/apt/lists is deliberately left alone,
since a stale index is how apt starts 404ing mid-install, and reducing
flakiness is the entire point.
The Report restored .debs step is temporary instrumentation to show
whether the cache is actually being read. Baseline to beat, from run 526:
8.1 30s, 8.2 53s, 8.3 454s, quality 151s, 8.5 733s and a hard failure.
Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Uw545F1vveNJKjzLxdi2ks
The two jobs were identical up to their final step, each paying for its own
Setup PHP. That step is the flaky one (#178), so running it twice to reach
two short commands was two chances for a run to fall over instead of one.
They are now steps in a single Coding Standards & Static Analysis job.
The one thing given up is that PHPCS failing now stops the job before
PHPStan reports, where before the two ran in parallel and both spoke. That
seemed a fair trade for halving the exposure, and the fix for a PHPCS
failure rarely depends on knowing PHPStan's verdict at the same time.
PHP 8.5 joins the test matrix. composer.json already allows it at >=8.1
and the suite passes on 8.5.9 locally: 915 tests, PHPStan and PHPCS clean,
check-platform-reqs satisfied. 8.4 is deliberately not added, only 8.5.
Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Uw545F1vveNJKjzLxdi2ks
The GitHub API rate limit was the wrong diagnosis, so this reverts the
1Password-backed token added in #175 along with the mirrored composite
action, leaving the workflows as they were.
Timing every Setup PHP step across runs 454-523 rules the rate limit out.
PHP 8.1 and 8.2 install in 26-41 seconds, 12 for 12, never once failing.
PHP 8.3 has never finished in under 143 seconds and ranges up to 1273,
with two outright failures. Those jobs share a fan-out, and so an egress
address and a rate limit bucket, with the 8.1 and 8.2 jobs that are never
touched. A throttle could not sort itself by PHP version that way.
Run 523, the first to carry the token, is the direct refutation: the
token resolved and verified, and Setup PHP still took 749 seconds on
kallone and 408 on eris. The 8.3 penalty also predates the whole story,
sitting at ~145 seconds back on 30 July.
What is left is a slow path specific to 8.3 on these arm64 runners, whose
long tail sometimes crosses the step timeout and reports the unhelpful
"Could not setup PHP 8.3". That is worth fixing on its own terms rather
than behind a token that was never in the path.
Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Uw545F1vveNJKjzLxdi2ks
setup-php resolves its tools through the GitHub API, unauthenticated at 60
requests an hour per source address. A CI fan-out across the fleet exhausts
that bucket, and the step then retries for several minutes before reporting
only "Could not setup PHP 8.3". It reads as a hang rather than a throttle,
and it took out both a main CI run and a release build.
Each cluster has its own egress address and so its own bucket, which is why
the same job passed on one runner and failed on another in the same minute.
The token comes from 1Password through the Connect instance in whichever
cluster picked up the job, matching the pattern in thatguygriff/infra. That
repository's composite action is not reachable from here, so it is mirrored
locally. It stays a step output rather than being exported to the job
environment, to keep it away from the package scripts composer install runs.
Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_0133tYSQoZhoKebKZV8o2GPs
Add CHANGELOG.md (one section per version, newest first; the top section
always reflects the current plugin header version — release status is
purely a matter of tagging).
The Release workflow now extracts the tagged version's changelog section
and publishes it as the Gitea release body (POST on create, PATCH when the
release was pre-created via the UI). After a stable release, a new
bump-version job bumps the plugin to the next patch version, opens a fresh
changelog section, and opens a PR. Pre-release tags are skipped.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Closes#65
Declare an Update URI header and answer core's update_plugins_{hostname}
filter from a new Update\UpdateChecker that offers the latest published
Gitea release's zip asset when it is newer than the installed version,
with transient caching and silent degradation on API failures.
Add a release workflow that fires on v* tag pushes: verifies the tag
matches the plugin Version header, runs the tests, builds the plugin zip,
and attaches it to the release (reusing a UI-created release, flagging
hyphenated versions as pre-release so /releases/latest skips them).
Co-Authored-By: Claude Fable 5 <[email protected]>
The unanchored dd\( pattern matched the substring in DateTimeImmutable::add(),
failing the check on non-debug code.
Co-Authored-By: Claude Fable 5 <[email protected]>
Gitea/Actions re-zips artifacts on download, so uploading the built plugin
zip produced a double-wrapped archive (a zip containing a zip). WordPress
then reported "No valid plugins were found" because the upload had no
plugin folder/header at its top level.
Unpack the built zip and upload the resulting plugin folder instead, so the
downloaded artifact's top level is unsupervised-schedular/ and installs
directly via Plugins -> Add New -> Upload.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
- bin/build-zip.sh + `composer build`: stage runtime files only, generate a
production (no-dev) optimized autoloader, and emit
dist/<slug>-<version>.zip with a single top-level plugin folder, ready to
upload via wp-admin. Tests, tooling configs, docs, and dev dependencies
are excluded; version is read from the plugin header.
- CI `build` job: on push to main (post-merge), after lint/static-analysis/
test/no-debug pass, runs the build and uploads the zip via
actions/upload-artifact.
- Ignore build/ and dist/.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
- Add phpcs.xml.dist: excludes PSR-4 file naming, camelCase naming,
short array syntax, and redundant per-method/property docblocks
- Fix wp_unslash() on all $_POST reads (LoginPage, AvailabilityController)
- Add phpcs:ignore for password field (must not be sanitized)
- Fix Yoda conditions throughout (AvailabilityRepository, AvailabilityEndpoint,
BookingEndpoint, AvailabilityController)
- Fix inline comments to end with full stops (AdminMenu)
- Replace short ternary ?: with explicit full ternary (BookingEndpoint)
- Rename $namespace param to $route_namespace (reserved keyword warning)
- Add short descriptions to doc blocks that had tag-only blocks
- Add nonce suppression comment in handleFormAction (nonce verified by caller)
- Update composer.json and CI to use phpcs.xml.dist
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
- Custom DB tables for availability slots and lesson bookings
- Instructor (wp-admin) and student (front-end) roles with custom capabilities
- REST API under us-scheduler/v1 for availability CRUD and booking
- [us_booking] and [us_student_login] shortcodes for student front end
- PHPUnit + Brain\Monkey unit test suite (29 tests)
- Gitea Actions CI: lint, PHPStan, tests on PHP 8.1/8.2/8.3, no-debug check
- Feature docs under docs/features/
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>