@decocms/start 2.30.1 → 3.0.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/.agents/skills/deco-to-tanstack-migration/references/worker-cloudflare.md +90 -63
- package/.cursor/rules/migration-tooling-policy.mdc +41 -28
- package/.github/workflows/deploy.yml +89 -70
- package/.github/workflows/preview.yml +137 -79
- package/.github/workflows/sync-secrets.yml +61 -70
- package/CODEOWNERS +6 -8
- package/MIGRATION_TOOLING_PLAN.md +14 -9
- package/deploy/README.md +100 -90
- package/deploy/wrangler-template.jsonc +22 -4
- package/package.json +1 -1
- package/scripts/deploy/build-wrangler-config.mjs +10 -12
- package/scripts/deploy/site-registry.mjs +52 -99
- package/scripts/deploy/wrangler-wrapper.mjs +22 -30
- package/scripts/migrate/phase-scaffold.ts +6 -6
- package/scripts/migrate/phase-verify.ts +2 -2
- package/scripts/migrate/templates/github-workflows.ts +86 -25
- package/deploy/sites/als-tanstack.jsonc +0 -7
- package/deploy/sites/americanas-tanstack.jsonc +0 -4
- package/deploy/sites/baggagio-tanstack.jsonc +0 -4
- package/deploy/sites/casaevideo-storefront.jsonc +0 -11
- package/deploy/sites/lebiscuit-tanstack.jsonc +0 -19
- package/deploy/sites/miess-01-tanstack.jsonc +0 -8
- package/scripts/deploy/resolve-site.mjs +0 -58
|
@@ -51,10 +51,10 @@ export function scaffold(ctx: MigrationContext): void {
|
|
|
51
51
|
logPhase("Scaffold");
|
|
52
52
|
|
|
53
53
|
// Root config files. wrangler.jsonc is INTENTIONALLY not generated --
|
|
54
|
-
// per D6, the canonical wrangler config lives in decocms/deco-start under
|
|
55
|
-
// deploy/wrangler-template.jsonc
|
|
56
|
-
//
|
|
57
|
-
//
|
|
54
|
+
// per D6.2, the canonical wrangler config lives in decocms/deco-start under
|
|
55
|
+
// deploy/wrangler-template.jsonc; the file is materialized locally by
|
|
56
|
+
// `deco-wrangler gen` and gitignored. Worker name = storefront repo basename
|
|
57
|
+
// by convention; there is no per-site registry.
|
|
58
58
|
writeFile(ctx, "package.json", generatePackageJson(ctx));
|
|
59
59
|
writeFile(ctx, "tsconfig.json", generateTsconfig());
|
|
60
60
|
writeFile(ctx, "vite.config.ts", generateViteConfig(ctx));
|
|
@@ -216,8 +216,8 @@ dist/
|
|
|
216
216
|
# Cloudflare Workers
|
|
217
217
|
.wrangler/
|
|
218
218
|
.dev.vars
|
|
219
|
-
# Generated by \`deco-wrangler\` from @decocms/start's
|
|
220
|
-
#
|
|
219
|
+
# Generated by \`deco-wrangler\` from @decocms/start's wrangler template.
|
|
220
|
+
# Worker name is derived from the git remote / package.json by convention.
|
|
221
221
|
wrangler.jsonc
|
|
222
222
|
|
|
223
223
|
# TanStack Router (auto-generated)
|
|
@@ -13,8 +13,8 @@ const REQUIRED_FILES = [
|
|
|
13
13
|
"package.json",
|
|
14
14
|
"tsconfig.json",
|
|
15
15
|
"vite.config.ts",
|
|
16
|
-
// wrangler.jsonc is INTENTIONALLY absent -- D6: it
|
|
17
|
-
//
|
|
16
|
+
// wrangler.jsonc is INTENTIONALLY absent -- D6.2: it's generated from
|
|
17
|
+
// decocms/deco-start's deploy/wrangler-template.jsonc by `deco-wrangler gen`.
|
|
18
18
|
".github/workflows/deploy.yml",
|
|
19
19
|
".github/workflows/preview.yml",
|
|
20
20
|
".github/workflows/regen-blocks.yml",
|
|
@@ -1,33 +1,51 @@
|
|
|
1
|
-
// Caller workflow stubs for new sites. Each stub
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
1
|
+
// Caller workflow stubs for new sites (v3, D6.2 architecture). Each stub mints
|
|
2
|
+
// a short-lived `decocms-deployer` GitHub App installation token and uses it
|
|
3
|
+
// to call the corresponding reusable workflow under
|
|
4
|
+
// `decocms/deco-start/.github/workflows/`. The customer repo holds no deploy
|
|
5
|
+
// logic of its own AND no Cloudflare credentials -- only the App ID + private
|
|
6
|
+
// key as deco-sites org-level secrets (`DECOCMS_DEPLOYER_APP_ID` and
|
|
7
|
+
// `DECOCMS_DEPLOYER_APP_PRIVATE_KEY`).
|
|
8
|
+
//
|
|
9
|
+
// See `deploy/README.md` and the migration-tooling-policy rule (D6.2) for the
|
|
10
|
+
// full trust model.
|
|
6
11
|
|
|
7
12
|
const DEPLOY_YML = `name: Deploy
|
|
8
13
|
|
|
9
|
-
#
|
|
14
|
+
# Triggers decocms/deco-start's central deploy workflow via App-token.
|
|
10
15
|
|
|
11
16
|
on:
|
|
12
17
|
push:
|
|
13
18
|
branches: [main]
|
|
14
19
|
|
|
15
20
|
permissions:
|
|
16
|
-
contents:
|
|
21
|
+
contents: read
|
|
17
22
|
|
|
18
23
|
jobs:
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
24
|
+
trigger:
|
|
25
|
+
runs-on: ubuntu-latest
|
|
26
|
+
steps:
|
|
27
|
+
- uses: actions/create-github-app-token@v1
|
|
28
|
+
id: app-token
|
|
29
|
+
with:
|
|
30
|
+
app-id: \${{ secrets.DECOCMS_DEPLOYER_APP_ID }}
|
|
31
|
+
private-key: \${{ secrets.DECOCMS_DEPLOYER_APP_PRIVATE_KEY }}
|
|
32
|
+
owner: decocms
|
|
33
|
+
repositories: deco-start
|
|
34
|
+
- env:
|
|
35
|
+
GH_TOKEN: \${{ steps.app-token.outputs.token }}
|
|
36
|
+
run: |
|
|
37
|
+
gh workflow run deploy.yml \\
|
|
38
|
+
--repo decocms/deco-start \\
|
|
39
|
+
--ref v3 \\
|
|
40
|
+
-f site_owner=\${GITHUB_REPOSITORY%%/*} \\
|
|
41
|
+
-f site_name=\${GITHUB_REPOSITORY##*/}
|
|
22
42
|
`;
|
|
23
43
|
|
|
24
44
|
const PREVIEW_YML = `name: Preview
|
|
25
45
|
|
|
26
|
-
#
|
|
46
|
+
# Triggers decocms/deco-start's central preview workflow via App-token.
|
|
27
47
|
|
|
28
48
|
on:
|
|
29
|
-
repository_dispatch:
|
|
30
|
-
types: [preview-deploy]
|
|
31
49
|
pull_request:
|
|
32
50
|
types: [opened, synchronize, reopened]
|
|
33
51
|
push:
|
|
@@ -35,18 +53,46 @@ on:
|
|
|
35
53
|
|
|
36
54
|
permissions:
|
|
37
55
|
contents: read
|
|
38
|
-
pull-requests: write
|
|
39
|
-
statuses: write
|
|
40
56
|
|
|
41
57
|
jobs:
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
58
|
+
trigger:
|
|
59
|
+
runs-on: ubuntu-latest
|
|
60
|
+
steps:
|
|
61
|
+
- id: meta
|
|
62
|
+
run: |
|
|
63
|
+
if [ "\${{ github.event_name }}" = "pull_request" ]; then
|
|
64
|
+
echo "alias=pr-\${{ github.event.pull_request.number }}" >> "$GITHUB_OUTPUT"
|
|
65
|
+
echo "sha=\${{ github.event.pull_request.head.sha }}" >> "$GITHUB_OUTPUT"
|
|
66
|
+
else
|
|
67
|
+
REF="\${GITHUB_REF#refs/heads/env/}"
|
|
68
|
+
echo "alias=$(echo "$REF" | sed 's|[^a-z0-9-]|-|g')" >> "$GITHUB_OUTPUT"
|
|
69
|
+
echo "sha=\${{ github.sha }}" >> "$GITHUB_OUTPUT"
|
|
70
|
+
fi
|
|
71
|
+
- uses: actions/create-github-app-token@v1
|
|
72
|
+
id: app-token
|
|
73
|
+
with:
|
|
74
|
+
app-id: \${{ secrets.DECOCMS_DEPLOYER_APP_ID }}
|
|
75
|
+
private-key: \${{ secrets.DECOCMS_DEPLOYER_APP_PRIVATE_KEY }}
|
|
76
|
+
owner: decocms
|
|
77
|
+
repositories: deco-start
|
|
78
|
+
- env:
|
|
79
|
+
GH_TOKEN: \${{ steps.app-token.outputs.token }}
|
|
80
|
+
run: |
|
|
81
|
+
gh workflow run preview.yml \\
|
|
82
|
+
--repo decocms/deco-start \\
|
|
83
|
+
--ref v3 \\
|
|
84
|
+
-f site_owner=\${GITHUB_REPOSITORY%%/*} \\
|
|
85
|
+
-f site_name=\${GITHUB_REPOSITORY##*/} \\
|
|
86
|
+
-f site_sha=\${{ steps.meta.outputs.sha }} \\
|
|
87
|
+
-f alias=\${{ steps.meta.outputs.alias }} \\
|
|
88
|
+
-f pr_number=\${{ github.event.pull_request.number || '' }}
|
|
45
89
|
`;
|
|
46
90
|
|
|
47
91
|
const REGEN_BLOCKS_YML = `name: Regenerate blocks.gen.json
|
|
48
92
|
|
|
49
93
|
# Thin caller for decocms/deco-start's central regen-blocks workflow.
|
|
94
|
+
# This one stays as workflow_call: it runs in the caller's runner context
|
|
95
|
+
# (writes back to the storefront repo) and needs no Cloudflare credentials.
|
|
50
96
|
|
|
51
97
|
on:
|
|
52
98
|
push:
|
|
@@ -59,13 +105,15 @@ permissions:
|
|
|
59
105
|
|
|
60
106
|
jobs:
|
|
61
107
|
regen:
|
|
62
|
-
uses: decocms/deco-start/.github/workflows/regen-blocks.yml@
|
|
108
|
+
uses: decocms/deco-start/.github/workflows/regen-blocks.yml@v3
|
|
63
109
|
secrets: inherit
|
|
64
110
|
`;
|
|
65
111
|
|
|
66
112
|
const SYNC_SECRETS_YML = `name: Sync worker secrets
|
|
67
113
|
|
|
68
|
-
#
|
|
114
|
+
# Triggers decocms/deco-start's central sync-secrets workflow via App-token.
|
|
115
|
+
# The actual SECRET_* values live in deco-start's '\${repo-basename}-secrets'
|
|
116
|
+
# environment, NOT in this repo. See deco-start's deploy/README.md.
|
|
69
117
|
|
|
70
118
|
on:
|
|
71
119
|
workflow_dispatch:
|
|
@@ -81,11 +129,24 @@ permissions:
|
|
|
81
129
|
contents: read
|
|
82
130
|
|
|
83
131
|
jobs:
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
132
|
+
trigger:
|
|
133
|
+
runs-on: ubuntu-latest
|
|
134
|
+
steps:
|
|
135
|
+
- uses: actions/create-github-app-token@v1
|
|
136
|
+
id: app-token
|
|
137
|
+
with:
|
|
138
|
+
app-id: \${{ secrets.DECOCMS_DEPLOYER_APP_ID }}
|
|
139
|
+
private-key: \${{ secrets.DECOCMS_DEPLOYER_APP_PRIVATE_KEY }}
|
|
140
|
+
owner: decocms
|
|
141
|
+
repositories: deco-start
|
|
142
|
+
- env:
|
|
143
|
+
GH_TOKEN: \${{ steps.app-token.outputs.token }}
|
|
144
|
+
run: |
|
|
145
|
+
gh workflow run sync-secrets.yml \\
|
|
146
|
+
--repo decocms/deco-start \\
|
|
147
|
+
--ref v3 \\
|
|
148
|
+
-f site_name=\${GITHUB_REPOSITORY##*/} \\
|
|
149
|
+
-f mode=\${{ inputs.mode }}
|
|
89
150
|
`;
|
|
90
151
|
|
|
91
152
|
export function generateGithubWorkflows(): Record<string, string> {
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
// Per-site overrides for `als-tanstack` (immutable repo->worker binding).
|
|
2
|
-
// Renaming `worker_name` is a breaking change: it points the next deploy at a
|
|
3
|
-
// different Cloudflare worker. Only the platform team can change this file
|
|
4
|
-
// (CODEOWNERS-protected).
|
|
5
|
-
{
|
|
6
|
-
"worker_name": "als-tanstack"
|
|
7
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
// Per-site overrides for `casaevideo-storefront`.
|
|
2
|
-
//
|
|
3
|
-
// NOTE: `kv_namespaces[].id` is shared with `lebiscuit-tanstack`. Verify this
|
|
4
|
-
// is intentional before promoting this registry to v1. R4 in the central-deploy
|
|
5
|
-
// plan adds a CI check that flags shared KV ids as a copy-paste smell.
|
|
6
|
-
{
|
|
7
|
-
"worker_name": "casaevideo-tanstack",
|
|
8
|
-
"kv_namespaces": [
|
|
9
|
-
{ "binding": "SITES_KV", "id": "ad0b74fc4d9341c9af9149c4ab85132f" }
|
|
10
|
-
]
|
|
11
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
// Per-site overrides for `lebiscuit-tanstack`.
|
|
2
|
-
//
|
|
3
|
-
// NOTE: `kv_namespaces[].id` is shared with `casaevideo-storefront`. See the
|
|
4
|
-
// note in casaevideo's site file. R4 will add CI validation for this.
|
|
5
|
-
//
|
|
6
|
-
// `version_metadata` and `analytics_engine_datasets` are consumed by
|
|
7
|
-
// @decocms/start's `instrumentWorker`:
|
|
8
|
-
// - version_metadata populates `service.version` on the OTel resource.
|
|
9
|
-
// - analytics_engine_datasets is the dual-emit metrics target.
|
|
10
|
-
{
|
|
11
|
-
"worker_name": "lebiscuit-tanstack",
|
|
12
|
-
"kv_namespaces": [
|
|
13
|
-
{ "binding": "SITES_KV", "id": "ad0b74fc4d9341c9af9149c4ab85132f" }
|
|
14
|
-
],
|
|
15
|
-
"version_metadata": { "binding": "CF_VERSION_METADATA" },
|
|
16
|
-
"analytics_engine_datasets": [
|
|
17
|
-
{ "binding": "DECO_METRICS", "dataset": "deco_metrics_lebiscuit" }
|
|
18
|
-
]
|
|
19
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
// Per-site overrides for `miess-01-tanstack`.
|
|
2
|
-
//
|
|
3
|
-
// Worker name keeps the historical `miess-tanstack` (no "-01") so the deploy
|
|
4
|
-
// continues to land on the existing Cloudflare worker. The repo name has the
|
|
5
|
-
// `-01-` suffix; the worker name does not.
|
|
6
|
-
{
|
|
7
|
-
"worker_name": "miess-tanstack"
|
|
8
|
-
}
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// resolve-site.mjs
|
|
3
|
-
//
|
|
4
|
-
// Validates that the calling repository has a registered site manifest in
|
|
5
|
-
// deco-start, and emits the resolved fields to GITHUB_OUTPUT for downstream
|
|
6
|
-
// steps (wrangler tail, status comments, etc.).
|
|
7
|
-
//
|
|
8
|
-
// Required env:
|
|
9
|
-
// DECO_START_PATH - path to a checked-out deco-start (e.g. ".deco-start")
|
|
10
|
-
// SITE_NAME - typically `${GITHUB_REPOSITORY#*/}` set by the workflow
|
|
11
|
-
//
|
|
12
|
-
// Optional env:
|
|
13
|
-
// GITHUB_OUTPUT - if set, emit `key=value` lines here (CI mode).
|
|
14
|
-
// If unset, prints a human-readable summary to stdout.
|
|
15
|
-
|
|
16
|
-
import { appendFileSync } from "node:fs";
|
|
17
|
-
import { loadSiteManifest } from "./site-registry.mjs";
|
|
18
|
-
|
|
19
|
-
function fail(message) {
|
|
20
|
-
console.error(`::error::${message}`);
|
|
21
|
-
process.exit(1);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const decoStartPath = process.env.DECO_START_PATH;
|
|
25
|
-
const siteName = process.env.SITE_NAME;
|
|
26
|
-
const ghOutput = process.env.GITHUB_OUTPUT;
|
|
27
|
-
|
|
28
|
-
if (!decoStartPath) fail("DECO_START_PATH env var is required");
|
|
29
|
-
if (!siteName) fail("SITE_NAME env var is required");
|
|
30
|
-
|
|
31
|
-
let manifest;
|
|
32
|
-
try {
|
|
33
|
-
manifest = loadSiteManifest(decoStartPath, siteName);
|
|
34
|
-
} catch (err) {
|
|
35
|
-
fail(err instanceof Error ? err.message : String(err));
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const summary = {
|
|
39
|
-
site_name: siteName,
|
|
40
|
-
worker_name: manifest.worker_name,
|
|
41
|
-
has_routes: String(Array.isArray(manifest.routes) && manifest.routes.length > 0),
|
|
42
|
-
has_kv: String(Array.isArray(manifest.kv_namespaces) && manifest.kv_namespaces.length > 0),
|
|
43
|
-
has_analytics: String(
|
|
44
|
-
Array.isArray(manifest.analytics_engine_datasets) &&
|
|
45
|
-
manifest.analytics_engine_datasets.length > 0,
|
|
46
|
-
),
|
|
47
|
-
has_version_metadata: String(Boolean(manifest.version_metadata)),
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
if (ghOutput) {
|
|
51
|
-
const lines = Object.entries(summary).map(([k, v]) => `${k}=${v}`);
|
|
52
|
-
appendFileSync(ghOutput, `${lines.join("\n")}\n`);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
console.log(`Resolved site "${siteName}" -> worker "${manifest.worker_name}"`);
|
|
56
|
-
for (const [k, v] of Object.entries(summary)) {
|
|
57
|
-
console.log(` ${k}: ${v}`);
|
|
58
|
-
}
|