@getvitops/create 0.1.0 → 0.2.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/README.md
CHANGED
|
@@ -40,6 +40,9 @@ with every relevant `@getvitops/*` package pre-wired:
|
|
|
40
40
|
collection, `primary`/`footer` menus, and settings apply on first boot; the
|
|
41
41
|
starter pages (home, about, terms, privacy — plus a 404 route) publish when
|
|
42
42
|
the setup wizard's "include sample content" option is chosen.
|
|
43
|
+
- **GitHub bootstrap** — `pnpm run init:github` creates a same-named GitHub
|
|
44
|
+
repo via the `gh` CLI, pushes `main` + `dev`, and makes `dev` the default
|
|
45
|
+
branch (idempotent; `--dry-run` / `--public` flags).
|
|
43
46
|
- **dev → main promotion flow** — GitHub Actions deploying `dev` to an
|
|
44
47
|
isolated `-dev` worker (`dev.<domain>` with a custom domain; own D1/R2 via
|
|
45
48
|
`scripts/build-dev-wrangler.mjs`, which hard-fails without `DEV_D1_ID`) and
|
package/package.json
CHANGED
|
@@ -47,4 +47,6 @@ searching them over pre-trained knowledge for Astro/EmDash questions.
|
|
|
47
47
|
- `pnpm typecheck` — `astro check`
|
|
48
48
|
- `pnpm deploy` — build + `wrangler deploy` prod (provisions D1/R2 on first run)
|
|
49
49
|
- `pnpm deploy:dev` — build + deploy the isolated dev worker (needs `DEV_D1_ID`)
|
|
50
|
+
- `pnpm run init:github` — one-time: create + push the GitHub repo (main + dev,
|
|
51
|
+
dev default). Only run when the user asks to set up GitHub.
|
|
50
52
|
- `npx vitops validate design-system.json` — schema-check the design config
|
|
@@ -69,15 +69,19 @@ The repo ships a two-environment flow modeled on branch = environment:
|
|
|
69
69
|
|
|
70
70
|
One-time setup:
|
|
71
71
|
|
|
72
|
-
1.
|
|
73
|
-
|
|
74
|
-
|
|
72
|
+
1. `pnpm run init:github` — creates a GitHub repo named after this project
|
|
73
|
+
(via the `gh` CLI; `-- --public` for a public repo), commits if needed,
|
|
74
|
+
pushes `main` + `dev`, and makes `dev` the default branch. Idempotent;
|
|
75
|
+
`-- --dry-run` previews. Then branch-protect `main` (require the promotion
|
|
76
|
+
PR + review).
|
|
75
77
|
2. Create the isolated dev resources:
|
|
76
78
|
`wrangler d1 create my-emdash-site-dev` and
|
|
77
79
|
`wrangler r2 bucket create my-emdash-site-media-dev`.
|
|
78
|
-
3. Add repo secrets: `CLOUDFLARE_API_TOKEN`,
|
|
79
|
-
`
|
|
80
|
-
(
|
|
80
|
+
3. Add repo secrets: `gh secret set CLOUDFLARE_API_TOKEN`,
|
|
81
|
+
`gh secret set CLOUDFLARE_ACCOUNT_ID`, and `gh secret set DEV_D1_ID`
|
|
82
|
+
(the id printed by `d1 create`). Optionally `PROMOTE_TOKEN` (a PAT allowed
|
|
83
|
+
to bypass protection) for hands-off promotion. The first workflow runs
|
|
84
|
+
fail until these exist.
|
|
81
85
|
|
|
82
86
|
`pnpm deploy:dev` reproduces the dev deploy locally: it rewrites the
|
|
83
87
|
adapter-generated wrangler config (`scripts/build-dev-wrangler.mjs`) so the
|
|
@@ -130,6 +134,7 @@ pnpm build:css # regenerate the CSS manually
|
|
|
130
134
|
| `src/pages/404.astro` | Not-found page (the catch-all rewrites here) |
|
|
131
135
|
| `wrangler.jsonc` | Cloudflare bindings (D1/R2) + cron trigger |
|
|
132
136
|
| `scripts/build-dev-wrangler.mjs` | Rewrites the built wrangler config for the isolated dev worker |
|
|
137
|
+
| `scripts/init-github.mjs` | One-time: create + push the GitHub repo (`pnpm run init:github`) |
|
|
133
138
|
| `.github/workflows/` | deploy-dev (push to `dev`), deploy-prod (push to `main`), promote |
|
|
134
139
|
| `.agents/skills/promote/` | Agent skill: dispatch the dev → main promotion |
|
|
135
140
|
| `.mcp.json` | Astro + EmDash docs MCP servers for coding agents |
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
"preview": "astro preview",
|
|
10
10
|
"deploy": "astro build && wrangler deploy",
|
|
11
11
|
"deploy:dev": "astro build && node scripts/build-dev-wrangler.mjs && wrangler deploy --config dist/server/wrangler.dev.json",
|
|
12
|
+
"init:github": "node scripts/init-github.mjs",
|
|
12
13
|
"typecheck": "astro check",
|
|
13
14
|
"build:css": "vitops generate -i design-system.json -f tailwind -o src/styles",
|
|
14
15
|
"prepare": "vp config"
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// One-time GitHub bootstrap: creates a GitHub repo named after this project
|
|
2
|
+
// (package.json name), pushes `main` + `dev`, and makes `dev` the default
|
|
3
|
+
// branch — the shape the deploy workflows expect (deploy-dev on push to dev,
|
|
4
|
+
// deploy-prod on push to main, promote.yml between them).
|
|
5
|
+
//
|
|
6
|
+
// pnpm run init:github # private repo (default)
|
|
7
|
+
// pnpm run init:github -- --public
|
|
8
|
+
// pnpm run init:github -- --dry-run
|
|
9
|
+
//
|
|
10
|
+
// Idempotent: safe to re-run — existing git repo, commits, dev branch, and
|
|
11
|
+
// origin remote are all left alone. Requires the GitHub CLI (`gh`), logged in
|
|
12
|
+
// (`gh auth login`).
|
|
13
|
+
|
|
14
|
+
import { execSync, spawnSync } from 'node:child_process';
|
|
15
|
+
import { readFileSync } from 'node:fs';
|
|
16
|
+
|
|
17
|
+
const args = new Set(process.argv.slice(2));
|
|
18
|
+
const dryRun = args.has('--dry-run');
|
|
19
|
+
const visibility = args.has('--public') ? '--public' : '--private';
|
|
20
|
+
|
|
21
|
+
const repoName = JSON.parse(readFileSync('package.json', 'utf8')).name.replace(/^@[^/]+\//, '');
|
|
22
|
+
|
|
23
|
+
function check(cmd) {
|
|
24
|
+
return spawnSync(cmd[0], cmd.slice(1), { encoding: 'utf8' });
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function quiet(cmd) {
|
|
28
|
+
try {
|
|
29
|
+
return execSync(cmd, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim();
|
|
30
|
+
} catch {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function run(cmd) {
|
|
36
|
+
if (dryRun) {
|
|
37
|
+
console.log(`[dry-run] ${cmd}`);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
console.log(`$ ${cmd}`);
|
|
41
|
+
try {
|
|
42
|
+
execSync(cmd, { stdio: 'inherit' });
|
|
43
|
+
} catch {
|
|
44
|
+
console.error(
|
|
45
|
+
`\nERROR: \`${cmd}\` failed (see output above). Fix and re-run — the script is idempotent.`,
|
|
46
|
+
);
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// --- Preflight: gh installed and authenticated -------------------------------
|
|
52
|
+
if (check(['gh', '--version']).status !== 0) {
|
|
53
|
+
console.error('ERROR: the GitHub CLI (`gh`) is required. Install it from https://cli.github.com');
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
if (check(['gh', 'auth', 'status']).status !== 0) {
|
|
57
|
+
console.error('ERROR: `gh` is not logged in. Run `gh auth login` first.');
|
|
58
|
+
process.exit(1);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// --- Local git: repo, initial commit, main + dev branches --------------------
|
|
62
|
+
if (quiet('git rev-parse --is-inside-work-tree') === null) {
|
|
63
|
+
run('git init -b main');
|
|
64
|
+
}
|
|
65
|
+
if (quiet('git rev-parse HEAD') === null) {
|
|
66
|
+
run('git add -A');
|
|
67
|
+
run('git commit -m "Initial commit (scaffolded from @getvitops/create emdash template)"');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// The workflows key off `main`; normalize whatever the initial branch is.
|
|
71
|
+
const branch = quiet('git branch --show-current');
|
|
72
|
+
if (branch && branch !== 'main' && branch !== 'dev') {
|
|
73
|
+
run(`git branch -m ${branch} main`);
|
|
74
|
+
}
|
|
75
|
+
if (quiet('git show-ref --verify refs/heads/dev') === null) {
|
|
76
|
+
run('git branch dev main');
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// --- GitHub: create repo (same name), push, default to dev -------------------
|
|
80
|
+
if (quiet('git remote get-url origin') === null) {
|
|
81
|
+
run(`gh repo create ${repoName} ${visibility} --source=. --remote=origin`);
|
|
82
|
+
} else {
|
|
83
|
+
console.log('origin remote already set — skipping `gh repo create`.');
|
|
84
|
+
}
|
|
85
|
+
run('git push -u origin main dev');
|
|
86
|
+
run('gh repo edit --default-branch dev');
|
|
87
|
+
run('git checkout dev');
|
|
88
|
+
|
|
89
|
+
// --- What's left (manual, needs your Cloudflare account) ---------------------
|
|
90
|
+
console.log(`
|
|
91
|
+
Repo ready: main (production) + dev (integration, default branch).
|
|
92
|
+
NOTE: the first workflow runs will fail until the secrets below exist.
|
|
93
|
+
|
|
94
|
+
Next steps:
|
|
95
|
+
1. Dev resources: wrangler d1 create ${repoName}-dev (note the printed id)
|
|
96
|
+
wrangler r2 bucket create ${repoName}-media-dev
|
|
97
|
+
2. Secrets: gh secret set CLOUDFLARE_API_TOKEN
|
|
98
|
+
gh secret set CLOUDFLARE_ACCOUNT_ID
|
|
99
|
+
gh secret set DEV_D1_ID
|
|
100
|
+
3. Protect main: Settings → Branches → protect 'main' (require the
|
|
101
|
+
promotion PR + review), so prod only ships via promote.yml.
|
|
102
|
+
`);
|