mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-13 13:38:01 +02:00
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Release verification must run the same server integration coverage as PR verification. > - Three server suites use real Rust Runner binaries. > - PR checks already run them with the shared Rust dependency cache, but release checks cold-build them inside ordinary server test shards. > - A cold Dot Runner build can consume its entire setup deadline before any test runs. > - This pull request gives release verification a required cached native integration lane and preserves every test. ## Linked Issues or Issue Description **What happened?** On master commit `1881894973a2b25838d8abed9bd8aeebc3af4441`, [Cloud readiness run 37837810707](https://github.com/paperclipai/paperclip/actions/runs/37837810707) failed in server shard 7. Dot Runner's `cargo build --release` exceeded its 300-second child-process deadline. The other 1,640 tests in that shard passed. The failed setup then tried to remove an undefined temporary path and emitted a second error. Cargo output was captured as an opaque buffer, which obscured build progress. **What did you expect to happen?** Build fixture binaries before tests in a lane with the existing Rust dependency cache. Run all native integration tests and make their result required for release readiness. A setup failure should keep its original diagnostic. **Steps to reproduce** Run release verification on a clean runner. The existing `general-server-without-chat` group retains the three Cargo-backed suites outside the PR workflow. The Dot suite can time out during a cold release build. Run the new workflow and partition tests against the previous source to reproduce five routing and coverage failures deterministically. **Version / commit** Observed at `1881894973a2b25838d8abed9bd8aeebc3af4441`; this change is based on `ed6abbf158b`. **Deployment mode** GitHub Actions Release and Cloud readiness verification. No application runtime or deployment action changes. Related work: #15581 also edits Dot integration tests for onboarding behavior. It does not repair release test routing. Searches found no open PR for this failure. ## What Changed - Add an explicit server test group that excludes the dedicated chat and native suites. Preserve the existing PR and local test groups. - Run all three native server suites in one required matrix lane with the existing trusted Rust dependency cache. - Build debug and release fixture binaries in a visible step with a 10-minute limit before tests start. Keep Cargo freshness checks and the existing test deadlines. - Stream Cargo diagnostics and clean up safely when Dot setup stops before creating its temporary directory. - Test complete, non-overlapping partitions for Release, Cloud readiness, other callers, and existing PR/local groups. Check cache restrictions, build order, and the source verification dependency. ## Verification - Passed 44 workflow and partition tests: `node --test scripts/__tests__/run-vitest-stable-shard.test.mjs scripts/__tests__/release-verify-workflow.test.mjs`. - The same tests fail in five relevant cases against the previous workflow and selector. They pass after this correction. - An independent review repeated all 44 tests successfully. - Passed `actionlint .github/workflows/release-verify.yml`, `git diff --check`, and a secret scan. - Passed all 381 workflow policy tests: `node --test '.github/scripts/tests/*.test.mjs'`. - Passed full `pnpm build` in a clean worktree. - Built debug and release fixture binaries, then passed all 32 tests in the three real native integration suites: `pnpm test:run:general -- --group general-server-native-runner` (49.5 seconds, no skips). - Passed full `pnpm -r typecheck`. - Injected a synthetic Cargo setup failure. The suite reports that failure without the secondary undefined-path cleanup error. - Exact-head CI completed: 53 successful checks, including all server shards, both native Runner lanes, build, typecheck, browser tests, and the canary dry run. Two optional Storybook checks were skipped. - Started the duplicate local `pnpm test:run` aggregate and stopped it after exact-head CI passed. No completed local aggregate result is claimed. All test processes owned by that run exited. - Greptile scored the final head `ffe5ab5a28af2dfea9db1c1952c652f070bf52f8` at 5/5 with no review threads. - `Superagent Supply Chain Scan` is neutral, not passed: it only supports exact dependency pin replacements and cannot verify structural edits to `.github/workflows/release-verify.yml`. It reported no annotations. Independent source review, Greptile, actionlint, and the workflow policy tests cover this structural change. - GitHub still requires a code-owner review for the workflow files. There are no merge conflicts. ## Risks - Adds one CI matrix job, which increases concurrent runner demand. The existing cache writer and trust restrictions stay in place. - Missing dependencies still compile from the lockfile. A build that exceeds its step limit fails visibly; failed tests still block source verification. - Workflow execution uses the new lane after merge. PR tests validate the workflow contract and run the existing native test lane. - The supply chain scanner cannot analyze this workflow structure. Its neutral result is an explicit coverage limit; it is not counted as a successful scan. - No runtime, schema, deployment, publication, credential, or test-timeout changes. ## Model Used OpenAI Codex, based on GPT-6, with repository inspection, code execution, and independent agent review. The exact deployed model ID and context-window size are not exposed in this session. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
239 lines
14 KiB
Markdown
239 lines
14 KiB
Markdown
# Cloud build readiness
|
|
|
|
The `Cloud readiness` workflow starts for every master push and retains the
|
|
versioned `Cloud source verified v1` job. It calls the full `Release Verify`
|
|
workflow for that exact commit, including typecheck, builds, general and
|
|
serialized tests, and Runner verification. The source proof depends on every
|
|
source check and fails closed if verification fails, is cancelled, or is skipped.
|
|
|
|
The recurring public `-cloud` publisher and its `Cloud deployable v1` gate are
|
|
retired. The workflow no longer builds a legacy image or waits for one.
|
|
Keep its filename and source-proof job name stable: npm canary publication and
|
|
downstream image composers consume that exact contract.
|
|
|
|
Standard images still publish independently through `docker.yml`. The
|
|
`cloud-migrator-artifacts.yml` workflow still publishes signed exact-source
|
|
migrators independently. A downstream composer must verify those artifacts,
|
|
build and test its own image, and record separate deployment readiness.
|
|
|
|
Verification runs outside the full npm release's concurrency group. Different
|
|
commits have independent groups. The npm canary release reuses the source proof
|
|
for its exact master push instead of starting another `Release Verify` run.
|
|
Stable releases and candidate-branch betas still run full verification.
|
|
|
|
The canary consumer requires the expected workflow ID and path, upstream source
|
|
repository, master push event, full SHA, and a successful job in the latest run
|
|
attempt. It checks the run again after reading the jobs to reject a concurrent
|
|
rerun. Missing proof waits for up to 45 minutes; failed, skipped, cancelled,
|
|
ambiguous, or mismatched proof cannot authorize publication. API failures fail
|
|
closed. If a source check fails, fix it and rerun Cloud readiness before retrying
|
|
the release. Use **Re-run all jobs** when a later attempt did not rerun the source
|
|
proof; an earlier attempt's successful job is not accepted. This avoids duplicate
|
|
test jobs on standard runners. Measure queue time to assess the timing gain.
|
|
|
|
Release verification spreads the general server suites across ten standard hosted
|
|
runners, with the long chat suite split separately across three jobs. Each server
|
|
job still runs one test worker. The three Rust-backed server suites run in a
|
|
separate Runner lane with the shared dependency cache. That lane builds both
|
|
debug and release test binaries in a visible, bounded step before Vitest starts;
|
|
the suites still check Cargo freshness and run against the current source. A
|
|
cache miss builds from source. Native test failures block source verification.
|
|
The partition covers every suite exactly once; normal PR and local test groups
|
|
keep their existing shape. More jobs increase concurrent runner demand, so compare
|
|
queue time as well as test duration.
|
|
|
|
All release verification installs, including the Runner scorer and chaos evals,
|
|
allow pnpm to refresh an outdated lockfile. Contributor PRs leave lockfile updates
|
|
to the separate refresh bot, so a dependency-changing master commit can arrive
|
|
before that bot's PR merges. Verification must install and test that commit
|
|
without waiting for another merge. The generated lockfile stays in the job's
|
|
workspace; these checks do not commit it back to the repository.
|
|
|
|
## Consumer contract and retirement boundary
|
|
|
|
Accept `Cloud source verified v1` only from the latest attempt of the canonical
|
|
`cloud-readiness.yml` master push for the expected repository identity and full
|
|
source SHA. Check the job itself and reject failed, skipped, cancelled, or
|
|
ambiguous proof. This signal verifies source only. It creates no release record,
|
|
certifies no composed image, and deploys no instance.
|
|
|
|
Downstream deployment consumers must separately verify the standard image's
|
|
immutable digest and attestation, the exact-source migrator's signature and
|
|
integrity, migration compatibility, their own image composition, and target
|
|
health. Order automatic candidates by master ancestry, not completion time.
|
|
|
|
Merge this retirement only after all active automatic deployment consumers use
|
|
the standard-image composition contract. A consumer still selecting
|
|
`Cloud deployable v1` will stop advancing at the last legacy-ready commit.
|
|
Do not rename the source proof to the old readiness name or weaken a consumer
|
|
check to hide that dependency.
|
|
|
|
Existing release records, immutable image digests, migrator artifacts, and
|
|
registry tags are retained for rollback. No registry deletion or live deployment
|
|
is part of this change. Explicit `release.yml` preview requests still use the
|
|
legacy `cloud` Dockerfile target for a specified source commit. They do not
|
|
restart recurring legacy publication. Keep that compatibility path until its
|
|
operator consumers migrate separately.
|
|
|
|
The old `nightly-cloud`, `beta-cloud`, `latest-cloud`, and `canary-cloud` aliases
|
|
stop advancing. Self-hosted standard release aliases continue unchanged. A
|
|
rollback to an already published image needs no rebuild; restoring recurring
|
|
legacy publication would require reverting the publisher retirement.
|
|
|
|
## Timing and rollout
|
|
|
|
The reusable Runner chaos workflow scopes concurrency to the caller workflow
|
|
and source ref. Cloud readiness, stable verification, and standalone evals can
|
|
verify the same commit at the same time. They must not cancel each other's
|
|
required test job.
|
|
|
|
Measure the complete path from a master merge to a healthy target running that
|
|
exact commit. Keep readiness and deployment as separate milestones:
|
|
|
|
| Milestone | Evidence | Elapsed time starts at |
|
|
| --- | --- | --- |
|
|
| Merge | Merged PR timestamp and full merge commit SHA | Merge |
|
|
| Image available | Successful full-SHA image publication and verification | Merge |
|
|
| Source verified | Successful `Cloud source verified v1` job in the accepted push run and attempt | Merge |
|
|
| Composed image ready | Downstream composition verification and publication succeed | Merge |
|
|
| Canary healthy | Deployment consumer's canary health gate confirms the target commit | Merge |
|
|
| Fleet complete | Campaign succeeds for all eligible targets at that commit | Merge |
|
|
|
|
Record the source SHA, workflow run ID and attempt, readiness job completion
|
|
time, and deployment campaign identity together. Verify the run against the
|
|
consumer contract above. A manual dispatch can test wiring, but its timestamp
|
|
does not measure automatic merge-to-deploy latency. A preparation-only run
|
|
resolves artifacts without deploying a target and must not be counted as a
|
|
successful deployment.
|
|
|
|
Record queue time and the image, source-verification, migrator, and composition durations
|
|
separately. The slowest prerequisite determines readiness; shortening an already
|
|
faster prerequisite may have no effect on the total. After readiness, measure
|
|
consumer discovery delay, artifact resolution, canary health, and fleet rollout.
|
|
An automatic consumer that still waits for the full npm canary publication has
|
|
that queue on its critical path even if cloud artifacts are ready earlier.
|
|
|
|
For a target health measurement, confirm the deployed source SHA as well as
|
|
service health. A proxy health response alone may describe the control plane
|
|
while the tenant still runs the previous image. Report the eligible target count,
|
|
excluded or sleeping targets, retries, and failures with the fleet result. Record
|
|
runner queue conditions and cache state; one warm or cold run is a sample, not a
|
|
latency guarantee.
|
|
|
|
## Reserved AWS verification capacity
|
|
|
|
`AWS_POST_MERGE_CI_ENABLED=true` routes cloud source verification and
|
|
exact-master migrator preparation to the
|
|
`paperclip-post-merge` runner group. The separate Fleet label is
|
|
`runs-on/fleet=paperclip-post-merge-x64/env=public-ci`. Its 36 reserved slots use
|
|
the same four-vCPU, 16-GiB machines as approved PR jobs. PR capacity is reduced
|
|
to 64; the separately provisioned image capacity is unchanged by this retirement.
|
|
This keeps PR bursts from consuming every post-merge verification slot.
|
|
|
|
Every selector checks the canonical repository name and ID, master ref, and a
|
|
push or manual event. Reusable verification also requires `inputs.ref` to equal
|
|
that event's `github.sha`. The migrator route requires `cloud-migrator` and
|
|
`inputs.source_ref == github.sha`. Branch/tag refs, PR events, arbitrary preview
|
|
sources, and missing or disabled switches use GitHub-hosted runners. If another
|
|
merge lands before a migrator dispatch resolves master, the older source uses
|
|
GitHub-hosted runners too. npm publication always remains GitHub-hosted to keep
|
|
its trusted-publisher identity.
|
|
|
|
Before enabling the switch, deploy the separate Fleet and restrict its GitHub
|
|
runner group to repository ID `1170821064` and these workflows at
|
|
`refs/heads/master`: `cloud-readiness.yml`,
|
|
`release-verify.yml`, `runner-chaos-evals.yml`, and `release.yml`. Do not authorize
|
|
PR-controlled workflow versions. The direct migrator producer always uses
|
|
GitHub-hosted runners and needs no AWS runner-group authorization. PR placement retains its independent pinned
|
|
workflow and six-account author/actor allowlist.
|
|
|
|
Disable the switch and rerun the whole workflow to restore GitHub-hosted
|
|
placement. Assigned jobs keep their original runners. Readiness requirements,
|
|
source checks, and npm integrity checks are unchanged.
|
|
|
|
## Retired AWS cloud build routing
|
|
|
|
`AWS_CLOUD_BUILDS_ENABLED` and the `paperclip-cloud-build` runner group no longer
|
|
route a public image job after this retirement. This source change does not
|
|
delete runner groups, Fleets, credentials, registry images, or cache tags. Review
|
|
shared infrastructure ownership separately before removing those resources.
|
|
|
|
### Typecheck Rust dependency cache
|
|
|
|
Source verification's typecheck job builds the native Runner binary through the
|
|
server's `prepare:runner-vendor` command. It restores and saves compiled Rust
|
|
dependencies only for canonical master pushes that verify the event's exact SHA.
|
|
The `release-typecheck-v2` cache is separate from Runner verification because
|
|
those jobs compile different profiles. The pinned toolchain is selected before
|
|
cache lookup, and the cache action receives the Runner crate through the same
|
|
checkout-independent `$HOME/paperclip-runner-rust` path as the Runner lanes
|
|
(see `RELEASE-AUTOMATION-SETUP.md`). Workspace crates and installed cargo
|
|
binaries are excluded, and all typechecks still execute. A missing or
|
|
invalidated cache triggers compilation.
|
|
|
|
### pnpm dependency store cache
|
|
|
|
The Refresh Lockfile workflow does not cache the pnpm store. Its resolution-only
|
|
command does not download packages and can save an empty default-branch cache
|
|
before full install jobs finish. The PR policy job also leaves store caching off.
|
|
|
|
PR install jobs restore the pnpm store without saving it. They hash the checked-in
|
|
lockfile before downloading the policy job's regenerated lockfile, matching the
|
|
key format used by master install jobs. A same-OS, same-architecture pnpm fallback
|
|
can reuse older package downloads when the exact key is absent. Each job still
|
|
installs with `--frozen-lockfile` against the policy artifact when one exists;
|
|
cache contents do not select dependency versions. A cache miss downloads packages
|
|
normally. New PR-only dependencies may be downloaded again on each PR run until
|
|
master populates a cache that contains them.
|
|
|
|
This avoids storing a full dependency archive under every PR merge ref. Those
|
|
copies competed with the Rust caches for the repository's storage limit. Keep
|
|
master cache writes enabled so trusted post-merge installs refresh shared stores.
|
|
After activating the new trusted workflow pin, verify cache restores and package
|
|
reuse in an allowlisted PR, and verify that no new `node-cache-` entries appear
|
|
under its `refs/pull/<number>/merge` ref. Existing copies can expire normally.
|
|
|
|
The repository cache storage ceiling is managed in GitHub Settings, separately
|
|
from this workflow. Check it with:
|
|
|
|
```sh
|
|
gh api repos/paperclipai/paperclip/actions/cache/storage-limit
|
|
```
|
|
|
|
Increasing the repository limit above 10 GB can require an organization owner to
|
|
raise the maximum in organization Settings → Actions → General first. Repository
|
|
administration access alone cannot override that maximum. Paid cache storage also
|
|
requires a payment method and sufficient Actions Cache Storage budget; see the
|
|
[GitHub cache storage documentation](https://docs.github.com/en/actions/reference/workflows-and-actions/dependency-caching#increasing-cache-size).
|
|
Preserve populated master pnpm and Rust caches when inspecting pressure.
|
|
|
|
After deploying this correction, remove any existing empty default-branch entry
|
|
for the current lockfile key. List cache IDs, branches, and archive sizes first:
|
|
|
|
```sh
|
|
gh api --paginate 'repos/paperclipai/paperclip/actions/caches?ref=refs/heads/master&key=node-cache-Linux-x64-pnpm-&per_page=100' \
|
|
--jq '.actions_caches[] | {id, ref, key, size_in_bytes}'
|
|
```
|
|
|
|
Match the key and upload size against the cache-creation job's logs. The
|
|
September 11 incident was cache ID `7559920987`, a 216-byte archive. This guarded
|
|
command deletes only that observed entry. It leaves a populated replacement or
|
|
an entry on another branch untouched, and does nothing if the old ID is absent:
|
|
|
|
```sh
|
|
bad_cache_id=7559920987
|
|
bad_cache_key=node-cache-Linux-x64-pnpm-c3096ecb02a34aaa9782baaadafcb731510e1dba10dd661618c3a2ee91e58fa5
|
|
entries="$(gh api --paginate --slurp 'repos/paperclipai/paperclip/actions/caches?ref=refs/heads/master&per_page=100')"
|
|
if printf '%s\n' "$entries" | jq -e --argjson id "$bad_cache_id" --arg key "$bad_cache_key" '
|
|
[.[].actions_caches[] | select(.id == $id)] |
|
|
length == 1 and .[0].ref == "refs/heads/master" and
|
|
.[0].key == $key and .[0].size_in_bytes == 216
|
|
' >/dev/null; then
|
|
gh api --method DELETE "repos/paperclipai/paperclip/actions/caches/$bad_cache_id"
|
|
fi
|
|
```
|
|
|
|
A subsequent master install can populate the missing entry. Check the saved
|
|
archive size and package reuse in install logs; a cache hit alone does not prove
|
|
that the entry contains dependencies.
|