@decocms/start 2.30.0 → 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 -48
- package/.cursor/rules/migration-tooling-policy.mdc +41 -14
- package/.github/workflows/deploy.yml +88 -62
- package/.github/workflows/preview.yml +136 -79
- package/.github/workflows/sync-secrets.yml +61 -63
- package/CODEOWNERS +6 -8
- package/MIGRATION_TOOLING_PLAN.md +14 -8
- package/deploy/README.md +106 -70
- 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
|
@@ -58,9 +58,10 @@ export default createDecoWorkerEntry(serverEntry, {
|
|
|
58
58
|
```
|
|
59
59
|
|
|
60
60
|
The `main` field is set centrally so a future migration of the entry path
|
|
61
|
-
applies to every site at once (single PR to the template).
|
|
62
|
-
override
|
|
63
|
-
|
|
61
|
+
applies to every site at once (single PR to the template). There is no
|
|
62
|
+
per-site override file (D6.2 Pure C); if a single site truly needs a different
|
|
63
|
+
entry path, change the template (and accept that all sites get it) or add a
|
|
64
|
+
substitution token like `$WORKER_ENTRY_PATH` and feed it from a per-site env.
|
|
64
65
|
|
|
65
66
|
This ensures admin route interception AND edge caching survive the build because they're in the Worker's own fetch handler, outside of TanStack's build pipeline.
|
|
66
67
|
|
|
@@ -211,22 +212,26 @@ Or in project `.npmrc` with an env var (for CI):
|
|
|
211
212
|
**Tradeoff with `github:` syntax**: No semver resolution — `npm update` is meaningless. Pin to a tag for stability: `github:decocms/deco-start#v0.14.2`. Without a tag, you get HEAD of the default branch.
|
|
212
213
|
|
|
213
214
|
|
|
214
|
-
## 46. Central Deploy / Wrangler Config (D6)
|
|
215
|
+
## 46. Central Deploy / Wrangler Config (D6.2)
|
|
215
216
|
|
|
216
|
-
**Severity**: HIGH — site repos must NOT commit `wrangler.jsonc
|
|
217
|
+
**Severity**: HIGH — site repos must NOT commit `wrangler.jsonc`, must NOT hold
|
|
218
|
+
Cloudflare credentials, and must NOT have per-site deploy logic. Doing so
|
|
219
|
+
reintroduces drift and breaks the trust model.
|
|
217
220
|
|
|
218
|
-
Per [D6](../../../../.cursor/rules/migration-tooling-policy.mdc), all
|
|
221
|
+
Per [D6.2](../../../../.cursor/rules/migration-tooling-policy.mdc), all
|
|
219
222
|
storefronts deploy via reusable workflows shipped from
|
|
220
|
-
`decocms/deco-start/.github/workflows/{deploy,preview,sync-secrets,regen-blocks}.yml@
|
|
221
|
-
|
|
222
|
-
`
|
|
223
|
-
`decocms/deco-start/deploy/
|
|
224
|
-
|
|
225
|
-
repos gitignore the
|
|
223
|
+
`decocms/deco-start/.github/workflows/{deploy,preview,sync-secrets,regen-blocks}.yml@v3`.
|
|
224
|
+
There is no per-site registry: worker name == storefront repo basename by
|
|
225
|
+
convention. The canonical `wrangler.jsonc` lives at
|
|
226
|
+
`decocms/deco-start/deploy/wrangler-template.jsonc`; the build script
|
|
227
|
+
substitutes `$WORKER_NAME` / `$WORKER_UNDERSCORE` tokens at deploy time and
|
|
228
|
+
writes a generated `wrangler.jsonc` in the runner. Site repos gitignore the
|
|
229
|
+
file.
|
|
226
230
|
|
|
227
231
|
### What goes in the site repo
|
|
228
232
|
|
|
229
|
-
Four
|
|
233
|
+
Four caller workflow stubs that mint a `decocms-deployer` GitHub App
|
|
234
|
+
installation token and call `gh workflow run` on `decocms/deco-start@v3`:
|
|
230
235
|
|
|
231
236
|
```yaml
|
|
232
237
|
# .github/workflows/deploy.yml
|
|
@@ -235,31 +240,48 @@ on:
|
|
|
235
240
|
push:
|
|
236
241
|
branches: [main]
|
|
237
242
|
permissions:
|
|
238
|
-
contents:
|
|
243
|
+
contents: read
|
|
239
244
|
jobs:
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
245
|
+
trigger:
|
|
246
|
+
runs-on: ubuntu-latest
|
|
247
|
+
steps:
|
|
248
|
+
- uses: actions/create-github-app-token@v1
|
|
249
|
+
id: app-token
|
|
250
|
+
with:
|
|
251
|
+
app-id: ${{ secrets.DECOCMS_DEPLOYER_APP_ID }}
|
|
252
|
+
private-key: ${{ secrets.DECOCMS_DEPLOYER_APP_PRIVATE_KEY }}
|
|
253
|
+
owner: decocms
|
|
254
|
+
repositories: deco-start
|
|
255
|
+
- env:
|
|
256
|
+
GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
|
257
|
+
run: |
|
|
258
|
+
gh workflow run deploy.yml \
|
|
259
|
+
--repo decocms/deco-start \
|
|
260
|
+
--ref v3 \
|
|
261
|
+
-f site_owner=${GITHUB_REPOSITORY%%/*} \
|
|
262
|
+
-f site_name=${GITHUB_REPOSITORY##*/}
|
|
243
263
|
```
|
|
244
264
|
|
|
245
265
|
(Plus equivalent `preview.yml`, `regen-blocks.yml`, `sync-secrets.yml` —
|
|
246
266
|
see `scripts/migrate/templates/github-workflows.ts` for the canonical text.)
|
|
247
|
-
The migration script generates these for new sites
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
267
|
+
The migration script generates these for new sites.
|
|
268
|
+
|
|
269
|
+
### App + secrets setup (one-time, per org)
|
|
270
|
+
|
|
271
|
+
1. Create a `decocms-deployer` GitHub App with permissions
|
|
272
|
+
`Actions: Write`, `Contents: Read`, `Pull requests: Write` (the last
|
|
273
|
+
only needed if you want preview URLs commented on PRs),
|
|
274
|
+
`Metadata: Read`. Install it on `decocms/deco-start` and on each
|
|
275
|
+
storefront repo (or whole-org install on `deco-sites`).
|
|
276
|
+
2. Store the App ID and private key as `deco-sites` org-level secrets
|
|
277
|
+
`DECOCMS_DEPLOYER_APP_ID` and `DECOCMS_DEPLOYER_APP_PRIVATE_KEY` so every
|
|
278
|
+
storefront workflow can mint installation tokens without per-repo setup.
|
|
279
|
+
3. Store `CLOUDFLARE_API_TOKEN` and `CLOUDFLARE_ACCOUNT_ID` as plain repo
|
|
280
|
+
secrets in `decocms/deco-start` (NOT in any storefront).
|
|
281
|
+
4. For each storefront that has runtime secrets: create a GitHub Environment
|
|
282
|
+
in `decocms/deco-start` named `<storefront-repo-basename>-secrets`, add
|
|
283
|
+
the `SECRET_*` values there, and configure protection rules to grant the
|
|
284
|
+
site team self-service access to that environment only.
|
|
263
285
|
|
|
264
286
|
### Local dev
|
|
265
287
|
|
|
@@ -277,16 +299,31 @@ Site repos add three package.json hooks so vite picks up the generated
|
|
|
277
299
|
```
|
|
278
300
|
|
|
279
301
|
`deco-wrangler` is a `bin` shipped from `@decocms/start` that materializes the
|
|
280
|
-
canonical config from the central
|
|
281
|
-
|
|
302
|
+
canonical config from the central template (worker name inferred from git
|
|
303
|
+
remote / package.json), then either exits (`gen` mode) or execs the real
|
|
304
|
+
`wrangler` with that config in cwd.
|
|
282
305
|
|
|
283
306
|
### Trust model
|
|
284
307
|
|
|
285
|
-
-
|
|
286
|
-
-
|
|
287
|
-
|
|
288
|
-
-
|
|
289
|
-
|
|
308
|
+
- **Authorization gate**: the deploy can only start if the
|
|
309
|
+
`decocms-deployer` App is installed on the target storefront repo. The
|
|
310
|
+
central workflow's App-token mint step fails with a clear error otherwise.
|
|
311
|
+
- **Worker naming is convention-based and not customer-controlled.** A
|
|
312
|
+
customer with push access to their own storefront cannot rename the worker
|
|
313
|
+
their deploy lands on (the central workflow uses `inputs.site_name` as the
|
|
314
|
+
worker name; modifying their stub to pass a different `site_name` would
|
|
315
|
+
also require the App to be installed on that other repo).
|
|
316
|
+
- **Cloudflare credentials never leave `decocms/deco-start`.** The central
|
|
317
|
+
workflow runs in deco-start's context, so the env-var resolves natively
|
|
318
|
+
from repo secrets.
|
|
319
|
+
- **Force-rollback is impossible for production.** The central deploy
|
|
320
|
+
workflow ignores any caller-supplied sha and always resolves the
|
|
321
|
+
storefront's current default-branch HEAD itself.
|
|
322
|
+
- **Per-site runtime secrets** (`SECRET_*`) live in deco-start environments,
|
|
323
|
+
not storefront repos. The storefront caller stub for `sync-secrets.yml`
|
|
324
|
+
triggers a workflow that binds to the matching env and runs
|
|
325
|
+
`wrangler secret put`. The storefront repo holds zero secrets beyond the
|
|
326
|
+
`decocms-deployer` App credentials.
|
|
290
327
|
|
|
291
328
|
### Common mistakes (do not do these)
|
|
292
329
|
|
|
@@ -295,12 +332,17 @@ execs the real `wrangler` with that config in cwd.
|
|
|
295
332
|
- **Adding a site-local `deploy.yml` step** (e.g. cache purge after deploy).
|
|
296
333
|
Add it to `deco-start/.github/workflows/deploy.yml` instead so every site
|
|
297
334
|
picks it up at once.
|
|
335
|
+
- **Adding `CLOUDFLARE_*` to a storefront repo's secrets.** They never
|
|
336
|
+
belong there. The central workflow runs in deco-start's context.
|
|
337
|
+
- **Adding `SECRET_*` to a storefront repo's secrets.** They live in the
|
|
338
|
+
matching `<site_name>-secrets` environment in deco-start.
|
|
298
339
|
- **Hard-coding `account_id` in a site's wrangler config.** It comes from
|
|
299
|
-
`CLOUDFLARE_ACCOUNT_ID` (
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
- **
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
340
|
+
`CLOUDFLARE_ACCOUNT_ID` (in CI; `wrangler login` locally) — keeping
|
|
341
|
+
it out of JSON is the one-way protection against accidentally deploying
|
|
342
|
+
to the wrong account.
|
|
343
|
+
- **Trying to override the worker name** for one site. There is no
|
|
344
|
+
per-site override mechanism in D6.2. If the worker MUST be named
|
|
345
|
+
differently from the repo, the right answer is either to rename the
|
|
346
|
+
repo to match (cleanest) or to do a CF-side migration (deploy a new
|
|
347
|
+
worker with the repo-name and re-attach routes). This trade-off was
|
|
348
|
+
taken intentionally in exchange for the registry-free architecture.
|
|
@@ -76,24 +76,51 @@ Failure modes get documented in skills, not encoded as escape hatches.
|
|
|
76
76
|
**Agent behavior**: when a migration goes sideways, propose deletion +
|
|
77
77
|
re-run, not in-place repair. Add the failure mode to the skill.
|
|
78
78
|
|
|
79
|
-
### D6 —
|
|
79
|
+
### D6.2 — App-mediated dispatch + no per-site registry (signed off 2026-05-07; supersedes D6 + D6.1)
|
|
80
80
|
All storefronts deploy via reusable workflows under
|
|
81
|
-
`decocms/deco-start/.github/workflows/{deploy,preview,sync-secrets,regen-blocks}.yml@
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
81
|
+
`decocms/deco-start/.github/workflows/{deploy,preview,sync-secrets,regen-blocks}.yml@v3`.
|
|
82
|
+
Storefront caller stubs mint a short-lived **`decocms-deployer` GitHub App**
|
|
83
|
+
installation token (App ID + private key live as `deco-sites` org-level
|
|
84
|
+
secrets) and call `gh workflow run deploy.yml --repo decocms/deco-start --ref v3
|
|
85
|
+
-f site_owner=… -f site_name=…`. The central workflow runs in
|
|
86
|
+
**`decocms/deco-start`'s context**, so `CLOUDFLARE_API_TOKEN` and
|
|
87
|
+
`CLOUDFLARE_ACCOUNT_ID` are ordinary repo secrets in `decocms/deco-start`
|
|
88
|
+
and never leave it.
|
|
89
|
+
|
|
90
|
+
There is **no per-site registry under `deploy/sites/`**. Worker name == storefront
|
|
91
|
+
repo basename by convention. Per-worker derived fields use `$WORKER_NAME` /
|
|
92
|
+
`$WORKER_UNDERSCORE` substitution tokens in
|
|
93
|
+
[`deploy/wrangler-template.jsonc`](../../deploy/wrangler-template.jsonc).
|
|
94
|
+
The deploy authorization gate is the App being installed on the storefront
|
|
95
|
+
repo — if it isn't, the App-token mint inside the central workflow fails and
|
|
96
|
+
the deploy never starts. **Customer repos do not commit `wrangler.jsonc`** —
|
|
97
|
+
it is generated locally by `deco-wrangler gen` (a `bin` shipped from
|
|
98
|
+
`@decocms/start`) and gitignored.
|
|
99
|
+
|
|
100
|
+
Production deploys are **force-rollback proof**: the central workflow ignores
|
|
101
|
+
any caller-supplied `site_sha` and resolves the storefront's current default
|
|
102
|
+
branch HEAD itself. The worst a compromised storefront can do across tenants
|
|
103
|
+
is trigger a no-op redeploy of another storefront's current main.
|
|
104
|
+
|
|
105
|
+
`SECRET_*` runtime secrets live in **`decocms/deco-start`** as well, in
|
|
106
|
+
per-storefront GitHub Environments named `<site_name>-secrets`. `sync-secrets.yml`
|
|
107
|
+
binds to the matching environment and runs `wrangler secret put`. Site teams
|
|
108
|
+
get edit/approve permission on their own environment via Environment
|
|
109
|
+
protection rules. **The storefront repo holds zero secrets** beyond the
|
|
110
|
+
App credentials (which only grant the ability to trigger workflows on
|
|
111
|
+
`decocms/deco-start`).
|
|
112
|
+
|
|
113
|
+
`deploy/`, `scripts/deploy/`, and the central workflow files are
|
|
89
114
|
CODEOWNERS-protected.
|
|
90
115
|
|
|
91
116
|
**Agent behavior**: when adding or migrating a site, do **not** generate a
|
|
92
|
-
per-site `wrangler.jsonc
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
`decocms
|
|
96
|
-
`
|
|
117
|
+
per-site `wrangler.jsonc`, do **not** generate a `deploy/sites/<repo>.jsonc`
|
|
118
|
+
file (that whole directory was removed in D6.2), and do **not** add
|
|
119
|
+
`CLOUDFLARE_*` or `SECRET_*` to a storefront repo's secrets. The site repo
|
|
120
|
+
gets four ~15-line caller stubs that mint a `decocms-deployer` App token and
|
|
121
|
+
fire `workflow_dispatch` at `decocms/deco-start@v3`; the App ID + private key
|
|
122
|
+
live as `deco-sites` org-level secrets `DECOCMS_DEPLOYER_APP_ID` and
|
|
123
|
+
`DECOCMS_DEPLOYER_APP_PRIVATE_KEY`.
|
|
97
124
|
|
|
98
125
|
## Priority order
|
|
99
126
|
|
|
@@ -1,115 +1,141 @@
|
|
|
1
1
|
name: deploy (central)
|
|
2
2
|
|
|
3
|
-
# Reusable workflow that drives `wrangler deploy` for any storefront repo
|
|
4
|
-
#
|
|
3
|
+
# Reusable workflow that drives `wrangler deploy` for any storefront repo.
|
|
4
|
+
# Worker name is the storefront repo basename by convention; there is no
|
|
5
|
+
# per-site registry. The deploy is gated by the `decocms-deployer` GitHub App
|
|
6
|
+
# being installed on the target storefront repo -- the App-token mint fails
|
|
7
|
+
# (and the deploy never starts) if the App isn't installed there.
|
|
5
8
|
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
# another site's worker.
|
|
9
|
+
# v3 architecture (D6.2): triggered via `workflow_dispatch` from the storefront,
|
|
10
|
+
# authenticated as the `decocms-deployer` GitHub App. The deploy runs IN THIS
|
|
11
|
+
# REPO'S CONTEXT, so `CLOUDFLARE_API_TOKEN` / `CLOUDFLARE_ACCOUNT_ID` resolve
|
|
12
|
+
# from this repo's plain repo secrets and never leave decocms/deco-start.
|
|
11
13
|
#
|
|
12
|
-
# Caller usage (in
|
|
14
|
+
# Caller usage (in the storefront repo, `.github/workflows/deploy.yml`):
|
|
13
15
|
#
|
|
14
16
|
# on:
|
|
15
17
|
# push:
|
|
16
18
|
# branches: [main]
|
|
17
19
|
# permissions:
|
|
18
|
-
# contents:
|
|
20
|
+
# contents: read
|
|
19
21
|
# jobs:
|
|
20
|
-
#
|
|
21
|
-
#
|
|
22
|
-
#
|
|
22
|
+
# trigger:
|
|
23
|
+
# runs-on: ubuntu-latest
|
|
24
|
+
# steps:
|
|
25
|
+
# - uses: actions/create-github-app-token@v1
|
|
26
|
+
# id: app-token
|
|
27
|
+
# with:
|
|
28
|
+
# app-id: ${{ secrets.DECOCMS_DEPLOYER_APP_ID }}
|
|
29
|
+
# private-key: ${{ secrets.DECOCMS_DEPLOYER_APP_PRIVATE_KEY }}
|
|
30
|
+
# owner: decocms
|
|
31
|
+
# repositories: deco-start
|
|
32
|
+
# - env:
|
|
33
|
+
# GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
|
34
|
+
# run: |
|
|
35
|
+
# gh workflow run deploy.yml \
|
|
36
|
+
# --repo decocms/deco-start \
|
|
37
|
+
# --ref v3 \
|
|
38
|
+
# -f site_owner=${GITHUB_REPOSITORY%%/*} \
|
|
39
|
+
# -f site_name=${GITHUB_REPOSITORY##*/}
|
|
23
40
|
|
|
24
41
|
on:
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
42
|
+
workflow_dispatch:
|
|
43
|
+
inputs:
|
|
44
|
+
site_owner:
|
|
45
|
+
description: "GitHub org of the storefront (e.g. deco-sites). Defaults to deco-sites."
|
|
46
|
+
type: string
|
|
47
|
+
required: false
|
|
48
|
+
default: deco-sites
|
|
49
|
+
site_name:
|
|
50
|
+
description: "Storefront repo basename. Becomes the Cloudflare worker name."
|
|
51
|
+
type: string
|
|
30
52
|
required: true
|
|
31
53
|
|
|
32
54
|
permissions:
|
|
33
|
-
contents:
|
|
55
|
+
contents: read
|
|
34
56
|
|
|
35
57
|
concurrency:
|
|
36
|
-
group: deploy-${{
|
|
58
|
+
group: deploy-${{ inputs.site_owner }}-${{ inputs.site_name }}
|
|
37
59
|
cancel-in-progress: false
|
|
38
60
|
|
|
39
61
|
jobs:
|
|
40
62
|
deploy:
|
|
41
63
|
runs-on: ubuntu-latest
|
|
42
64
|
steps:
|
|
43
|
-
- name: Checkout
|
|
65
|
+
- name: Checkout deco-start (template + scripts)
|
|
44
66
|
uses: actions/checkout@v4
|
|
45
67
|
|
|
46
|
-
- name:
|
|
47
|
-
id:
|
|
68
|
+
- name: Mint App token for storefront checkout
|
|
69
|
+
id: app-token
|
|
70
|
+
uses: actions/create-github-app-token@v1
|
|
71
|
+
with:
|
|
72
|
+
app-id: ${{ secrets.DECOCMS_DEPLOYER_APP_ID }}
|
|
73
|
+
private-key: ${{ secrets.DECOCMS_DEPLOYER_APP_PRIVATE_KEY }}
|
|
74
|
+
owner: ${{ inputs.site_owner }}
|
|
75
|
+
repositories: ${{ inputs.site_name }}
|
|
76
|
+
|
|
77
|
+
# SECURITY: production deploys IGNORE any caller-supplied sha. The deploy
|
|
78
|
+
# always targets the storefront's CURRENT default-branch HEAD. This means
|
|
79
|
+
# an attacker with push to repo A who triggers a deploy of repo B can
|
|
80
|
+
# only force a no-op redeploy of B's current main -- they cannot select
|
|
81
|
+
# an arbitrary historical commit (no force-rollback attack).
|
|
82
|
+
- name: Resolve target sha (storefront default branch HEAD)
|
|
83
|
+
id: target
|
|
84
|
+
env:
|
|
85
|
+
GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
|
86
|
+
SITE_REPO: ${{ inputs.site_owner }}/${{ inputs.site_name }}
|
|
48
87
|
run: |
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
REF="${REF#refs/tags/}"
|
|
56
|
-
REF="${REF#refs/heads/}"
|
|
57
|
-
echo "deco_start_ref=$REF" >> "$GITHUB_OUTPUT"
|
|
58
|
-
echo "site_name=${GITHUB_REPOSITORY#*/}" >> "$GITHUB_OUTPUT"
|
|
88
|
+
set -euo pipefail
|
|
89
|
+
DEFAULT_BRANCH=$(gh api "repos/$SITE_REPO" --jq .default_branch)
|
|
90
|
+
SHA=$(gh api "repos/$SITE_REPO/branches/$DEFAULT_BRANCH" --jq .commit.sha)
|
|
91
|
+
echo "ref=$DEFAULT_BRANCH" >> "$GITHUB_OUTPUT"
|
|
92
|
+
echo "sha=$SHA" >> "$GITHUB_OUTPUT"
|
|
93
|
+
echo "::notice::Deploying $SITE_REPO @ $DEFAULT_BRANCH ($SHA)"
|
|
59
94
|
|
|
60
|
-
- name: Checkout
|
|
95
|
+
- name: Checkout storefront at default-branch HEAD
|
|
61
96
|
uses: actions/checkout@v4
|
|
62
97
|
with:
|
|
63
|
-
repository:
|
|
64
|
-
ref: ${{ steps.
|
|
65
|
-
|
|
98
|
+
repository: ${{ inputs.site_owner }}/${{ inputs.site_name }}
|
|
99
|
+
ref: ${{ steps.target.outputs.sha }}
|
|
100
|
+
token: ${{ steps.app-token.outputs.token }}
|
|
101
|
+
path: site
|
|
102
|
+
fetch-depth: 1
|
|
66
103
|
|
|
67
104
|
- uses: actions/setup-node@v4
|
|
68
105
|
with:
|
|
69
106
|
node-version: 22
|
|
70
107
|
|
|
71
|
-
- name: Generate lockfile if missing
|
|
72
|
-
if: hashFiles('package-lock.json') == ''
|
|
73
|
-
run: npm install --package-lock-only
|
|
74
|
-
|
|
75
108
|
- name: Restore npm cache
|
|
76
109
|
uses: actions/cache@v4
|
|
77
110
|
with:
|
|
78
111
|
path: ~/.npm
|
|
79
|
-
key: npm-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
|
|
112
|
+
key: npm-${{ runner.os }}-${{ hashFiles('site/package-lock.json') }}
|
|
80
113
|
restore-keys: npm-${{ runner.os }}-
|
|
81
114
|
|
|
82
|
-
- name:
|
|
115
|
+
- name: Install dependencies
|
|
116
|
+
working-directory: site
|
|
83
117
|
run: |
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
git config user.name "github-actions[bot]"
|
|
87
|
-
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
88
|
-
git add package-lock.json
|
|
89
|
-
git commit -m "chore: sync package-lock.json"
|
|
90
|
-
git push || echo "Lockfile push failed (remote ahead); proceeding with deploy"
|
|
118
|
+
if [ ! -f package-lock.json ]; then
|
|
119
|
+
npm install --package-lock-only
|
|
91
120
|
fi
|
|
92
121
|
npm ci
|
|
93
122
|
|
|
94
123
|
- name: Build
|
|
124
|
+
working-directory: site
|
|
95
125
|
run: npm run build
|
|
96
126
|
|
|
97
|
-
- name:
|
|
98
|
-
|
|
99
|
-
run: node .deco-start/scripts/deploy/resolve-site.mjs
|
|
100
|
-
env:
|
|
101
|
-
DECO_START_PATH: .deco-start
|
|
102
|
-
SITE_NAME: ${{ steps.meta.outputs.site_name }}
|
|
103
|
-
|
|
104
|
-
- name: Generate wrangler.jsonc
|
|
105
|
-
run: node .deco-start/scripts/deploy/build-wrangler-config.mjs
|
|
127
|
+
- name: Generate wrangler.jsonc from template
|
|
128
|
+
working-directory: site
|
|
106
129
|
env:
|
|
107
|
-
DECO_START_PATH: .
|
|
108
|
-
|
|
109
|
-
OUTPUT_PATH: ./wrangler.jsonc
|
|
130
|
+
DECO_START_PATH: "${{ github.workspace }}"
|
|
131
|
+
WORKER_NAME: ${{ inputs.site_name }}
|
|
132
|
+
OUTPUT_PATH: "./wrangler.jsonc"
|
|
133
|
+
run: node "$DECO_START_PATH/scripts/deploy/build-wrangler-config.mjs"
|
|
110
134
|
|
|
111
135
|
- name: Deploy to Cloudflare Workers
|
|
112
|
-
|
|
136
|
+
working-directory: site
|
|
113
137
|
env:
|
|
114
138
|
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
|
115
139
|
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
|
140
|
+
BUILD_HASH: ${{ steps.target.outputs.sha }}
|
|
141
|
+
run: npx wrangler deploy --var "BUILD_HASH:${BUILD_HASH:0:7}"
|