code-foundry 1.11.0 → 1.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/CONTRIBUTING.md +7 -6
- package/.github/workflows/cloudflare-delivery.yml +354 -0
- package/.github/workflows/cloudflare-deploy.yml +90 -47
- package/.github/workflows/draft-enforcement_self-ci.yml +3 -4
- package/.github/workflows/opencode-security_self-ci.yml +2 -1
- package/.github/workflows/validation_self-ci.yml +6 -4
- package/AGENTS.md +6 -5
- package/CHANGELOG.md +14 -0
- package/README.md +7 -6
- package/docs/CONFIGURATION.md +17 -9
- package/docs/PERFORMANCE.md +3 -3
- package/docs/README.md +1 -0
- package/docs/WORKFLOWS.md +14 -14
- package/docs/cloudflare-delivery.md +188 -0
- package/docs/fleet-rollouts.md +139 -0
- package/package.json +1 -1
- package/src/commands/cloudflare-delivery.mjs +351 -0
- package/src/commands/doctor.mjs +8 -3
- package/src/commands/fleet.mjs +355 -42
- package/src/commands/sync.mjs +11 -6
- package/src/lib/cloudflare-delivery.mjs +233 -0
- package/src/lib/fleet-manifest.mjs +654 -0
|
@@ -7,6 +7,7 @@ on:
|
|
|
7
7
|
branches: [main, staging]
|
|
8
8
|
types:
|
|
9
9
|
- ready_for_review
|
|
10
|
+
- synchronize
|
|
10
11
|
|
|
11
12
|
# Default every caller job to no repository permissions. Individual jobs grant
|
|
12
13
|
# only the scopes their own validation path consumes.
|
|
@@ -20,9 +21,10 @@ concurrency:
|
|
|
20
21
|
jobs:
|
|
21
22
|
mode:
|
|
22
23
|
name: Mode
|
|
23
|
-
# The mode classifier is only needed for pull requests. Main pushes
|
|
24
|
-
# the dedicated default-branch CodeQL lane below
|
|
25
|
-
|
|
24
|
+
# The mode classifier is only needed for ready pull requests. Main pushes
|
|
25
|
+
# use the dedicated default-branch CodeQL lane below; draft updates do not
|
|
26
|
+
# allocate a validation runner.
|
|
27
|
+
if: vars.CI_BILLING_PAUSED != 'true' && github.event_name == 'pull_request' && github.event.pull_request.draft == false
|
|
26
28
|
runs-on: ubuntu-slim
|
|
27
29
|
timeout-minutes: 10
|
|
28
30
|
permissions:
|
|
@@ -62,7 +64,7 @@ jobs:
|
|
|
62
64
|
validation:
|
|
63
65
|
name: Validation
|
|
64
66
|
needs: mode
|
|
65
|
-
if: vars.CI_BILLING_PAUSED != 'true' && github.event_name == 'pull_request'
|
|
67
|
+
if: vars.CI_BILLING_PAUSED != 'true' && github.event_name == 'pull_request' && github.event.pull_request.draft == false
|
|
66
68
|
# Reusable workflows can only maintain or reduce the caller job's scopes.
|
|
67
69
|
# The audit tier needs security-events: write for CodeQL uploads.
|
|
68
70
|
permissions:
|
package/AGENTS.md
CHANGED
|
@@ -103,13 +103,14 @@ This repository uses the `direct` workflow. Topic pull requests target `main`.
|
|
|
103
103
|
- Open every ordinary pull request as a draft. Use `gh pr create --draft` or
|
|
104
104
|
set `draft: true` in the GitHub API; never create a ready ordinary pull
|
|
105
105
|
request as a shortcut.
|
|
106
|
-
- Keep ordinary pull requests in draft while
|
|
107
|
-
Draft Guard
|
|
108
|
-
|
|
106
|
+
- Keep ordinary pull requests in draft while preparing them. The generated
|
|
107
|
+
Draft Guard converts ready ordinary pull requests to draft when they are
|
|
108
|
+
opened or reopened, and runner-heavy validation starts only after an
|
|
109
109
|
explicit `ready_for_review` transition.
|
|
110
110
|
- Run local validation and finish review preparation before marking an ordinary
|
|
111
|
-
pull request ready.
|
|
112
|
-
the current head
|
|
111
|
+
pull request ready. Ready pull requests stay ready when new commits arrive,
|
|
112
|
+
and validation reruns for the current head; draft updates allocate no
|
|
113
|
+
validation runner until the pull request is ready.
|
|
113
114
|
- This contract is mandatory for every agent scope. Nested `AGENTS.md` files
|
|
114
115
|
may add stricter rules but must not weaken or replace it.
|
|
115
116
|
- Release Please version pull requests are managed by the Code Foundry release
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.13.0](https://github.com/0xPlayerOne/code-foundry/compare/v1.12.0...v1.13.0) (2026-09-09)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **fleet:** add declared inventory and resumable canary rollouts ([#536](https://github.com/0xPlayerOne/code-foundry/issues/536)) ([6aa86d4](https://github.com/0xPlayerOne/code-foundry/commit/6aa86d4cd85cdbd4041c70d8c01d8e351e21fc0b))
|
|
9
|
+
|
|
10
|
+
## [1.12.0](https://github.com/0xPlayerOne/code-foundry/compare/v1.11.0...v1.12.0) (2026-09-09)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
* **cloudflare:** verify candidates before protected version promotion ([#535](https://github.com/0xPlayerOne/code-foundry/issues/535)) ([5dd9afa](https://github.com/0xPlayerOne/code-foundry/commit/5dd9afa8418718823844875b0aedce926b887184))
|
|
16
|
+
|
|
3
17
|
## [1.11.0](https://github.com/0xPlayerOne/code-foundry/compare/v1.10.1...v1.11.0) (2026-09-09)
|
|
4
18
|
|
|
5
19
|
|
package/README.md
CHANGED
|
@@ -76,12 +76,13 @@ The standard workflow triggers are:
|
|
|
76
76
|
|
|
77
77
|
Automated feature/fix and staging-promotion pull requests open as drafts.
|
|
78
78
|
The trusted Draft Guard is a fallback for manually created or reopened ready
|
|
79
|
-
PRs
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
ready
|
|
84
|
-
cancellation control. Scheduled and manually
|
|
79
|
+
PRs: it converts them to drafts without checking out PR code. It verifies the
|
|
80
|
+
event head and update timestamp before changing state, and excludes Release
|
|
81
|
+
Please version PRs whose release workflow owns readiness. Pull-request
|
|
82
|
+
validation runs on the ready-for-review transition and on new commits while a
|
|
83
|
+
PR remains ready; draft updates allocate no validation runner. Converting a PR
|
|
84
|
+
to draft runs only the lightweight cancellation control. Scheduled and manually
|
|
85
|
+
dispatched audits are unaffected.
|
|
85
86
|
|
|
86
87
|
Jobs are language-aware and skip irrelevant setup inside the applicable
|
|
87
88
|
aggregate checks. TypeScript uses Oxlint, Oxfmt, and Bun's native
|
package/docs/CONFIGURATION.md
CHANGED
|
@@ -179,15 +179,23 @@ shards. Do not split a single crate by arbitrary non-Rust directories: use
|
|
|
179
179
|
## Cloudflare Workers deployments
|
|
180
180
|
|
|
181
181
|
Repositories that deploy to Cloudflare Workers can opt into GitHub-native
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
`cloudflare-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
`
|
|
188
|
-
`CLOUDFLARE_ACCOUNT_ID` secrets in the consumer
|
|
189
|
-
|
|
190
|
-
|
|
182
|
+
verified delivery (fixed `Preview`/`Production` environments, candidate
|
|
183
|
+
verification, and version-identity promotion) by adding a caller for the
|
|
184
|
+
runtime's reusable `cloudflare-delivery.yml` workflow. Use the same immutable
|
|
185
|
+
40-character Code Foundry commit SHA for both the reusable workflow ref and
|
|
186
|
+
`runtime-ref`; configure required reviewers and branch restrictions on the
|
|
187
|
+
`Production` environment. The workflow requires the
|
|
188
|
+
`CLOUDFLARE_API_TOKEN` and `CLOUDFLARE_ACCOUNT_ID` secrets in the consumer
|
|
189
|
+
repository. See [Verified Cloudflare delivery](./cloudflare-delivery.md) for
|
|
190
|
+
binding policy, canary, rollback, and evidence requirements.
|
|
191
|
+
|
|
192
|
+
The legacy `cloudflare-deploy.yml` workflow remains available for direct
|
|
193
|
+
(unverified) deployments. It runs `wrangler versions upload` for previews and
|
|
194
|
+
`wrangler deploy` for production, records a GitHub deployment plus status, and
|
|
195
|
+
respects `CI_BILLING_PAUSED`. Its legacy-compatible Wrangler default is `latest`;
|
|
196
|
+
callers should prefer `local` or provide an exact `wrangler-version` for
|
|
197
|
+
reproducibility. Bun consumers may pass `build-script`, `install-working-directory`, and `bun-version`;
|
|
198
|
+
the runtime installs the frozen lockfile and builds the Worker before invoking
|
|
191
199
|
Wrangler. Bun-backed callers invoke Wrangler through `bunx` so OpenNext's
|
|
192
200
|
production delegation resolves the workspace-local `opennextjs-cloudflare`
|
|
193
201
|
binary; callers without `build-script` retain the npm/npx path.
|
package/docs/PERFORMANCE.md
CHANGED
|
@@ -15,9 +15,9 @@ belong to the run that produced them, not the source tree.
|
|
|
15
15
|
| Format, lint, type-check, and build | 15 s | Bound the local CI feedback loop |
|
|
16
16
|
| Runtime dependencies | 0 | Keep the installed CLI dependency-free |
|
|
17
17
|
| Development dependencies | 4 | Prevent unreviewed toolchain growth |
|
|
18
|
-
| Packed artifact |
|
|
19
|
-
| Unpacked artifact |
|
|
20
|
-
| Packed files |
|
|
18
|
+
| Packed artifact | 210 kB | Bound registry transfer and install cost |
|
|
19
|
+
| Unpacked artifact | 800 kB | Bound installed footprint |
|
|
20
|
+
| Packed files | 90 | Detect accidental release contents |
|
|
21
21
|
|
|
22
22
|
The performance workflow disables build-cache reads and writes for this task.
|
|
23
23
|
That makes timing comparisons independent of a warm protected-branch cache and
|
package/docs/README.md
CHANGED
|
@@ -14,6 +14,7 @@ its own names, environments, and deployment details.
|
|
|
14
14
|
- [Caching and remote caching](CACHING.md)
|
|
15
15
|
- [Performance budgets and baselines](PERFORMANCE.md)
|
|
16
16
|
- [Required capabilities and task evidence](required-capabilities.md)
|
|
17
|
+
- [Declarative fleet inventory and staged rollouts](fleet-rollouts.md)
|
|
17
18
|
|
|
18
19
|
## Repository-specific documentation
|
|
19
20
|
|
package/docs/WORKFLOWS.md
CHANGED
|
@@ -15,19 +15,19 @@ pull_request:
|
|
|
15
15
|
# direct topology: branches: [main]
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
The generated validation caller listens for `ready_for_review` and
|
|
19
|
-
`
|
|
20
|
-
validation runner; main pushes run only the default-branch
|
|
21
|
-
full validation remains pull-request-only.
|
|
22
|
-
|
|
23
|
-
`
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
pull
|
|
30
|
-
request
|
|
18
|
+
The generated validation caller listens for `ready_for_review` and
|
|
19
|
+
`synchronize`. Its jobs require the pull request to remain ready, so draft
|
|
20
|
+
updates allocate no validation runner; main pushes run only the default-branch
|
|
21
|
+
CodeQL lane, while full validation remains pull-request-only. A separate
|
|
22
|
+
lightweight Draft Guard runs from the trusted base branch on `opened` and
|
|
23
|
+
`reopened`; it converts ordinary ready pull requests back to draft without
|
|
24
|
+
checking out pull-request code. It rechecks the current head and update
|
|
25
|
+
timestamp before mutating state, so a stale event cannot undo a later draft or
|
|
26
|
+
ready transition. Release Please version heads are excluded because the
|
|
27
|
+
release workflow owns their state. A separate draft-control caller listens for
|
|
28
|
+
`converted_to_draft` and cancels queued or running pull-request workflows.
|
|
29
|
+
Marking a pull request ready starts validation, and each new commit on a ready
|
|
30
|
+
pull request starts it again for the current head.
|
|
31
31
|
|
|
32
32
|
The separate `validation-audit.yml` caller is pinned to the configured released
|
|
33
33
|
runtime and handles scheduled and manual audits:
|
|
@@ -108,7 +108,7 @@ opt in or out without a code change.
|
|
|
108
108
|
| Security | Profile, audits, and public-only Dependency Review |
|
|
109
109
|
| CodeQL | GitHub-native code scanning, kept separate from CI |
|
|
110
110
|
| Draft PR | Create/update development pull requests |
|
|
111
|
-
| Draft Guard | Keep ordinary PRs draft until `ready_for_review`
|
|
111
|
+
| Draft Guard | Keep opened/reopened ordinary PRs draft until `ready_for_review` |
|
|
112
112
|
| Release PR | Promote `staging` into `main` (staging-release topology only) |
|
|
113
113
|
| Release | Release Please, GitHub release, and optional npm publication |
|
|
114
114
|
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
# Verified Cloudflare delivery
|
|
2
|
+
|
|
3
|
+
The opt-in `cloudflare-delivery.yml` workflow builds and uploads a candidate,
|
|
4
|
+
validates its actual version bindings, runs an HTTP smoke probe and the required
|
|
5
|
+
repository-owned verification command, then promotes **that version ID** after
|
|
6
|
+
GitHub environment approval. Production promotion uses the Cloudflare deployment
|
|
7
|
+
API and never rebuilds the application. The existing `cloudflare-deploy.yml`
|
|
8
|
+
remains available for direct deployments and initial provisioning.
|
|
9
|
+
|
|
10
|
+
## Adoption
|
|
11
|
+
|
|
12
|
+
Call the new reusable workflow using an immutable, reviewed 40-character Code
|
|
13
|
+
Foundry commit SHA and pass the same `runtime-ref`. Required inputs are
|
|
14
|
+
`worker-name`, `artifact-path`, and `verify-command`.
|
|
15
|
+
|
|
16
|
+
```yaml
|
|
17
|
+
jobs:
|
|
18
|
+
delivery:
|
|
19
|
+
# Replace REVIEWED_SHA with the same reviewed 40-character SHA in both places.
|
|
20
|
+
uses: 0xPlayerOne/code-foundry/.github/workflows/cloudflare-delivery.yml@REVIEWED_SHA
|
|
21
|
+
permissions:
|
|
22
|
+
contents: read
|
|
23
|
+
deployments: write
|
|
24
|
+
with:
|
|
25
|
+
runtime-ref: REVIEWED_SHA
|
|
26
|
+
mode: production
|
|
27
|
+
worker-name: company-site
|
|
28
|
+
artifact-path: dist
|
|
29
|
+
verify-command: '["bun", "run", "test:deployed"]'
|
|
30
|
+
production-url: https://example.com
|
|
31
|
+
smoke-path: /health
|
|
32
|
+
canary-percentage: 10
|
|
33
|
+
canary-verify-command: '["bun", "run", "test:canary"]'
|
|
34
|
+
secrets:
|
|
35
|
+
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
|
36
|
+
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
`artifact-path` is relative to `working-directory`; `install-working-directory`
|
|
40
|
+
selects the lockfile root. The selected output tree is hashed before and after
|
|
41
|
+
upload; changes during upload fail. Include all built code/assets in that tree
|
|
42
|
+
and disable duplicate custom build steps. This digest identifies the declared
|
|
43
|
+
local build tree, not a Cloudflare-signed digest of every uploaded configuration
|
|
44
|
+
field. The Worker version ID is the authoritative identity for promotion.
|
|
45
|
+
|
|
46
|
+
Wrangler defaults to the installed, lockfile-resolved version. Explicit overrides
|
|
47
|
+
must be exact versions, never `latest`, floating majors, or semver ranges. Pin a
|
|
48
|
+
Wrangler version supporting `WRANGLER_OUTPUT_FILE_PATH` and version-1
|
|
49
|
+
`version-upload` records. Missing preview URLs and output-schema mismatches fail.
|
|
50
|
+
Bun remains the installation path, consistent with the existing deploy workflow.
|
|
51
|
+
|
|
52
|
+
The repository verification command receives `BASE_URL` and
|
|
53
|
+
`FOUNDRY_DEPLOYMENT_PHASE` (`candidate`, `canary`, or `production`). It must check
|
|
54
|
+
critical journeys, redirects, assets, and application-specific behavior. The
|
|
55
|
+
built-in smoke probe requires a successful 2xx response and does not follow
|
|
56
|
+
redirects. Deploy credentials are not supplied to verification steps and are
|
|
57
|
+
removed from the verification child environment as defense in depth. Install any
|
|
58
|
+
browser binaries required by your verification command explicitly.
|
|
59
|
+
|
|
60
|
+
When `canary-percentage` is below 100, `canary-verify-command` is required and
|
|
61
|
+
must prove that the live request served the candidate rather than the baseline.
|
|
62
|
+
It receives `FOUNDRY_EXPECTED_VERSION_ID`, `FOUNDRY_DEPLOYMENT_ID`, and
|
|
63
|
+
`FOUNDRY_CANARY_PERCENTAGE`; use a version-aware response/header or an equivalent
|
|
64
|
+
application check. A command that only observes a successful production URL is
|
|
65
|
+
not sufficient.
|
|
66
|
+
|
|
67
|
+
## Approvals, ordering, and evidence
|
|
68
|
+
|
|
69
|
+
Create and protect the fixed `Preview` and `Production` GitHub environments
|
|
70
|
+
before adoption. The workflow references them at the **job** level; naming an
|
|
71
|
+
environment does not itself configure reviewers or branch restrictions. Configure
|
|
72
|
+
required reviewers and branch restrictions on `Production` separately. Production
|
|
73
|
+
execution requires the current default-branch commit and
|
|
74
|
+
rechecks freshness after approval and before final promotion. Fork PRs and
|
|
75
|
+
`pull_request_target` execution are excluded.
|
|
76
|
+
|
|
77
|
+
Per-repository/Worker/mode concurrency never cancels a running promotion. GitHub
|
|
78
|
+
concurrency is not a FIFO queue; stale-source rejection is still necessary.
|
|
79
|
+
Other deployment systems and dashboard edits are outside this lock. The helper
|
|
80
|
+
also checks that its deployment has not been replaced before a subsequent
|
|
81
|
+
promotion or rollback, but the Cloudflare API check/write is not an atomic CAS.
|
|
82
|
+
Migrate one application to one deployment owner; do not leave competing legacy
|
|
83
|
+
and new production workflows active.
|
|
84
|
+
|
|
85
|
+
Outputs include preview URL, exact version ID, source SHA, declared build-tree
|
|
86
|
+
SHA-256 digest, Cloudflare deployment ID, and GitHub application deployment ID.
|
|
87
|
+
Explicit application deployment records receive in-progress and success/failure
|
|
88
|
+
statuses, in addition to GitHub's environment-job records. Sanitized candidate and
|
|
89
|
+
production JSON evidence is uploaded even on failure. Binding values, API bodies,
|
|
90
|
+
and credentials are not copied into those reports. Forced runner termination may
|
|
91
|
+
prevent final status steps; the GitHub job still reflects cancellation/failure.
|
|
92
|
+
|
|
93
|
+
## Stateful resources and isolation
|
|
94
|
+
|
|
95
|
+
Without a policy file, non-resource bindings (for example strings, secrets, and
|
|
96
|
+
static assets) are allowed; resource/service bindings fail closed. The uploaded
|
|
97
|
+
version's actual bindings are inspected through the Cloudflare API. Durable
|
|
98
|
+
Object bindings or exports are rejected: use a repository-specific migration and
|
|
99
|
+
preview workflow instead of pretending version preview supports that topology.
|
|
100
|
+
|
|
101
|
+
A reviewed read-only policy can allow smoke testing a candidate that shares
|
|
102
|
+
production resources:
|
|
103
|
+
|
|
104
|
+
```json
|
|
105
|
+
{
|
|
106
|
+
"schemaVersion": 1,
|
|
107
|
+
"readOnlyBindings": [{ "name": "DB", "type": "d1" }],
|
|
108
|
+
"rollbackSafe": false
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Pass its relative path as `binding-policy-file`. This declaration is **not a
|
|
113
|
+
sandbox**: the repository owner must ensure its test routes cannot mutate shared
|
|
114
|
+
data. A version preview does not automatically create isolated KV, R2, D1, or
|
|
115
|
+
service resources, and a GET route can still have side effects.
|
|
116
|
+
|
|
117
|
+
For separately provisioned preview Workers, `isolatedBindings` entries can compare
|
|
118
|
+
the actual binding's resource identifiers with expected preview identifiers and
|
|
119
|
+
assert that they differ from declared production identifiers:
|
|
120
|
+
|
|
121
|
+
```json
|
|
122
|
+
{
|
|
123
|
+
"schemaVersion": 1,
|
|
124
|
+
"isolatedBindings": [
|
|
125
|
+
{
|
|
126
|
+
"name": "DB",
|
|
127
|
+
"type": "d1",
|
|
128
|
+
"expected": { "id": "preview-database-id" },
|
|
129
|
+
"production": { "id": "production-database-id" }
|
|
130
|
+
}
|
|
131
|
+
]
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Use the field names returned for that binding type by the Version API. Resource
|
|
136
|
+
provisioning and the correctness of production-identifier declarations remain
|
|
137
|
+
repository-owned. Isolated preview bindings are rejected in production mode to
|
|
138
|
+
prevent accidentally promoting staging resources. A version from a different
|
|
139
|
+
Worker cannot be promoted across Workers; production mode uploads and tests its
|
|
140
|
+
own candidate on the production Worker with reviewed read-only tests.
|
|
141
|
+
|
|
142
|
+
## Canary and rollback policy
|
|
143
|
+
|
|
144
|
+
A percentage below 100 first routes that share to the candidate, verifies it,
|
|
145
|
+
and then promotes the same version to 100 and verifies again. A canary requires
|
|
146
|
+
one prior baseline serving 100% and the explicit `canary-verify-command` above.
|
|
147
|
+
A single load-balanced HTTP request may hit the old version; the command must
|
|
148
|
+
observe the expected version ID. Set `canary-percentage: 100` when that
|
|
149
|
+
version-aware observability is not configured.
|
|
150
|
+
|
|
151
|
+
Automatic rollback is off. Enabling `auto-rollback` also requires an explicit
|
|
152
|
+
`rollbackSafe: true` policy and both current and prior versions to be free of
|
|
153
|
+
stateful bindings/DO exports. The policy must additionally account for external
|
|
154
|
+
side effects that binding inspection cannot detect. Rollback restores the exact
|
|
155
|
+
previous traffic split only when this run's deployment is still current. Failure
|
|
156
|
+
remains a failed deployment even after rollback. Resource data, migrations,
|
|
157
|
+
external API side effects, routes, and non-versioned settings are never rewound.
|
|
158
|
+
The evidence file records prior versions for manual recovery when automation is
|
|
159
|
+
unsafe or unavailable. Recovery itself must be verified operationally.
|
|
160
|
+
|
|
161
|
+
This workflow targets already-provisioned Workers with version previews enabled.
|
|
162
|
+
Manage initial Worker/route/trigger setup and non-versioned settings separately;
|
|
163
|
+
the deployment API intentionally changes version routing only.
|
|
164
|
+
|
|
165
|
+
## Legacy workflow hardening
|
|
166
|
+
|
|
167
|
+
`cloudflare-deploy.yml` now uses real job environments, non-cancelling concurrency,
|
|
168
|
+
structured Wrangler output, exact/local Wrangler selection, reusable outputs, and
|
|
169
|
+
in-progress/failure deployment records. Its legacy-compatible default remains
|
|
170
|
+
`latest`; callers should prefer `local` or an exact version for reproducibility. A
|
|
171
|
+
production URL can be supplied with `deployment-url` when API output contains only
|
|
172
|
+
route patterns. It is still a **direct, unverified deployment**; adopt
|
|
173
|
+
`cloudflare-delivery.yml` for candidate verification and guarded promotion.
|
|
174
|
+
|
|
175
|
+
## References and testing
|
|
176
|
+
|
|
177
|
+
The implementation follows Cloudflare's structured Wrangler output and version
|
|
178
|
+
routing APIs:
|
|
179
|
+
|
|
180
|
+
- https://developers.cloudflare.com/workers/wrangler/system-environment-variables/
|
|
181
|
+
- https://developers.cloudflare.com/workers/versions-and-deployments/
|
|
182
|
+
- https://developers.cloudflare.com/api/resources/workers/subresources/scripts/subresources/versions/methods/get/
|
|
183
|
+
- https://developers.cloudflare.com/api/resources/workers/subresources/scripts/subresources/deployments/methods/create/
|
|
184
|
+
|
|
185
|
+
Run `node --test test/cloudflare-delivery.test.mjs`. Tests use deterministic API
|
|
186
|
+
responses and never deploy a Worker. Before production rollout, run the new
|
|
187
|
+
workflow against a disposable Worker and protected test environments, including
|
|
188
|
+
smoke failure and rollback scenarios.
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# Declarative fleet inventory and staged rollouts
|
|
2
|
+
|
|
3
|
+
Place `code-foundry-fleet.json` in the directory passed to `--root`. Its presence
|
|
4
|
+
opts that fleet into inventory-based discovery and controlled upgrades, without
|
|
5
|
+
changing legacy directory discovery for existing users.
|
|
6
|
+
|
|
7
|
+
```json
|
|
8
|
+
{
|
|
9
|
+
"schemaVersion": 1,
|
|
10
|
+
"cohorts": ["canary", "applications"],
|
|
11
|
+
"repositories": [
|
|
12
|
+
{
|
|
13
|
+
"repository": "owner/package-canary",
|
|
14
|
+
"path": "packages/package-canary",
|
|
15
|
+
"cohort": "canary",
|
|
16
|
+
"profile": "published-package",
|
|
17
|
+
"expected": { "git_workflow": "direct" },
|
|
18
|
+
"requiredCapabilities": ["unit", "performance"],
|
|
19
|
+
"validation": [
|
|
20
|
+
["bun", "install", "--frozen-lockfile"],
|
|
21
|
+
["bun", "run", "test:unit"],
|
|
22
|
+
["bun", "run", "test:consumer"],
|
|
23
|
+
["bun", "run", "performance:check"]
|
|
24
|
+
],
|
|
25
|
+
"requiredChecks": ["Validation / Gate"]
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"repository": "owner/application",
|
|
29
|
+
"path": "applications/application",
|
|
30
|
+
"cohort": "applications",
|
|
31
|
+
"validation": [
|
|
32
|
+
["bun", "install", "--frozen-lockfile"],
|
|
33
|
+
["bun", "run", "type-check"],
|
|
34
|
+
["bun", "run", "test:unit"]
|
|
35
|
+
],
|
|
36
|
+
"requiredChecks": ["Validation / Gate"]
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Repository names in the example are placeholders. Populate the actual fleet
|
|
43
|
+
before use. Paths are relative to the manifest, may be arbitrarily nested, and
|
|
44
|
+
must not escape through `..`, absolute paths, or symlinks. Missing checkouts and
|
|
45
|
+
origin mismatches remain visible as blocked inventory entries rather than silently
|
|
46
|
+
disappearing. There is no automatic clone or repository-settings mutation.
|
|
47
|
+
|
|
48
|
+
`profile` is a descriptive inventory annotation; it does not install tools or
|
|
49
|
+
activate a quality profile. `expected` maps scalar `.github/code-foundry.yml` keys
|
|
50
|
+
to desired values; `requiredCapabilities` audits declarations in that same file.
|
|
51
|
+
The runtime-upgrade operation does not silently author missing capability policy.
|
|
52
|
+
Adopt those requirements in consumer repositories before requiring them here.
|
|
53
|
+
|
|
54
|
+
## Commands
|
|
55
|
+
|
|
56
|
+
```sh
|
|
57
|
+
code-foundry fleet status --root /path/to/fleet
|
|
58
|
+
code-foundry fleet upgrade --root /path/to/fleet --dry-run
|
|
59
|
+
code-foundry fleet upgrade --root /path/to/fleet --create-pr
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Run from the intended released Code Foundry installation/checkout. The existing
|
|
63
|
+
source-version guard still rejects mismatched `--version` requests. Manifest mode
|
|
64
|
+
requires `--create-pr` or `--dry-run` and never syncs original checkouts in place.
|
|
65
|
+
`--force` does not bypass dirty-tree safety in manifest mode. Dry-run reports
|
|
66
|
+
inventory, target version, and configuration drift without network calls, running
|
|
67
|
+
consumer commands, or modifying files. Status likewise audits local facts; it does
|
|
68
|
+
not pretend to verify remote branch protection or environment settings.
|
|
69
|
+
|
|
70
|
+
The first incomplete cohort is the only cohort allowed to create PRs. All
|
|
71
|
+
non-excepted members of each earlier cohort must have a matching managed upgrade
|
|
72
|
+
PR that is merged, successful explicitly named required checks on its head SHA,
|
|
73
|
+
no still-pending/failed checks, and the target runtime/configuration still present
|
|
74
|
+
on its current base branch. Neutral/skipped required checks do not qualify.
|
|
75
|
+
Unknown, inaccessible, closed-without-merge, stale, or failed evidence does not
|
|
76
|
+
unlock subsequent cohorts. One local validation failure stops remaining work.
|
|
77
|
+
|
|
78
|
+
Each repository must supply explicit validation argv arrays. Include locked
|
|
79
|
+
installation, application checks, and genuine consumer compatibility tests where
|
|
80
|
+
relevant. No shell splitting is used. Commands run in an isolated detached
|
|
81
|
+
worktree, have bounded execution time, and must not rewrite the candidate source.
|
|
82
|
+
Validation is not a security sandbox: commands run as the invoking user with its
|
|
83
|
+
inherited environment and network access. Treat the manifest and every validation
|
|
84
|
+
command as trusted code; do not use this feature with unreviewed manifests or
|
|
85
|
+
credentials that the checks should not access.
|
|
86
|
+
Only files changed by Code Foundry sync are staged; generated test evidence and
|
|
87
|
+
other untracked files are not swept into the commit. A commit-hook change to the
|
|
88
|
+
validated Git tree is rejected before publishing.
|
|
89
|
+
|
|
90
|
+
This implementation does not create an automatic scheduler, mark PRs ready,
|
|
91
|
+
merge PRs, lower checks, or bypass review. After reviewing and validating canaries,
|
|
92
|
+
merge their PRs normally and run the fleet command again to advance the cohort.
|
|
93
|
+
A repository already at the target version with no managed PR does not establish
|
|
94
|
+
canary evidence; choose a real upgrade canary rather than treating an empty diff
|
|
95
|
+
as successful rollout validation.
|
|
96
|
+
|
|
97
|
+
## Resuming and intentional exceptions
|
|
98
|
+
|
|
99
|
+
The target version and complete repository policy produce a deterministic branch
|
|
100
|
+
and PR marker. Repeated runs return an existing matching open PR instead of
|
|
101
|
+
creating duplicates. If push succeeded but PR creation failed, the next run
|
|
102
|
+
recognizes the managed commit and recorded tree identity, reruns consumer
|
|
103
|
+
validation, and creates the missing **draft** PR without force-pushing. Unknown
|
|
104
|
+
branches or commits with mismatched tree markers are preserved and blocked for
|
|
105
|
+
manual review. Local managed refs preserve committed work after a failed push.
|
|
106
|
+
The marker is an ownership/recovery guard, not a cryptographic signature.
|
|
107
|
+
|
|
108
|
+
PR creation is draft-first in both manifest and legacy discovery modes. A PR that
|
|
109
|
+
a human has already made ready is not silently converted back or modified.
|
|
110
|
+
|
|
111
|
+
An entry may include a reviewed time-limited exception:
|
|
112
|
+
|
|
113
|
+
```json
|
|
114
|
+
{ "exception": { "reason": "Pending consumer compatibility work", "expires": "2026-10-01" } }
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Exceptions appear explicitly in inventory/rollout output. Expired/invalid dates
|
|
118
|
+
fail parsing. The command's existing `--exclude` flag is also honored. Excluding
|
|
119
|
+
all canaries never satisfies a canary gate or unlocks later cohorts. Update the
|
|
120
|
+
manifest deliberately when cohort membership or compatibility policy changes.
|
|
121
|
+
|
|
122
|
+
## Evidence and tests
|
|
123
|
+
|
|
124
|
+
Upgrade output is schema-versioned JSON with target version, aggregate status,
|
|
125
|
+
per-repository cohort/status, PR link, and local validation command exit statuses.
|
|
126
|
+
Failed command output is not copied into reports, avoiding accidental credentials
|
|
127
|
+
in logs; reproduce the declared command locally for full debugging output. A
|
|
128
|
+
failed rollout returns a nonzero exit status. Pending PRs are not failures and do
|
|
129
|
+
not grant permission to advance a cohort. Worktree cleanup failures preserve the
|
|
130
|
+
isolated path and report it rather than deleting unknown paths.
|
|
131
|
+
|
|
132
|
+
`node --test test/fleet-manifest.test.mjs` includes actual local Git repositories,
|
|
133
|
+
bare remotes, isolated worktrees, validation failure, orphan-branch recovery,
|
|
134
|
+
clean-original preservation, and canary advancement. Only GitHub responses are
|
|
135
|
+
fixture-backed; no real fleet repositories or remote PRs are modified by tests.
|
|
136
|
+
|
|
137
|
+
GitHub CLI contracts:
|
|
138
|
+
https://cli.github.com/manual/gh_pr_list
|
|
139
|
+
https://cli.github.com/manual/gh_pr_create
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "code-foundry",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.13.0",
|
|
4
4
|
"description": "A fast, language-aware repository factory for agent-ready workflows, testing, security, and release automation.",
|
|
5
5
|
"homepage": "https://github.com/0xPlayerOne/code-foundry#readme",
|
|
6
6
|
"bugs": {
|