@ibalzam/codejitsu-core 0.12.0 → 0.13.1
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/MIGRATIONS/0.13.0.md +56 -0
- package/SETUP.md +5 -1
- package/bin/codejitsu.mjs +1 -1
- package/checklist/core.md +1 -1
- package/modules/audit/src/groups/structure.mjs +5 -2
- package/modules/cli/src/deploy.mjs +46 -12
- package/modules/deploy/CLAUDE.md +28 -4
- package/modules/deploy/checklist.md +4 -4
- package/modules/deploy/templates/daily-deploy.yml +22 -6
- package/package.json +1 -1
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# 0.13.0 — Daily deploy supports multi-site monorepos
|
|
2
|
+
|
|
3
|
+
## Summary
|
|
4
|
+
|
|
5
|
+
The deploy module now drives **every** Cloudflare Pages project in a repo, not just one. Previously the `daily-deploy.yml` workflow pinged a single deploy hook (`CLOUDFLARE_DEPLOY_HOOK_URL`), so a monorepo that deploys several Pages projects (e.g. `sites/www`, `sites/kamloops`, `sites/kelowna`) only ever rebuilt one of them on the morning cron — the others never graduated their scheduled/future-dated posts.
|
|
6
|
+
|
|
7
|
+
A new secret, `CLOUDFLARE_DEPLOY_HOOK_URLS`, holds every project's deploy hook URL (comma-separated). The workflow prefers it and pings each URL. Single-site repos are unchanged: `CLOUDFLARE_DEPLOY_HOOK_URL` still works and is still what `deploy:setup` writes when you give it one URL.
|
|
8
|
+
|
|
9
|
+
This is backward compatible — **no action needed for single-site repos**. Action is only required if one git repo deploys to **more than one** Cloudflare Pages project.
|
|
10
|
+
|
|
11
|
+
## Required actions
|
|
12
|
+
|
|
13
|
+
### Single-site repo (one Pages project)
|
|
14
|
+
|
|
15
|
+
Nothing to do. If you re-copy the workflow template, the behaviour is identical.
|
|
16
|
+
|
|
17
|
+
### Multi-site monorepo (one repo → several Pages projects)
|
|
18
|
+
|
|
19
|
+
This is the case the change exists for. Symptom: only one site publishes scheduled content each morning; the others look stale until something else triggers a build.
|
|
20
|
+
|
|
21
|
+
1. **Update the workflow file.** Re-copy the template so it loops over multiple hooks:
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
cp node_modules/@ibalzam/codejitsu-core/modules/deploy/templates/daily-deploy.yml \
|
|
25
|
+
.github/workflows/daily-deploy.yml
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
(Or run `npx codejitsu deploy:setup`, which copies it for you if missing.)
|
|
29
|
+
|
|
30
|
+
2. **Create one Cloudflare deploy hook per Pages project** — dashboard → each project → Settings → Builds & deployments → Deploy hooks, branch `main`.
|
|
31
|
+
|
|
32
|
+
3. **Store all the hook URLs in `CLOUDFLARE_DEPLOY_HOOK_URLS`, comma-separated.** Easiest via the wizard:
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
npx codejitsu deploy:setup
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
When it prompts, paste every project's URL comma-separated. It writes the plural secret (and removes the now-redundant singular one). Or set it directly:
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
gh secret set CLOUDFLARE_DEPLOY_HOOK_URLS \
|
|
42
|
+
--body "https://api.cloudflare.com/.../hook-a,https://api.cloudflare.com/.../hook-b,https://api.cloudflare.com/.../hook-c"
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
4. **Adding a site later:** create its deploy hook and append `,<new-url>` to `CLOUDFLARE_DEPLOY_HOOK_URLS`. No workflow edit needed.
|
|
46
|
+
|
|
47
|
+
## Verify
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
npm update @ibalzam/codejitsu-core
|
|
51
|
+
npx codejitsu deploy:run # dispatch the workflow once
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Then confirm a deployment kicks off in **every** Pages project, not just one. `npx codejitsu audit` now passes when either `CLOUDFLARE_DEPLOY_HOOK_URL` or `CLOUDFLARE_DEPLOY_HOOK_URLS` is set.
|
|
55
|
+
|
|
56
|
+
See `modules/deploy/CLAUDE.md` → "Multi-site monorepos" for the full reference.
|
package/SETUP.md
CHANGED
|
@@ -393,7 +393,11 @@ npx codejitsu deploy:setup
|
|
|
393
393
|
Interactive wizard:
|
|
394
394
|
- Copies `.github/workflows/daily-deploy.yml` + `wrangler.toml` from
|
|
395
395
|
package templates if missing.
|
|
396
|
-
- Prompts for the Cloudflare deploy hook URL.
|
|
396
|
+
- Prompts for the Cloudflare deploy hook URL(s). For a multi-site monorepo
|
|
397
|
+
(one repo → several Pages projects), enter every project's hook URL
|
|
398
|
+
comma-separated; they're stored in `CLOUDFLARE_DEPLOY_HOOK_URLS` and the
|
|
399
|
+
workflow pings each. A single site uses `CLOUDFLARE_DEPLOY_HOOK_URL`.
|
|
400
|
+
See `modules/deploy/CLAUDE.md` → "Multi-site monorepos".
|
|
397
401
|
- Stores it as a GH Actions secret via `gh secret set`.
|
|
398
402
|
- Optionally triggers a test run.
|
|
399
403
|
|
package/bin/codejitsu.mjs
CHANGED
|
@@ -73,7 +73,7 @@ function printHelp() {
|
|
|
73
73
|
console.log(` blog:init Install /blog, /blog-batch, /blog-images slash commands`);
|
|
74
74
|
console.log(` blog:selftest Cold-Claude write a throwaway post + grade it. Flags: --topic, --model`);
|
|
75
75
|
console.log(``);
|
|
76
|
-
console.log(` deploy:setup Wire up daily Cloudflare deploy (prompts for hook URL)`);
|
|
76
|
+
console.log(` deploy:setup Wire up daily Cloudflare deploy (prompts for hook URL(s); multi-site aware)`);
|
|
77
77
|
console.log(` deploy:run Trigger the Daily Deploy workflow once now`);
|
|
78
78
|
console.log(``);
|
|
79
79
|
console.log(` doctor Check Node + dependency versions are current (run BEFORE upgrading or scaffolding)`);
|
package/checklist/core.md
CHANGED
|
@@ -9,7 +9,7 @@ The runner covers the easy stuff (file presence, meta tags, canonical, schema sc
|
|
|
9
9
|
- [ ] `npm run build` exits 0 with no warnings about missing pages, unresolved imports, or broken links.
|
|
10
10
|
- [ ] `dist/` contains static HTML for every expected route. No `.html` route is missing.
|
|
11
11
|
- [ ] `wrangler.toml` is present and points to `dist`.
|
|
12
|
-
- [ ] `.github/workflows/daily-deploy.yml` exists; the
|
|
12
|
+
- [ ] `.github/workflows/daily-deploy.yml` exists; the deploy-hook secret is set in the repo — `CLOUDFLARE_DEPLOY_HOOK_URL` (single site) or `CLOUDFLARE_DEPLOY_HOOK_URLS` (comma-separated, one Deploy Hook per Pages project, for a multi-site monorepo). Skip if the site has no scheduled content.
|
|
13
13
|
|
|
14
14
|
## URLs + routing
|
|
15
15
|
|
|
@@ -75,12 +75,15 @@ export async function runStructure(ctx) {
|
|
|
75
75
|
const secrets = await listSecrets(repo);
|
|
76
76
|
if (secrets === null) {
|
|
77
77
|
results.push(info('Skipped GH secret check (gh not authenticated for this repo)'));
|
|
78
|
+
} else if (secrets.includes('CLOUDFLARE_DEPLOY_HOOK_URLS')) {
|
|
79
|
+
results.push(pass(`CLOUDFLARE_DEPLOY_HOOK_URLS set in ${repo} (multi-site)`));
|
|
78
80
|
} else if (secrets.includes('CLOUDFLARE_DEPLOY_HOOK_URL')) {
|
|
79
81
|
results.push(pass(`CLOUDFLARE_DEPLOY_HOOK_URL set in ${repo}`));
|
|
80
82
|
} else {
|
|
81
83
|
results.push(warn(
|
|
82
|
-
'
|
|
83
|
-
'Daily deploy workflow will fail. Run `npx codejitsu deploy:setup` to configure.'
|
|
84
|
+
'Deploy hook secret missing (CLOUDFLARE_DEPLOY_HOOK_URL or _URLS)',
|
|
85
|
+
'Daily deploy workflow will fail. Run `npx codejitsu deploy:setup` to configure. ' +
|
|
86
|
+
'For a multi-site monorepo, set CLOUDFLARE_DEPLOY_HOOK_URLS (one hook per Pages project, comma-separated).'
|
|
84
87
|
));
|
|
85
88
|
}
|
|
86
89
|
}
|
|
@@ -93,13 +93,19 @@ export async function runDeploySetup() {
|
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
// ─── GitHub secret ───────────────────────────────────────────────────
|
|
96
|
+
// Single site → CLOUDFLARE_DEPLOY_HOOK_URL. Multi-site monorepo (one repo,
|
|
97
|
+
// several Pages projects) → CLOUDFLARE_DEPLOY_HOOK_URLS holding every
|
|
98
|
+
// project's hook, comma-separated. The daily-deploy workflow prefers the
|
|
99
|
+
// plural secret and pings each URL.
|
|
96
100
|
console.log('\nChecking GitHub Actions secrets…');
|
|
97
101
|
const secrets = await listSecrets(repo);
|
|
98
|
-
const
|
|
102
|
+
const hasSingular = secrets.includes('CLOUDFLARE_DEPLOY_HOOK_URL');
|
|
103
|
+
const hasPlural = secrets.includes('CLOUDFLARE_DEPLOY_HOOK_URLS');
|
|
99
104
|
|
|
100
|
-
if (
|
|
101
|
-
|
|
102
|
-
|
|
105
|
+
if (hasSingular || hasPlural) {
|
|
106
|
+
const which = hasPlural ? 'CLOUDFLARE_DEPLOY_HOOK_URLS' : 'CLOUDFLARE_DEPLOY_HOOK_URL';
|
|
107
|
+
console.log(c.green('✓') + ` ${which} is set`);
|
|
108
|
+
const rotate = await prompt('\nRotate / re-enter the deploy hook URL(s)? [y/N]: ');
|
|
103
109
|
if (!/^y(es)?$/i.test(rotate.trim())) {
|
|
104
110
|
console.log(c.gray('\nNothing to do. The daily deploy is configured.\n'));
|
|
105
111
|
await offerTestRun(repo);
|
|
@@ -107,28 +113,51 @@ export async function runDeploySetup() {
|
|
|
107
113
|
}
|
|
108
114
|
}
|
|
109
115
|
|
|
110
|
-
// Prompt for URL.
|
|
116
|
+
// Prompt for URL(s).
|
|
111
117
|
console.log('');
|
|
112
|
-
console.log('Get a deploy hook URL from Cloudflare Pages:');
|
|
118
|
+
console.log('Get a deploy hook URL from Cloudflare Pages (one per Pages project):');
|
|
113
119
|
console.log(c.gray(' 1. Open Cloudflare dashboard → Pages → ' + (pagesName ?? 'your project') + ' → Settings'));
|
|
114
120
|
console.log(c.gray(' 2. Builds & deployments → Deploy hooks → "Add deploy hook"'));
|
|
115
121
|
console.log(c.gray(' 3. Name: "daily-scheduled-content" — Branch: main'));
|
|
116
122
|
console.log(c.gray(' 4. Copy the URL'));
|
|
123
|
+
console.log(c.gray(' Multi-site monorepo: repeat for every Pages project and paste all URLs comma-separated.'));
|
|
117
124
|
console.log('');
|
|
118
125
|
|
|
119
|
-
const
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
126
|
+
const raw = (await prompt('Paste the deploy hook URL(s), comma-separated: ')).trim();
|
|
127
|
+
const urls = raw.split(',').map((u) => u.trim()).filter(Boolean);
|
|
128
|
+
const prefix = 'https://api.cloudflare.com/client/v4/pages/webhooks/deploy_hooks/';
|
|
129
|
+
if (urls.length === 0) {
|
|
130
|
+
console.error(c.red('\n✗ No deploy hook URL provided.'));
|
|
131
|
+
process.exit(1);
|
|
132
|
+
}
|
|
133
|
+
const bad = urls.filter((u) => !u.startsWith(prefix));
|
|
134
|
+
if (bad.length > 0) {
|
|
135
|
+
console.error(c.red('\n✗ These don\'t look like Cloudflare Pages deploy hook URLs:'));
|
|
136
|
+
bad.forEach((u) => console.error(' ' + u));
|
|
137
|
+
console.error(' Expected prefix: ' + prefix);
|
|
123
138
|
process.exit(1);
|
|
124
139
|
}
|
|
125
140
|
|
|
126
|
-
|
|
141
|
+
// One URL → singular secret (back-compat). Multiple → plural secret.
|
|
142
|
+
const secretName = urls.length > 1 ? 'CLOUDFLARE_DEPLOY_HOOK_URLS' : 'CLOUDFLARE_DEPLOY_HOOK_URL';
|
|
143
|
+
const setOk = await setSecret(repo, secretName, urls.join(','));
|
|
127
144
|
if (!setOk) {
|
|
128
145
|
console.error(c.red('\n✗ Failed to set GitHub secret.'));
|
|
129
146
|
process.exit(1);
|
|
130
147
|
}
|
|
131
|
-
console.log(
|
|
148
|
+
console.log(
|
|
149
|
+
c.green('✓') + ` Secret ${secretName} set in ${repo}` +
|
|
150
|
+
(urls.length > 1 ? ` (${urls.length} hooks)` : '')
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
// Switching singular → plural: the stale singular secret is ignored by the
|
|
154
|
+
// workflow (plural wins) but is confusing. Remove it.
|
|
155
|
+
if (urls.length > 1 && hasSingular) {
|
|
156
|
+
const cleaned = await deleteSecret(repo, 'CLOUDFLARE_DEPLOY_HOOK_URL');
|
|
157
|
+
if (cleaned) {
|
|
158
|
+
console.log(c.gray(' Removed now-redundant CLOUDFLARE_DEPLOY_HOOK_URL (plural secret takes precedence).'));
|
|
159
|
+
}
|
|
160
|
+
}
|
|
132
161
|
|
|
133
162
|
await offerTestRun(repo);
|
|
134
163
|
}
|
|
@@ -236,6 +265,11 @@ async function setSecret(repo, name, value) {
|
|
|
236
265
|
return r.code === 0;
|
|
237
266
|
}
|
|
238
267
|
|
|
268
|
+
async function deleteSecret(repo, name) {
|
|
269
|
+
const r = await runGh(['secret', 'delete', name, '--repo', repo]);
|
|
270
|
+
return r.code === 0;
|
|
271
|
+
}
|
|
272
|
+
|
|
239
273
|
function runGh(args) {
|
|
240
274
|
return new Promise((resolve) => {
|
|
241
275
|
const proc = spawn('gh', args, { stdio: ['ignore', 'pipe', 'pipe'] });
|
package/modules/deploy/CLAUDE.md
CHANGED
|
@@ -5,7 +5,7 @@ When the user asks to **set up codejitsu/core/deploy** (or "wire up the Cloudfla
|
|
|
5
5
|
## What this module provides
|
|
6
6
|
|
|
7
7
|
- `templates/wrangler.toml` — minimal Cloudflare Pages config.
|
|
8
|
-
- `templates/daily-deploy.yml` — GitHub Action that pings
|
|
8
|
+
- `templates/daily-deploy.yml` — GitHub Action that pings one or more Cloudflare deploy hooks every morning so scheduled blog posts (or any time-gated content) graduate from hidden to public on their publish date. Handles both single-site repos and multi-site monorepos (see below).
|
|
9
9
|
|
|
10
10
|
## Wiring it into a site
|
|
11
11
|
|
|
@@ -30,11 +30,34 @@ gh secret set CLOUDFLARE_DEPLOY_HOOK_URL --body "<paste URL>"
|
|
|
30
30
|
|
|
31
31
|
Or via the GitHub UI: Settings → Secrets and variables → Actions → New repository secret, named `CLOUDFLARE_DEPLOY_HOOK_URL`.
|
|
32
32
|
|
|
33
|
+
> Multi-site monorepo? Skip this step and follow **Multi-site monorepos** below instead.
|
|
34
|
+
|
|
33
35
|
### 4. Verify
|
|
34
36
|
|
|
35
37
|
- Trigger the workflow manually: `gh workflow run "Daily Deploy"` (or via the GH UI).
|
|
36
38
|
- A Cloudflare Pages deployment should kick off within seconds.
|
|
37
39
|
|
|
40
|
+
## Multi-site monorepos
|
|
41
|
+
|
|
42
|
+
A single repo can host several sites (e.g. `sites/www`, `sites/kamloops`, `sites/kelowna`), each deployed as its **own Cloudflare Pages project**. There is still only **one** `.github/workflows/daily-deploy.yml` for the repo, but it must rebuild **every** project — otherwise only one site graduates its scheduled content each morning and the rest stay stale.
|
|
43
|
+
|
|
44
|
+
The template already handles this. To wire it up:
|
|
45
|
+
|
|
46
|
+
1. **Create one deploy hook per Pages project** (Cloudflare dashboard → each project → Settings → Builds & deployments → Deploy hooks, branch `main`). For garagedoorpros that's three: `garagedoorpros-ca`, `gdp-kamloops`, `gdp-kelowna`.
|
|
47
|
+
2. **Store all the URLs in a single plural secret, comma-separated** (one line — easiest to set and paste; Cloudflare hook URLs never contain commas):
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
gh secret set CLOUDFLARE_DEPLOY_HOOK_URLS \
|
|
51
|
+
--body "https://api.cloudflare.com/.../www-hook,https://api.cloudflare.com/.../kamloops-hook,https://api.cloudflare.com/.../kelowna-hook"
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
(Newline- or space-separated values also work — the workflow splits on commas, newlines, and spaces — but commas keep it a single line, which avoids the multi-line `--body` / paste pitfalls.)
|
|
55
|
+
3. The workflow prefers `CLOUDFLARE_DEPLOY_HOOK_URLS` when present, splits it, and pings each URL. It only falls back to the singular `CLOUDFLARE_DEPLOY_HOOK_URL` when the plural secret is absent — so single-site repos need no change.
|
|
56
|
+
|
|
57
|
+
**Adding a site later:** create its deploy hook, append `,<new-url>` to `CLOUDFLARE_DEPLOY_HOOK_URLS`, done. No workflow edit needed.
|
|
58
|
+
|
|
59
|
+
**Verify:** `gh workflow run "Daily Deploy"` then confirm a deployment kicks off in *every* Pages project, not just one.
|
|
60
|
+
|
|
38
61
|
## Build command (for Cloudflare Pages git integration)
|
|
39
62
|
|
|
40
63
|
If using Cloudflare's git integration (preferred for push-driven deploys):
|
|
@@ -45,7 +68,8 @@ If using Cloudflare's git integration (preferred for push-driven deploys):
|
|
|
45
68
|
|
|
46
69
|
## What must NOT be done
|
|
47
70
|
|
|
48
|
-
- **Don't commit the deploy hook URL.**
|
|
71
|
+
- **Don't commit the deploy hook URL(s).** They belong in the `CLOUDFLARE_DEPLOY_HOOK_URL` / `CLOUDFLARE_DEPLOY_HOOK_URLS` secret only.
|
|
72
|
+
- **Don't add a second daily-deploy workflow for a monorepo's extra sites.** One workflow pings all hooks via `CLOUDFLARE_DEPLOY_HOOK_URLS` — see **Multi-site monorepos**. Duplicate workflows mean duplicate crons and drift.
|
|
49
73
|
- **Don't change the cron without reason.** 13:00 UTC is intentional — early-morning Pacific so posts are live by the time users wake up. If a site is on a different timezone, change it explicitly and note why in a comment in the workflow file.
|
|
50
74
|
- **Don't add a `wrangler deploy` step to the cron workflow.** The workflow only *pings* the deploy hook; Cloudflare does the actual build via git integration. Doing the build twice causes drift.
|
|
51
75
|
- **Don't skip the daily-deploy workflow even if the site has no scheduled content yet.** It's the safety net for when the user adds a scheduled post six months later.
|
|
@@ -54,5 +78,5 @@ If using Cloudflare's git integration (preferred for push-driven deploys):
|
|
|
54
78
|
|
|
55
79
|
- [ ] `wrangler.toml` present at site root with correct `name`.
|
|
56
80
|
- [ ] `.github/workflows/daily-deploy.yml` present.
|
|
57
|
-
- [ ]
|
|
58
|
-
- [ ] Cloudflare Pages project exists and is connected to the git repo.
|
|
81
|
+
- [ ] Deploy-hook secret set (check with `gh secret list`): `CLOUDFLARE_DEPLOY_HOOK_URL` for a single site, or `CLOUDFLARE_DEPLOY_HOOK_URLS` (one URL per line) for a multi-site monorepo.
|
|
82
|
+
- [ ] A Cloudflare Pages project exists for **each** site and is connected to the git repo, and every project has a hook in the secret.
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
- [ ] `wrangler.toml` exists at site root with the correct Cloudflare Pages project `name`.
|
|
4
4
|
- [ ] `pages_build_output_dir = "dist"` in `wrangler.toml`.
|
|
5
5
|
- [ ] `.github/workflows/daily-deploy.yml` exists and is unmodified from the template (or modifications are documented in a comment).
|
|
6
|
-
- [ ]
|
|
7
|
-
- [ ] Cloudflare Pages project exists and is connected to the GitHub repo (git integration).
|
|
8
|
-
- [ ] Pages build command is `npm run build
|
|
9
|
-
- [ ] Manual run of `gh workflow run "Daily Deploy"` triggers a Cloudflare deployment within seconds.
|
|
6
|
+
- [ ] Deploy-hook secret is set in the repo (`gh secret list`): `CLOUDFLARE_DEPLOY_HOOK_URL` (single site) or `CLOUDFLARE_DEPLOY_HOOK_URLS` (multi-site monorepo, one URL per line).
|
|
7
|
+
- [ ] A Cloudflare Pages project exists for **each** site and is connected to the GitHub repo (git integration); every project's hook is in the secret.
|
|
8
|
+
- [ ] Each Pages project's build command is `npm run build` (for its own site/workspace), output dir is `dist`, Node version is 20.
|
|
9
|
+
- [ ] Manual run of `gh workflow run "Daily Deploy"` triggers a Cloudflare deployment in **every** Pages project within seconds.
|
|
@@ -3,9 +3,14 @@ name: Daily Deploy
|
|
|
3
3
|
# Triggers a Cloudflare Pages rebuild each morning so any scheduled content
|
|
4
4
|
# whose publish date has arrived graduates from hidden to public.
|
|
5
5
|
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
6
|
+
# Single-site repo: set the secret CLOUDFLARE_DEPLOY_HOOK_URL to the one
|
|
7
|
+
# Deploy Hook URL from Cloudflare Pages (Project settings -> Builds &
|
|
8
8
|
# deployments -> Deploy hooks).
|
|
9
|
+
#
|
|
10
|
+
# Multi-site monorepo (one repo -> several Pages projects): set the secret
|
|
11
|
+
# CLOUDFLARE_DEPLOY_HOOK_URLS to ALL the projects' Deploy Hook URLs, separated
|
|
12
|
+
# by commas (newlines also work). The job pings every URL so each site
|
|
13
|
+
# rebuilds. If both secrets are set, the plural one wins.
|
|
9
14
|
|
|
10
15
|
on:
|
|
11
16
|
schedule:
|
|
@@ -18,12 +23,23 @@ jobs:
|
|
|
18
23
|
runs-on: ubuntu-latest
|
|
19
24
|
timeout-minutes: 5
|
|
20
25
|
steps:
|
|
21
|
-
- name: Ping Cloudflare deploy hook
|
|
26
|
+
- name: Ping Cloudflare deploy hook(s)
|
|
22
27
|
env:
|
|
28
|
+
HOOKS: ${{ secrets.CLOUDFLARE_DEPLOY_HOOK_URLS }}
|
|
23
29
|
HOOK: ${{ secrets.CLOUDFLARE_DEPLOY_HOOK_URL }}
|
|
24
30
|
run: |
|
|
25
|
-
|
|
26
|
-
|
|
31
|
+
# Prefer the plural (multi-URL) secret; fall back to the singular one.
|
|
32
|
+
urls="$HOOKS"
|
|
33
|
+
[ -z "$urls" ] && urls="$HOOK"
|
|
34
|
+
if [ -z "$urls" ]; then
|
|
35
|
+
echo "Neither CLOUDFLARE_DEPLOY_HOOK_URLS nor CLOUDFLARE_DEPLOY_HOOK_URL is set"
|
|
27
36
|
exit 1
|
|
28
37
|
fi
|
|
29
|
-
|
|
38
|
+
# Accept commas, newlines, or spaces as separators between URLs.
|
|
39
|
+
failed=0
|
|
40
|
+
for url in $(echo "$urls" | tr ',\n' ' '); do
|
|
41
|
+
[ -z "$url" ] && continue
|
|
42
|
+
echo "Pinging deploy hook: ${url%%\?*}"
|
|
43
|
+
curl --fail-with-body -X POST "$url" || failed=1
|
|
44
|
+
done
|
|
45
|
+
exit $failed
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ibalzam/codejitsu-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Shared core for Codejitsu Astro sites — reusable code and Claude-facing instructions for blog, SEO, images, deploy, and llms.txt.",
|
|
6
6
|
"keywords": [
|