@decocms/start 3.0.0 → 4.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/SKILL.md +1 -1
- package/.agents/skills/deco-to-tanstack-migration/references/worker-cloudflare.md +32 -135
- package/.agents/skills/deco-to-tanstack-migration/templates/package-json.md +2 -5
- package/.cursor/rules/migration-tooling-policy.mdc +32 -48
- package/CODEOWNERS +4 -12
- package/MIGRATION_TOOLING_PLAN.md +9 -13
- package/package.json +2 -3
- package/scripts/migrate/phase-scaffold.ts +9 -12
- package/scripts/migrate/phase-verify.ts +3 -5
- package/scripts/migrate/templates/package-json.ts +6 -9
- package/.github/workflows/deploy.yml +0 -141
- package/.github/workflows/preview.yml +0 -200
- package/.github/workflows/sync-secrets.yml +0 -171
- package/deploy/README.md +0 -121
- package/deploy/wrangler-template.jsonc +0 -46
- package/scripts/deploy/build-wrangler-config.mjs +0 -47
- package/scripts/deploy/jsonc.mjs +0 -76
- package/scripts/deploy/site-registry.mjs +0 -95
- package/scripts/deploy/wrangler-wrapper.mjs +0 -118
- package/scripts/migrate/templates/github-workflows.ts +0 -159
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// build-wrangler-config.mjs
|
|
3
|
-
//
|
|
4
|
-
// Materializes a `wrangler.jsonc` from the canonical template, with
|
|
5
|
-
// $WORKER_* tokens substituted. The output file is what `wrangler deploy` /
|
|
6
|
-
// `wrangler versions upload` / `wrangler secret put` will read.
|
|
7
|
-
//
|
|
8
|
-
// Required env:
|
|
9
|
-
// DECO_START_PATH - path to a checked-out deco-start (e.g. ".deco-start")
|
|
10
|
-
// WORKER_NAME - the Cloudflare worker name (= storefront repo basename
|
|
11
|
-
// by convention; passed by the central CI workflows)
|
|
12
|
-
// OUTPUT_PATH - where to write the merged wrangler.jsonc
|
|
13
|
-
// (e.g. "./wrangler.jsonc" in the caller checkout)
|
|
14
|
-
|
|
15
|
-
import { writeFileSync } from "node:fs";
|
|
16
|
-
import { resolve } from "node:path";
|
|
17
|
-
import { applyWorkerName, loadTemplate } 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 workerName = process.env.WORKER_NAME;
|
|
26
|
-
const outputPath = process.env.OUTPUT_PATH;
|
|
27
|
-
|
|
28
|
-
if (!decoStartPath) fail("DECO_START_PATH env var is required");
|
|
29
|
-
if (!workerName) fail("WORKER_NAME env var is required");
|
|
30
|
-
if (!outputPath) fail("OUTPUT_PATH env var is required");
|
|
31
|
-
|
|
32
|
-
let merged;
|
|
33
|
-
try {
|
|
34
|
-
merged = applyWorkerName(loadTemplate(decoStartPath), workerName);
|
|
35
|
-
} catch (err) {
|
|
36
|
-
fail(err instanceof Error ? err.message : String(err));
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const header = `// AUTOGENERATED by @decocms/start at deploy time.
|
|
40
|
-
// Do not edit -- changes will be overwritten on the next deploy.
|
|
41
|
-
// Source: decocms/deco-start deploy/wrangler-template.jsonc + worker name "${workerName}"
|
|
42
|
-
`;
|
|
43
|
-
|
|
44
|
-
const body = JSON.stringify(merged, null, 2);
|
|
45
|
-
writeFileSync(resolve(outputPath), `${header}${body}\n`);
|
|
46
|
-
|
|
47
|
-
console.log(`Wrote ${outputPath} (worker "${workerName}")`);
|
package/scripts/deploy/jsonc.mjs
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
// Minimal JSONC -> JSON parser used by the deploy scripts.
|
|
2
|
-
//
|
|
3
|
-
// Strips // line comments and /* block comments */ outside of string literals
|
|
4
|
-
// and tolerates trailing commas in objects/arrays. Dependency-free so the
|
|
5
|
-
// deploy scripts can run with vanilla `node` in CI.
|
|
6
|
-
|
|
7
|
-
import { readFileSync } from "node:fs";
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* @param {string} input
|
|
11
|
-
* @returns {string}
|
|
12
|
-
*/
|
|
13
|
-
function stripComments(input) {
|
|
14
|
-
let out = "";
|
|
15
|
-
let i = 0;
|
|
16
|
-
let inStr = false;
|
|
17
|
-
let strChar = "";
|
|
18
|
-
while (i < input.length) {
|
|
19
|
-
const c = input[i];
|
|
20
|
-
const n = input[i + 1];
|
|
21
|
-
if (inStr) {
|
|
22
|
-
out += c;
|
|
23
|
-
if (c === "\\" && i + 1 < input.length) {
|
|
24
|
-
out += input[i + 1];
|
|
25
|
-
i += 2;
|
|
26
|
-
continue;
|
|
27
|
-
}
|
|
28
|
-
if (c === strChar) inStr = false;
|
|
29
|
-
i++;
|
|
30
|
-
continue;
|
|
31
|
-
}
|
|
32
|
-
if (c === '"') {
|
|
33
|
-
inStr = true;
|
|
34
|
-
strChar = c;
|
|
35
|
-
out += c;
|
|
36
|
-
i++;
|
|
37
|
-
continue;
|
|
38
|
-
}
|
|
39
|
-
if (c === "/" && n === "/") {
|
|
40
|
-
while (i < input.length && input[i] !== "\n") i++;
|
|
41
|
-
continue;
|
|
42
|
-
}
|
|
43
|
-
if (c === "/" && n === "*") {
|
|
44
|
-
i += 2;
|
|
45
|
-
while (i < input.length && !(input[i] === "*" && input[i + 1] === "/")) i++;
|
|
46
|
-
i += 2;
|
|
47
|
-
continue;
|
|
48
|
-
}
|
|
49
|
-
out += c;
|
|
50
|
-
i++;
|
|
51
|
-
}
|
|
52
|
-
return out;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* @param {string} text
|
|
57
|
-
* @returns {unknown}
|
|
58
|
-
*/
|
|
59
|
-
export function parseJsonc(text) {
|
|
60
|
-
const stripped = stripComments(text).replace(/,\s*([}\]])/g, "$1");
|
|
61
|
-
return JSON.parse(stripped);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* @param {string} path
|
|
66
|
-
* @returns {unknown}
|
|
67
|
-
*/
|
|
68
|
-
export function readJsoncFile(path) {
|
|
69
|
-
const raw = readFileSync(path, "utf8");
|
|
70
|
-
try {
|
|
71
|
-
return parseJsonc(raw);
|
|
72
|
-
} catch (err) {
|
|
73
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
74
|
-
throw new Error(`Failed to parse JSONC at ${path}: ${message}`);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
// Template loader + token substitution for the canonical wrangler config.
|
|
2
|
-
//
|
|
3
|
-
// There is no per-site "registry" anymore: every site's wrangler config is
|
|
4
|
-
// produced from `deploy/wrangler-template.jsonc` plus the worker name (which
|
|
5
|
-
// equals the storefront repo basename by convention). To accommodate fields
|
|
6
|
-
// that must vary deterministically per worker, the template can use these
|
|
7
|
-
// substitution tokens, which are replaced at config-build time:
|
|
8
|
-
//
|
|
9
|
-
// $WORKER_NAME -> worker name verbatim (e.g. "als-tanstack")
|
|
10
|
-
// $WORKER_UNDERSCORE -> worker name, `-` -> `_` (e.g. "als_tanstack")
|
|
11
|
-
//
|
|
12
|
-
// Trust model: callers cannot pass a fabricated worker name to the central
|
|
13
|
-
// CI workflows -- the deploy is gated by the `decocms-deployer` GitHub App
|
|
14
|
-
// being installed on the target storefront repo. If the App isn't installed
|
|
15
|
-
// there, the App-token mint fails and the deploy never starts.
|
|
16
|
-
|
|
17
|
-
import { existsSync } from "node:fs";
|
|
18
|
-
import { join } from "node:path";
|
|
19
|
-
import { readJsoncFile } from "./jsonc.mjs";
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* @param {string} decoStartPath
|
|
23
|
-
* @returns {string}
|
|
24
|
-
*/
|
|
25
|
-
export function templatePath(decoStartPath) {
|
|
26
|
-
return join(decoStartPath, "deploy", "wrangler-template.jsonc");
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* @param {string} decoStartPath
|
|
31
|
-
* @returns {Record<string, unknown>}
|
|
32
|
-
*/
|
|
33
|
-
export function loadTemplate(decoStartPath) {
|
|
34
|
-
const path = templatePath(decoStartPath);
|
|
35
|
-
if (!existsSync(path)) {
|
|
36
|
-
throw new Error(`wrangler-template.jsonc not found at ${path}.`);
|
|
37
|
-
}
|
|
38
|
-
const raw = readJsoncFile(path);
|
|
39
|
-
if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
|
|
40
|
-
throw new Error(`Template at ${path} must be a JSON object.`);
|
|
41
|
-
}
|
|
42
|
-
return /** @type {Record<string, unknown>} */ (raw);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Recursively replace `$WORKER_*` tokens in any string value of an
|
|
47
|
-
* object/array tree. Returns a new tree.
|
|
48
|
-
*
|
|
49
|
-
* @param {unknown} value
|
|
50
|
-
* @param {Record<string, string>} replacements
|
|
51
|
-
* @returns {unknown}
|
|
52
|
-
*/
|
|
53
|
-
function substituteTokens(value, replacements) {
|
|
54
|
-
if (typeof value === "string") {
|
|
55
|
-
let out = value;
|
|
56
|
-
for (const [token, repl] of Object.entries(replacements)) {
|
|
57
|
-
out = out.split(token).join(repl);
|
|
58
|
-
}
|
|
59
|
-
return out;
|
|
60
|
-
}
|
|
61
|
-
if (Array.isArray(value)) {
|
|
62
|
-
return value.map((v) => substituteTokens(v, replacements));
|
|
63
|
-
}
|
|
64
|
-
if (value && typeof value === "object") {
|
|
65
|
-
const out = /** @type {Record<string, unknown>} */ ({});
|
|
66
|
-
for (const [k, v] of Object.entries(value)) {
|
|
67
|
-
out[k] = substituteTokens(v, replacements);
|
|
68
|
-
}
|
|
69
|
-
return out;
|
|
70
|
-
}
|
|
71
|
-
return value;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Produce the wrangler config object by substituting `$WORKER_*` tokens in
|
|
76
|
-
* the template and prepending `name`.
|
|
77
|
-
*
|
|
78
|
-
* @param {Record<string, unknown>} template
|
|
79
|
-
* @param {string} workerName
|
|
80
|
-
* @returns {Record<string, unknown>}
|
|
81
|
-
*/
|
|
82
|
-
export function applyWorkerName(template, workerName) {
|
|
83
|
-
if (typeof workerName !== "string" || !/^[a-z0-9][a-z0-9-]*$/.test(workerName)) {
|
|
84
|
-
throw new Error(
|
|
85
|
-
`Invalid worker name: ${JSON.stringify(workerName)}. Use lowercase, hyphen-separated.`,
|
|
86
|
-
);
|
|
87
|
-
}
|
|
88
|
-
const substituted = /** @type {Record<string, unknown>} */ (
|
|
89
|
-
substituteTokens(template, {
|
|
90
|
-
$WORKER_UNDERSCORE: workerName.replace(/-/g, "_"),
|
|
91
|
-
$WORKER_NAME: workerName,
|
|
92
|
-
})
|
|
93
|
-
);
|
|
94
|
-
return { name: workerName, ...substituted };
|
|
95
|
-
}
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// deco-wrangler
|
|
3
|
-
//
|
|
4
|
-
// Local-dev wrapper around `wrangler` for storefront repos that no longer
|
|
5
|
-
// commit a `wrangler.jsonc`. Generates the canonical config from
|
|
6
|
-
// `@decocms/start`'s template into `./wrangler.jsonc` (gitignored), then
|
|
7
|
-
// optionally execs the real `wrangler` with that config in cwd.
|
|
8
|
-
//
|
|
9
|
-
// Usage from a customer repo (after `npm i -D @decocms/start@latest`):
|
|
10
|
-
//
|
|
11
|
-
// npx deco-wrangler gen # generate ./wrangler.jsonc and exit
|
|
12
|
-
// # (used by predev/prebuild/prepare hooks)
|
|
13
|
-
// npx deco-wrangler tail # tail prod logs (worker name resolved automatically)
|
|
14
|
-
// npx deco-wrangler types # regenerate worker-configuration.d.ts
|
|
15
|
-
// npx deco-wrangler deploy # discouraged in dev; deploys go via CI
|
|
16
|
-
// npx deco-wrangler --help # passes through to wrangler
|
|
17
|
-
//
|
|
18
|
-
// All non-`gen` invocations also (re)generate ./wrangler.jsonc first so the
|
|
19
|
-
// file is always in sync with the template before wrangler runs. The
|
|
20
|
-
// `@cloudflare/vite-plugin` and the `wrangler` CLI both auto-discover
|
|
21
|
-
// ./wrangler.jsonc in cwd, so no extra config plumbing is required.
|
|
22
|
-
//
|
|
23
|
-
// Worker name resolves in this order:
|
|
24
|
-
//
|
|
25
|
-
// 1. DECO_WORKER_NAME env var (explicit override)
|
|
26
|
-
// 2. git remote `origin` URL parsed for the GitHub repo basename
|
|
27
|
-
// 3. package.json `name` field
|
|
28
|
-
//
|
|
29
|
-
// By convention worker name == storefront repo basename. The CI deploys use
|
|
30
|
-
// the same convention. Local dev never deploys -- this wrapper is purely for
|
|
31
|
-
// generating a config that matches what the central workflow will produce.
|
|
32
|
-
|
|
33
|
-
import { execSync, spawnSync } from "node:child_process";
|
|
34
|
-
import { readFileSync, writeFileSync } from "node:fs";
|
|
35
|
-
import { dirname, resolve } from "node:path";
|
|
36
|
-
import { fileURLToPath } from "node:url";
|
|
37
|
-
import { applyWorkerName, loadTemplate } from "./site-registry.mjs";
|
|
38
|
-
|
|
39
|
-
const SCRIPT_DIR = dirname(fileURLToPath(import.meta.url));
|
|
40
|
-
// scripts/deploy/wrangler-wrapper.mjs -> deco-start root
|
|
41
|
-
const DECO_START_PATH = resolve(SCRIPT_DIR, "..", "..");
|
|
42
|
-
|
|
43
|
-
function eprintln(msg) {
|
|
44
|
-
process.stderr.write(`[deco-wrangler] ${msg}\n`);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function tryGitRemoteWorkerName() {
|
|
48
|
-
try {
|
|
49
|
-
const url = execSync("git remote get-url origin", {
|
|
50
|
-
stdio: ["ignore", "pipe", "ignore"],
|
|
51
|
-
})
|
|
52
|
-
.toString()
|
|
53
|
-
.trim();
|
|
54
|
-
// matches both git@github.com:org/repo(.git) and https://github.com/org/repo(.git)
|
|
55
|
-
const m = url.match(/github\.com[:/][^/]+\/([^/]+?)(?:\.git)?$/);
|
|
56
|
-
return m?.[1];
|
|
57
|
-
} catch {
|
|
58
|
-
return undefined;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function tryPackageJsonName() {
|
|
63
|
-
try {
|
|
64
|
-
const pkg = JSON.parse(readFileSync(resolve(process.cwd(), "package.json"), "utf8"));
|
|
65
|
-
return typeof pkg.name === "string" ? pkg.name : undefined;
|
|
66
|
-
} catch {
|
|
67
|
-
return undefined;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function resolveWorkerName() {
|
|
72
|
-
const envName = process.env.DECO_WORKER_NAME?.trim();
|
|
73
|
-
if (envName) return { name: envName, source: "DECO_WORKER_NAME env var" };
|
|
74
|
-
const gitName = tryGitRemoteWorkerName();
|
|
75
|
-
if (gitName) return { name: gitName, source: "git remote origin" };
|
|
76
|
-
const pkgName = tryPackageJsonName();
|
|
77
|
-
if (pkgName) return { name: pkgName, source: "package.json name" };
|
|
78
|
-
return undefined;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const resolved = resolveWorkerName();
|
|
82
|
-
if (!resolved) {
|
|
83
|
-
eprintln(
|
|
84
|
-
"Could not determine worker name. Set DECO_WORKER_NAME or run from a repo with a github.com 'origin' remote.",
|
|
85
|
-
);
|
|
86
|
-
process.exit(1);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
let merged;
|
|
90
|
-
try {
|
|
91
|
-
merged = applyWorkerName(loadTemplate(DECO_START_PATH), resolved.name);
|
|
92
|
-
} catch (err) {
|
|
93
|
-
eprintln(err instanceof Error ? err.message : String(err));
|
|
94
|
-
eprintln(`Worker name "${resolved.name}" was inferred from ${resolved.source}.`);
|
|
95
|
-
process.exit(1);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const outputPath = resolve(process.cwd(), "wrangler.jsonc");
|
|
99
|
-
const header = `// AUTOGENERATED by deco-wrangler -- DO NOT COMMIT.
|
|
100
|
-
// Add wrangler.jsonc to .gitignore. Regenerated on every \`deco-wrangler\` run.
|
|
101
|
-
// Source: @decocms/start deploy/wrangler-template.jsonc + worker name "${resolved.name}"
|
|
102
|
-
`;
|
|
103
|
-
writeFileSync(outputPath, `${header}${JSON.stringify(merged, null, 2)}\n`);
|
|
104
|
-
|
|
105
|
-
eprintln(`Resolved worker name "${resolved.name}" (via ${resolved.source})`);
|
|
106
|
-
eprintln(`Generated ${outputPath}`);
|
|
107
|
-
|
|
108
|
-
const argv = process.argv.slice(2);
|
|
109
|
-
// `gen` mode: just write the config and exit. Used by package.json
|
|
110
|
-
// predev/prebuild/prepare hooks to keep wrangler.jsonc in sync with the
|
|
111
|
-
// template without invoking wrangler itself.
|
|
112
|
-
if (argv[0] === "gen" || argv[0] === "generate") {
|
|
113
|
-
process.exit(0);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
const wranglerArgs = ["wrangler", ...argv];
|
|
117
|
-
const result = spawnSync("npx", wranglerArgs, { stdio: "inherit" });
|
|
118
|
-
process.exit(result.status ?? 1);
|
|
@@ -1,159 +0,0 @@
|
|
|
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.
|
|
11
|
-
|
|
12
|
-
const DEPLOY_YML = `name: Deploy
|
|
13
|
-
|
|
14
|
-
# Triggers decocms/deco-start's central deploy workflow via App-token.
|
|
15
|
-
|
|
16
|
-
on:
|
|
17
|
-
push:
|
|
18
|
-
branches: [main]
|
|
19
|
-
|
|
20
|
-
permissions:
|
|
21
|
-
contents: read
|
|
22
|
-
|
|
23
|
-
jobs:
|
|
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##*/}
|
|
42
|
-
`;
|
|
43
|
-
|
|
44
|
-
const PREVIEW_YML = `name: Preview
|
|
45
|
-
|
|
46
|
-
# Triggers decocms/deco-start's central preview workflow via App-token.
|
|
47
|
-
|
|
48
|
-
on:
|
|
49
|
-
pull_request:
|
|
50
|
-
types: [opened, synchronize, reopened]
|
|
51
|
-
push:
|
|
52
|
-
branches: ['env/**']
|
|
53
|
-
|
|
54
|
-
permissions:
|
|
55
|
-
contents: read
|
|
56
|
-
|
|
57
|
-
jobs:
|
|
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 || '' }}
|
|
89
|
-
`;
|
|
90
|
-
|
|
91
|
-
const REGEN_BLOCKS_YML = `name: Regenerate blocks.gen.json
|
|
92
|
-
|
|
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.
|
|
96
|
-
|
|
97
|
-
on:
|
|
98
|
-
push:
|
|
99
|
-
branches: [main]
|
|
100
|
-
paths:
|
|
101
|
-
- ".deco/blocks/**"
|
|
102
|
-
|
|
103
|
-
permissions:
|
|
104
|
-
contents: write
|
|
105
|
-
|
|
106
|
-
jobs:
|
|
107
|
-
regen:
|
|
108
|
-
uses: decocms/deco-start/.github/workflows/regen-blocks.yml@v3
|
|
109
|
-
secrets: inherit
|
|
110
|
-
`;
|
|
111
|
-
|
|
112
|
-
const SYNC_SECRETS_YML = `name: Sync worker secrets
|
|
113
|
-
|
|
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.
|
|
117
|
-
|
|
118
|
-
on:
|
|
119
|
-
workflow_dispatch:
|
|
120
|
-
inputs:
|
|
121
|
-
mode:
|
|
122
|
-
description: "dry-run = print diff only | apply = set secrets on worker"
|
|
123
|
-
required: true
|
|
124
|
-
default: "dry-run"
|
|
125
|
-
type: choice
|
|
126
|
-
options: [dry-run, apply]
|
|
127
|
-
|
|
128
|
-
permissions:
|
|
129
|
-
contents: read
|
|
130
|
-
|
|
131
|
-
jobs:
|
|
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 }}
|
|
150
|
-
`;
|
|
151
|
-
|
|
152
|
-
export function generateGithubWorkflows(): Record<string, string> {
|
|
153
|
-
return {
|
|
154
|
-
".github/workflows/deploy.yml": DEPLOY_YML,
|
|
155
|
-
".github/workflows/preview.yml": PREVIEW_YML,
|
|
156
|
-
".github/workflows/regen-blocks.yml": REGEN_BLOCKS_YML,
|
|
157
|
-
".github/workflows/sync-secrets.yml": SYNC_SECRETS_YML,
|
|
158
|
-
};
|
|
159
|
-
}
|