Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
e8fcaeb
Build/Test Tools: Add Code Reference preview foundations
sirreal Aug 9, 2026
a80f03b
Build/Test Tools: Resolve Code Reference build inputs
sirreal Aug 9, 2026
4e27b0b
Build/Test Tools: Pin Code Reference build tools
sirreal Aug 9, 2026
62dc257
Build/Test Tools: Cache the Code Reference site base
sirreal Aug 9, 2026
b97d59f
Build/Test Tools: Generate Code Reference parser data
sirreal Aug 9, 2026
173b818
Build/Test Tools: Package Code Reference snapshots
sirreal Aug 9, 2026
2a8dc89
Build/Test Tools: Add Code Reference runtime policy
sirreal Aug 9, 2026
ca62018
Build/Test Tools: Validate Code Reference snapshots
sirreal Aug 9, 2026
dea4904
Build/Test Tools: Orchestrate Code Reference previews
sirreal Aug 9, 2026
b1cdc81
Build/Test Tools: Stop executing preview source during import
sirreal Aug 9, 2026
d1fd8a0
Build/Test Tools: Add the Code Reference pull request build
sirreal Aug 9, 2026
13e0aab
Build/Test Tools: Validate Code Reference publication handoffs
sirreal Aug 9, 2026
976908d
Build/Test Tools: Add the Code Reference publisher transport
sirreal Aug 9, 2026
02c2cd2
Build/Test Tools: Add published preview validation
sirreal Aug 9, 2026
02155cc
Build/Test Tools: Publish PR snapshots transactionally
sirreal Aug 9, 2026
d2a18d6
Build/Test Tools: Test PR publication transactions
sirreal Aug 9, 2026
7242c10
Build/Test Tools: Publish Code Reference PR snapshots
sirreal Aug 9, 2026
36f1339
Build/Test Tools: Add PR cache cleanup transport
sirreal Aug 9, 2026
744e374
Build/Test Tools: Manage Code Reference PR lifecycle
sirreal Aug 9, 2026
785e45c
Build/Test Tools: Activate Code Reference PR lifecycle
sirreal Aug 9, 2026
60970c1
Build/Test Tools: Close PR lifecycle races
sirreal Aug 9, 2026
15f2237
Build/Test Tools: Bind stale docs comments to exact state
sirreal Aug 9, 2026
4c44ebd
Build/Test Tools: Define trunk docs publication identity
sirreal Aug 9, 2026
92db866
Build/Test Tools: Add trunk publication transport
sirreal Aug 9, 2026
d67ad63
Build/Test Tools: Publish trunk docs transactionally
sirreal Aug 9, 2026
00c09d5
Build/Test Tools: Test trunk publication recovery
sirreal Aug 9, 2026
43f4b57
Build/Test Tools: Run docs preview on trunk pushes
sirreal Aug 9, 2026
cc4e878
Build/Test Tools: Document Code Reference previews
sirreal Aug 9, 2026
000b7ff
Build/Test Tools: Validate the stable docs pointer
sirreal Aug 9, 2026
77f1aaf
Build/Test Tools: Fix docs workflow runner paths
sirreal Aug 9, 2026
2009084
Build/Test Tools: Apply Core style to docs harness
sirreal Aug 9, 2026
2b1d7cb
Build/Test Tools: Apply Core style to docs PHP
sirreal Aug 9, 2026
65fa146
Build/Test Tools: Preserve docs preview comment state
sirreal Aug 9, 2026
7cc5076
Build/Test Tools: Preserve the last docs preview link
sirreal Aug 9, 2026
44342ea
Build/Test Tools: Let Playground choose validation workers
sirreal Aug 9, 2026
82c01ef
Build/Test Tools: Use six Playground snapshot workers
sirreal Aug 9, 2026
ced2240
Build/Test Tools: Serialize Playground snapshot builds
sirreal Aug 9, 2026
6344e3f
Build/Test Tools: Preserve ambiguous trunk assets
sirreal Aug 9, 2026
f265b00
Build/Test Tools: Allow staging fork documentation builds
sirreal Aug 10, 2026
7ff5bd7
Build/Test Tools: Enforce fork preview validation
sirreal Aug 10, 2026
ae69eb6
Build/Test Tools: Report nested publisher failures
sirreal Aug 10, 2026
e438fd8
Build/Test Tools: Grant PR publisher write access
sirreal Aug 10, 2026
6f3f931
Build/Test Tools: Preserve stale docs preview links
sirreal Aug 10, 2026
b9f9088
Merge branch 'trunk' into add-docs-preview-v2
sirreal Aug 10, 2026
000d9f8
Build/Test Tools: Resolve stable builds between betas
sirreal Aug 10, 2026
32a930a
Build/Test Tools: Replace orphaned preview assets
sirreal Aug 10, 2026
50252c0
Build/Test Tools: Verify the Composer download
sirreal Aug 10, 2026
866f463
Build/Test Tools: Yield gracefully in lifecycle races
sirreal Aug 10, 2026
4462b8a
Build/Test Tools: Yield gracefully in publisher startup races
sirreal Aug 10, 2026
8bbee81
Build/Test Tools: Recreate a deleted preview comment
sirreal Aug 10, 2026
68dbda9
Build/Test Tools: Publish the newest built trunk snapshot
sirreal Aug 10, 2026
d9e6d1c
Build/Test Tools: Survive CDN caching of the trunk pointer
sirreal Aug 10, 2026
cd4796b
Build/Test Tools: Report failed trunk validation
sirreal Aug 10, 2026
4db798d
Add strict type checking to docs preview
sirreal Aug 10, 2026
b13236b
Ignore *.tsbuildinfo anywhere
sirreal Aug 10, 2026
ba80eed
Build/Test Tools: Stop scanning the whole trunk build history
sirreal Aug 10, 2026
28f79c8
Build/Test Tools: Skip publishing for skipped builds
sirreal Aug 10, 2026
55dca5c
Build/Test Tools: Harden preview reuse and output capture
sirreal Aug 10, 2026
54debcd
Build/Test Tools: Give every remote read a deadline
sirreal Aug 10, 2026
bf332e7
Build/Test Tools: Retry transient API reads
sirreal Aug 10, 2026
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
8 changes: 8 additions & 0 deletions .github/actionlint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
paths:
.github/workflows/docs-playground-preview-publish.yml:
ignore:
# actionlint 1.7.11 predates GitHub's concurrency queue property.
- 'unexpected key "queue" for "concurrency" section'
.github/workflows/docs-playground-preview-lifecycle.yml:
ignore:
- 'unexpected key "queue" for "concurrency" section'
1 change: 1 addition & 0 deletions .github/docs-playground-preview/.nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
20.20.2
119 changes: 119 additions & 0 deletions .github/docs-playground-preview/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# Code Reference Playground preview

This directory pins the inputs for the WordPress Core Code Reference preview. The implementation lives in `.github/scripts/docs-playground-preview`; GitHub Actions only supplies exact source identity, caching, and publication authority.

The preview is informational. Pull request source is parsed as data in a job with no secrets and `contents: read` at most. Build jobs use GitHub's cache service: a trusted `trunk` build can warm the shared cache, while GitHub scopes a pull-request-created entry to its pull request ref so it cannot warm or replace the default-branch cache. Only default-branch publisher and cleanup code receives repository write permissions for release assets, comments, labels, cache deletion, or the stable `trunk` pointer.

## Local build

Use the exact Node, npm, PHP, and Composer versions in `dependencies.json`, then run:

```sh
npm --prefix .github/docs-playground-preview run build
```

The command infers the current Git repository and commit, resolves the moving Playground `beta` channel, builds or restores the invariant site base, parses eligible PHP under `src`, imports the complete Code Reference, packages the snapshot, and runs the same behavioral validation as CI. Local output and cache data are written below `.cache/docs-playground-preview`.

CI passes explicit `--source-repository`, `--source-sha`, run identity, cache, output, and metadata paths to this same command. `--resolve-only` writes the concrete beta and exact cache identity before the cache restore step. Local and CI snapshots are equivalent when their symbol counts, representative routes, search, runtime constants, and size boundary agree; their bytes need not agree.

Run the script tests with:

```sh
npm test --prefix .github/docs-playground-preview
```

## Updating pins

All repositories in `dependencies.json` must remain on the allowed repositories enforced by `.github/scripts/docs-playground-preview/lib/config.mjs`, and every repository revision must be a full immutable commit hash. Tool versions are exact. GitHub Actions are pinned to full commit hashes in the workflow files.

To update a pinned repository:

1. Change its full commit in `dependencies.json`. The dependency's own lock files come from that immutable checkout; this repository does not copy or re-verify them.
2. Run the script tests and a complete local build.
3. Exercise cold and warm builds in the staging repository.

Keep duplicated tool identities synchronized:

- For `@wp-playground/cli`, `yarn`, `@wordpress/scripts`, or `@wordpress/i18n`, update both `dependencies.json` and the exact dependency in `package.json`, then regenerate `package-lock.json` with the manifest's exact Node and npm versions. A Playground CLI update also requires changing its fixed version check in `.github/scripts/docs-playground-preview/lib/config.mjs`.
- For Node, update `dependencies.json`, `.nvmrc`, `package.json`'s `engines.node`, and every `setup-node` input in the build, publish, and lifecycle workflows. Select a Node distribution containing the npm version recorded in `dependencies.json`; the build rejects a different npm version.
- For PHP, update `dependencies.json`, the fixed runtime checks in `.github/scripts/docs-playground-preview/lib/config.mjs` and `.github/scripts/docs-playground-preview/lib/publication.mjs`, and both `setup-php` inputs in the build workflow. PHP remains `8.4` unless the specification changes.
- For Composer, update `dependencies.json` and both `setup-php` Composer tool specifications in the build workflow.
- For a GitHub Action, update its full commit SHA and the adjacent release comment in every workflow use.

After any tool change, run the script tests, regenerate the lockfile when applicable, complete a local build, and exercise cold and warm staging builds.

A manifest or harness change automatically produces a different exact cache key. Increment `cacheSchemaVersion` when the stored base layout or meaning changes incompatibly, even if no dependency pin changed. Broad restore keys are prohibited.

## Repository activation

The workflows run in `WordPress/wordpress-develop`. Trusted staging work in `sirreal/wordpress-develop` runs only when the repository Actions variable `DOCS_PREVIEW_STAGING` is exactly `true`. That variable controls `trunk` builds, PR and `trunk` publishers, comments, labels, stale and expired lifecycle handling, cleanup, cache deletion, and every other trusted mutation.

There is one deliberate staging exception: the untrusted `pull_request` build job is enabled by the hard-coded `sirreal/wordpress-develop` allowlist without consulting `DOCS_PREVIEW_STAGING`. GitHub does not expose the base repository's Actions variables to a fork's `pull_request` workflow run. Requiring the variable there would make the required fork preview impossible to stage. With staging disabled, explicitly labeling a PR may therefore consume isolated read-only CI and create a one-day handoff artifact, but it cannot publish, comment, change labels, delete caches, or perform another trusted mutation. Arbitrary forks remain inert. This user-approved exception to section 5 is confined to the staging repository and the untrusted build job.

The staging repository needs a `docs-preview` label and the Actions variables used for the scenario being tested. Disable trusted staging by deleting `DOCS_PREVIEW_STAGING` or setting it to anything other than the lowercase string `true`.

## Validation enforcement

Behavioral validation is advisory unless the repository Actions variable `DOCS_PREVIEW_ENFORCE` is exactly `true`. Advisory failures emit workflow warnings and terminal PR state but cannot publish or replace a snapshot. Fatal build, handoff, identity, digest, size, and publication failures always fail.

GitHub does not expose base-repository Actions variables to an untrusted fork `pull_request` job. Such a job therefore records a behavioral failure in its handoff without enforcing it locally. The trusted publisher reads `DOCS_PREVIEW_ENFORCE` from the base repository, updates the sticky comment without publishing the invalid candidate, and then fails its workflow when enforcement is enabled. Same-repository and `trunk` builds can read the variable directly and fail their build workflow as well.

To enable enforcement:

1. Open repository **Settings**.
2. Open **Secrets and variables → Actions → Variables**.
3. Create or update `DOCS_PREVIEW_ENFORCE` with the value `true`.

## Pull request lifecycle

The label name is exactly `docs-preview`, and only pull requests targeting `trunk` are eligible.

- Adding the label requests a complete build of the exact pull request head repository and SHA.
- A healthy public snapshot for the same SHA is reused. **Re-run all jobs** on the original build bypasses reuse.
- While the label remains, a synchronized head cancels the obsolete build and requests the newest SHA.
- The latest terminal publisher removes the label after success, validation failure, or build failure.
- A later unlabeled commit retains the latest successful link, marks it stale, and asks a maintainer to add the label again.
- Closing or merging deletes only that pull request's assets and `refs/pull/<number>/merge` docs caches, then marks the historical comment expired.

The sticky comment is separate from the general Core Playground comment and is identified by `<!-- code-reference-docs-preview -->`.

## Publication and cleanup

Snapshots and metadata are assets on the `code-reference-playground-preview` prerelease.

- Pull request snapshots use `code-reference-pr-<number>-<sha>-<run>-<attempt>.zip` with a same-stem JSON metadata asset. Only the latest healthy pair for an open pull request is retained.
- Trunk snapshots use `code-reference-trunk-<sha>-<run>-<attempt>.zip` with a same-stem JSON metadata asset.
- The stable trunk Blueprint is `code-reference-trunk.json` on the dedicated `docs-preview-code-reference` Git branch. The repository README points Playground at that stable raw URL.

Trunk publication uploads and publicly validates the immutable snapshot and metadata, creates and publicly validates an immutable Blueprint commit, then atomically moves the dedicated branch ref and re-reads its exact SHA. Only after that identity is proven are older trunk assets deleted. A failed or ambiguous ref mutation retains every snapshot the ref could identify.

PR cleanup matches only its exact PR prefix. Trunk cleanup matches only the trunk prefix. Neither path deletes assets owned by the other or changes another pull request.

## Recovery

Publication failure never requires deleting the current working asset first.

- For a PR, fix the cause and add `docs-preview` again, or use **Re-run all jobs** on the original build for a forced same-SHA rebuild.
- For `trunk`, re-run the newest trunk build or push the next commit. The next successful publisher moves the stable ref and removes orphaned trunk assets.
- If the publisher cannot determine whether the stable ref moved, it retains both old and candidate assets. Inspect the ref and the two metadata assets before removing anything manually.
- Do not delete the `docs-preview-code-reference` branch or the snapshot it names during recovery. A successful newest trunk run repairs the pointer safely.

## Bespoke validators

Pinned standard tools own Git, ZIP, SQLite, JSON, PHP, and process semantics. This implementation does not inspect archive grammar, database bytes, canonical serialization, descriptors, or process trees. The retained project-specific checks are limited to boundaries or product behavior that standard tools cannot understand on their own:

- **Dependency manifest and cache identity:** checks the repository allowlist, immutable commit shape, exact tool versions, concrete beta identity, and every base input. This protects the shared default-branch cache boundary.
- **Publisher handoff identity:** binds schema, deployment repository, event, PR when applicable, exact source SHA, run ID and attempt, runtime identity, filename, size, and digest before any publication. This protects the untrusted-to-trusted publication boundary.
- **Candidate file size and digest:** uses ordinary file stat and SHA-256 tools without opening the snapshot. This enforces the publisher identity and 100 MiB boundaries.
- **Parser product inspection:** uses the standard JSON parser, then enforces eligible Core source paths, supported hook types, nonempty records, per-type catastrophic-under-count floors, and the trusted importer root. These are required section 14 product and “parse, never execute” checks; they do not validate the parser's internal format beyond the fields the importer consumes.
- **Latest-wins authorization:** re-reads current PR or `trunk` state and the newest eligible workflow attempt immediately before publication mutations. This prevents an obsolete run from moving or deleting the live preview.
- **Public snapshot delivery:** fetches the immutable snapshot through the Playground CORS proxy and checks response status, CORS headers, byte size, and SHA-256. Publication is not complete until the public product has the validated identity.
- **Public metadata identity:** downloads the just-published JSON metadata, applies the same source/runtime/snapshot identity checks, and compares its parsed value with the candidate. This prevents a wrong public metadata asset from becoming the retained pointer identity.
- **Public Blueprint and stable ref identity:** parses the small Blueprint with the standard JSON parser, checks its semantic identity through the public proxy at an immutable commit, atomically moves the dedicated Git ref, and verifies that ref's SHA. This protects transactional availability without reimplementing Git semantics.
- **Behavioral snapshot validation:** boots the final snapshot through Playground and checks the required routes, search, provenance, and runtime policy. This is the section 14 product validator; it deliberately ignores intermediate archive and database representations.

No archive grammar, database format, canonical byte serialization, descriptor transaction, or process-tree validator is part of this pipeline.

## Staging evidence

Before upstream rollout, record links to the `sirreal/wordpress-develop` workflow runs and comments that demonstrate every scenario in the specification's staging acceptance gate. Evidence may be accumulated across runs. Keep the run URLs and observed SHA, cache state, comment state, public URL, route/search results, runtime policy, failure-preservation result, cleanup result, and measured public snapshot size in the eventual pull request description.
95 changes: 95 additions & 0 deletions .github/docs-playground-preview/dependencies.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
{
"schemaVersion": 1,
"cacheSchemaVersion": 1,
"toolchain": {
"nodeVersion": "20.20.2",
"npmVersion": "10.8.2",
"composerVersion": "2.8.12",
"yarnVersion": "1.22.22",
"wpScriptsVersion": "32.6.0",
"wpI18nVersion": "6.24.0"
},
"playground": {
"cliVersion": "3.1.48",
"phpVersion": "8.4",
"wordpressChannel": "beta",
"wordpressVersionApi": "https://api.wordpress.org/core/version-check/1.7/?channel=beta",
"blueprintSchema": "https://playground.wordpress.net/blueprint-schema.json"
},
"repositories": {
"phpdocParser": {
"repository": "WordPress/phpdoc-parser",
"commit": "1156399efccafd344818fa3b566ce5beafdc655e",
"path": "."
},
"wporgDeveloper": {
"repository": "WordPress/wporg-developer",
"commit": "f2b6b9c1fe788fb4a5441a296b591f6dff540607",
"path": "source/wp-content/themes/wporg-developer-2023"
},
"wporgParent2021": {
"repository": "WordPress/wporg-parent-2021",
"commit": "3b61f284dcc600dc5ad500e34d56108351909d32",
"path": "source/wp-content/themes/wporg-parent-2021"
},
"wporgMuPlugins": {
"repository": "WordPress/wporg-mu-plugins",
"commit": "f37f522a0ed78b64748fa0b390e58e9f74de32ea",
"path": "mu-plugins"
},
"postsToPosts": {
"repository": "scribu/wp-posts-to-posts",
"commit": "d2f297dbe257a09438da6ffe22c9a876acb7b49b",
"path": "."
},
"codeSyntaxBlock": {
"repository": "mkaz/code-syntax-block",
"commit": "7179d747eef70ca8760cf5e0c04d3877158fa350",
"path": "."
}
},
"limits": {
"snapshotBytes": 104857600,
"artifactRetentionDays": 1
},
"validation": {
"minimumSymbols": {
"classes": 400,
"methods": 3000,
"functions": 1800,
"hooks": 600,
"filters": 1000
},
"routes": {
"index": {
"path": "/reference/",
"expectedText": "Code Reference"
},
"class": {
"path": "/reference/classes/wp_html_tag_processor/",
"expectedText": "WP_HTML_Tag_Processor"
},
"method": {
"path": "/reference/classes/wp_html_tag_processor/next_tag/",
"expectedText": "next_tag"
},
"function": {
"path": "/reference/functions/wp_parse_args/",
"expectedText": "wp_parse_args"
},
"hook": {
"path": "/reference/hooks/init/",
"expectedText": "init"
},
"filter": {
"path": "/reference/hooks/the_content/",
"expectedText": "the_content"
}
},
"search": {
"path": "/?s=wp_parse_args&post_type=wp-parser-function",
"expectedText": "wp_parse_args",
"expectedPath": "/reference/functions/wp_parse_args/"
}
}
}
Loading
Loading