Skip to content

Rust #325: native image parity, native- release tags, pending-count limits, native publisher isolation - #810

Merged
rmcdaniel merged 6 commits into
mainfrom
rust-325-image-parity-limits
Oct 27, 2026
Merged

rmcdaniel merged 6 commits into
mainfrom
rust-325-image-parity-limits

Conversation

@rmcdaniel

@rmcdaniel rmcdaniel commented Oct 27, 2026 •

Copy link
Copy Markdown
Member

Four independent changes for Rust Server #325, batched to save a CI cycle.

1. Qualify a native image over the shared fixture corpus (875ad3878)

Release-candidate qualification has to compare the published native image with the published PHP reference, not only a source build.

  • native-image-corpus.sh <image> runs the image the way an operator would: its own entrypoint, user and maintenance loop, with SQLite in its /app/database volume. It records the shared corpus on SQLite against published PHP 2.11.4, embedded PHP and that image, then compares the three records.
  • Fixture selection matches the Shared Server fixtures corpus part. update-validation and service-calls are recorded separately through the same helper, with PHP's maintenance loop stopped (Rust Server train: MySQL statement closes (#714), update validation, policy-map JSON, worker history presentation #723, Investigate first-call PHP service rate rejection during SQLite maintenance #796).
  • The image must be pinned by digest, or be the job's own local build. Containers use dw-parity-<run>-<attempt>-<job>, the name the shared PHP maintenance window expects.
  • It writes a durable-workflow.native-image-corpus.v1 receipt naming the image reference, the image id, the PHP reference, the runner revision and each step's status.
  • native-image-parity.yml runs on dispatch with an image digest. A PR that changes the comparison or its helpers builds the image from its own source into the runner's daemon and compares that build, so the comparison is tested before it is relied on. Nothing is pushed, and an always step removes the containers.

2. Publish native release candidates from native- Git tags (2e1b63e15)

This follows the tag scheme General chose: a native RC is its own Git tag, native-<version>, and the image tag drops the prefix.

  • verify-release-tag-source.sh takes RELEASE_TAG_PREFIX, which is either empty (PHP; behavior and messages unchanged) or native-.
  • native-release-publish.sh accepts only native-<version>.
  • check-native-release-tags.sh proves release.yml's push-tag filter matches no native- tag and still matches 2.11.4 and 2.12.0-rc.1. It runs from the Native image workflow.

3. External-worker completions meet the pending-count limits (02dbad62b)

Core 2.14.1 shipped Workflow #933's package side (#939), so the 2.11.4 reference refuses an external-worker completion that would pass the pending activity, child or timer limit. Native now checks each schedule_activity, start_child_workflow and start_timer before writing it.

  • The counts match Core 2.14.2's StructuralLimits guards.
  • The refusal is Server 2.11.4's WorkerController answer: 422 structural_limit_exceeded with the limit kind, current value and configured limit. Nothing is written and the task keeps its lease.
  • DW_V2_LIMIT_PENDING_ACTIVITIES, _CHILDREN and _TIMERS are honored with PHP's defaults (2000, 1000, 2000).

4. Give native publication its own empty Environment and secret names (33a653f4a)

native-release.yml used the PHP release's dockerhub Environment and the repository's Docker Hub pair. Native now uses the dockerhub-native Environment and NATIVE_DOCKERHUB_USERNAME / NATIVE_DOCKERHUB_TOKEN, and the workflow fails closed while they are absent: each job signs in to Docker Hub before it builds, so a dispatch pushes nothing.

The fifth commit, 98334052b, records the image parity script's Composer install in composer-sinks.json. It uses the same confined run-composer.sh call as the fixtures workflow.

d51dd139c pulls the pinned Composer image before the MySQL, PostgreSQL and SQLite fixture jobs and the image parity job run, using pull-images.sh's registry retries. This PR's previous run lost two fixture jobs to a Docker Hub HTTP 500 on that image (run 40474209808). Every other pinned image those jobs use was already pulled this way.

Checks run

  • Native image parity, locally, against an image built from this branch's source (image id sha256:d6cd5bd2…), with PHP reference bee30cde…: the PHP, embedded and native records, the comparison, and the separate update-validation and service-calls records all pass (71 cases in the main selection).
  • Pending limits: SQLite lib 338/338 and execution 562/562 on this branch rebased onto main after Move the Shared Server fixtures reference to published 2.11.4 #805. pending_limits passes on PostgreSQL, MySQL and MariaDB.
  • Policies: both organization policies and check-native-release-tags.sh pass.

Part of #325. Nothing is published or dispatched.

🤖 Generated with Claude Code

@rmcdaniel

Copy link
Copy Markdown
Member Author

General's release-control review accepts c3f36e2a6 and e75a082d9 as present in d8c6497e626ec9dfaebef34608eb1019409148bb.

The full immutable native-<version> Git tag remains bound to the planned full commit. Only the literal prefix is removed for the image tag. The current PHP release filter excludes native-prefixed tags and retains ordinary stable/RC tags. All three native release jobs use the dedicated publication environment and distinct secret names, with Docker Hub authentication before GHCR publication. Existing digest smoke, non-overwrite, two-registry index equality and attestation controls remain intact.

The actual input/tag guard passed in an isolated container with network disabled. It stops the verifier/publisher before any API or registry call. This review ran no Rust build or native publication.

Please remove the private operations reference and credential-install coordination from the new public workflow header before merge; the technical absent-credential/fail-closed explanation is sufficient. That comment cleanup needs no further implementation review. Owner CI and the existing first-publication prerequisites still apply. This is a scoped release-control acceptance, not a claim that the native/runtime changes or all hosted checks have passed.

rmcdaniel added a commit that referenced this pull request Oct 27, 2026
Two of #810's fixture jobs (execution-and-codec corpus, postgres-storage
restarts) failed at their first Composer run when Docker Hub answered the
pinned composer:2.10.3 manifest with HTTP 500 (run 40474209808). Every
other pinned image those jobs use is pulled first by pull-images.sh, which
retries registry errors; the Composer image was left to the first docker run.
The MySQL, PostgreSQL and SQLite fixture jobs, and the native image parity
job, now pull it there too. The reference is recorded in composer-sinks.json
as the same pinned Composer image.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
rmcdaniel and others added 6 commits October 27, 2026 08:46
Release-candidate qualification has to compare the published native image
with the published PHP reference, not only a source build (Server #325).

native-image-corpus.sh runs the given image as an operator would: its
entrypoint, its user, its maintenance loop, and SQLite in its /app/database
volume, with the fixtures' file:///state storage roots mounted too. It
records the shared corpus on SQLite against published PHP 2.11.4, embedded
PHP and that image, with CI's selection: the reviewed corpus plus its
pending candidates, with update-validation and service-calls recorded
separately by update-validation-sqlite.sh with PHP's maintenance loop
stopped (#723, #796). It compares the records and writes a
durable-workflow.native-image-corpus.v1 receipt naming the image reference,
its image id, the PHP reference, the runner revision and each step's status.
The image must be pinned by digest or be the job's local build.

Containers and the network use dw-parity-<run>-<attempt>-<job>, the name the
shared PHP maintenance window expects.

native-image-parity.yml runs it on dispatch with an image digest. A pull
request that changes the comparison or its helpers builds the image from its
own source into the runner's daemon and compares that build, so the
comparison is exercised before anyone relies on it. Nothing is pushed; an
always step removes the containers and keeps the evidence.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
General's release decision (server-325 chat 2922): a native release
candidate is its own immutable Git tag, native-<version> (for example
native-2.12.0-rc.1), bound to one full commit. The PHP Release workflow
runs on every pushed tag matching [0-9]+.[0-9]+.[0-9]+*, so a plain
version tag would also start a PHP release; a native- tag never matches.
- verify-release-tag-source.sh takes RELEASE_TAG_PREFIX, which may only
  be empty (the PHP release, unchanged) or native-. The full Git tag is
  verified against the planned commit exactly as before.
- native-release.yml passes native- to it in both architecture jobs.
- native-release-publish.sh accepts only native-<version> and tags both
  registries with the version, the prefix stripped.
- check-native-release-tags.sh proves it: release.yml's push-tag patterns
  match no native- tag and still match plain versions; the verifier and
  the publisher accept native- only as intended (each stopped at its
  input checks, before any API or registry call). Native image runs it
  on pull requests that change any of these files or release.yml.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Workflow #933: the package's bridge never applied the embedded executor's
pending activity, child and timer limits to external workers, and native
followed it. Native now checks each before writing a schedule_activity,
start_child_workflow or start_timer: a run already holding the limit
refuses the whole completion with PHP's WorkerController answer for
StructuralLimitExceededException (422 structural_limit_exceeded, the limit
kind, current value and configured limit), nothing is written, and the
task keeps its lease.

DW_V2_LIMIT_PENDING_ACTIVITIES, _CHILDREN and _TIMERS are honored instead
of refused or ignored, with PHP's defaults (2000, 1000, 2000), and the
structural limit snapshot reports the values in force.

Core 2.14.1 shipped the package side (Workflow #939), so the published
2.11.4 reference enforces these limits; native had not, until now.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
native-release.yml used the PHP release's dockerhub Environment and the
repository's DOCKERHUB_USERNAME / DOCKERHUB_TOKEN, so a dispatch would
resolve the predecessor publisher credential even though native has never
published. Native now names the dockerhub-native Environment and
NATIVE_DOCKERHUB_USERNAME / NATIVE_DOCKERHUB_TOKEN. While they are absent the
workflow fails closed: each job signs in to Docker Hub before it builds, so a
dispatch stops at sign-in and pushes nothing to either registry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
native-image-corpus.sh installs the conformance runner's dependencies with
the same scripts/ci/run-composer.sh invocation the Shared Server fixtures
workflow uses, so it carries the same confinement: the pinned Composer image
after the fixed Brotli decoder, with the checked CA file and an empty CA
directory set after the caller's options.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Two of #810's fixture jobs (execution-and-codec corpus, postgres-storage
restarts) failed at their first Composer run when Docker Hub answered the
pinned composer:2.10.3 manifest with HTTP 500 (run 40474209808). Every
other pinned image those jobs use is pulled first by pull-images.sh, which
retries registry errors; the Composer image was left to the first docker run.
The MySQL, PostgreSQL and SQLite fixture jobs, and the native image parity
job, now pull it there too. The reference is recorded in composer-sinks.json
as the same pinned Composer image.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@rmcdaniel
rmcdaniel force-pushed the rust-325-image-parity-limits branch from 88a26ec to d51dd13 Compare October 27, 2026 08:46
@sonarqubecloud

Copy link
Copy Markdown

@rmcdaniel
rmcdaniel added this pull request to the merge queue Oct 27, 2026
Merged via the queue into main with commit 1a0c6c0 Oct 27, 2026
59 of 60 checks passed
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