create-grist-widget 0.2.22 → 0.2.23

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-grist-widget",
3
- "version": "0.2.22",
3
+ "version": "0.2.23",
4
4
  "description": "Scaffold a new Grist custom widget from the grist-widget-sdk Vite template",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -5,12 +5,19 @@ name: Deploy widget to GitHub Pages
5
5
  # /<repo>/v<version>/ + mutable /<repo>/latest/.
6
6
  # Rebuilt only when package.json's version has no v<version> dir yet, so
7
7
  # re-pushing main without a version bump is a no-op deploy.
8
- # A push that *creates* the main ref (github.event.created) -- fired by
9
- # GitHub's "Use this template" copying this repo onto a brand-new ref --
10
- # is skipped entirely instead: it would otherwise publish whatever
11
- # boilerplate version package.json happens to have checked in and
12
- # permanently spend the first-release override before anyone's done
13
- # real work.
8
+ # A push that *creates* the main ref, authored by GitHub's own web-flow
9
+ # bot -- fired by "Use this template" copying this repo onto a brand-new
10
+ # ref -- is skipped entirely instead: it would otherwise publish
11
+ # whatever boilerplate version package.json happens to have checked in
12
+ # and permanently spend the first-release override before anyone's done
13
+ # real work. (Checking github.event.created alone isn't enough: a CLI
14
+ # scaffold's own first `git push -u origin main` also creates that ref
15
+ # for the first time, but is a real user's genuine first release and
16
+ # must not be skipped -- the web-flow committer check tells the two
17
+ # apart.) That skipped run still clears any foreign content the copy
18
+ # brought along (stray v<version>/ dirs, a root/latest/ still pointing
19
+ # at the source repo's own path) via `cleanup-foreign`, so root/latest/
20
+ # aren't left blank until the widget's real first release.
14
21
  # - push to dev -> dev channel: mutable /<repo>/dev/
15
22
  # with version.json + a self-reload snippet, for live review inside Grist.
16
23
  #
@@ -98,7 +105,7 @@ jobs:
98
105
  --event "${{ github.event_name }}" \
99
106
  --ref "${{ github.ref }}" \
100
107
  ${{ github.event.inputs.force == 'true' && '--force' || '' }} \
101
- ${{ github.event.created == true && '--created' || '' }})
108
+ ${{ github.event.created == true && github.event.head_commit.committer.email == 'noreply@github.com' && '--created' || '' }})
102
109
  echo "Plan: $PLAN"
103
110
  node -e '
104
111
  const p = JSON.parse(process.argv[1]);
@@ -106,6 +113,7 @@ jobs:
106
113
  const out = process.env.GITHUB_OUTPUT;
107
114
  fs.appendFileSync(out, `context=${p.context}\n`);
108
115
  fs.appendFileSync(out, `skip=${p.skip ? "true" : "false"}\n`);
116
+ fs.appendFileSync(out, `reason=${p.reason || ""}\n`);
109
117
  fs.appendFileSync(out, `version=${p.version || ""}\n`);
110
118
  fs.appendFileSync(out, `base=${p.base}\n`);
111
119
  fs.appendFileSync(out, `firstRelease=${p.firstRelease ? "true" : "false"}\n`);
@@ -130,9 +138,19 @@ jobs:
130
138
  --sha "$SHA" --ref "${{ github.ref }}"
131
139
 
132
140
  - name: Skip (already published)
133
- if: steps.plan.outputs.skip == 'true'
141
+ if: steps.plan.outputs.skip == 'true' && steps.plan.outputs.reason != 'ref-created'
134
142
  run: echo "== skip — v${{ steps.plan.outputs.version }} already published"
135
143
 
144
+ # The ref-created push never reaches Build/Place, so it's the only
145
+ # path where cleanupForeignVersionsIfFirstRelease (normally a side
146
+ # effect of Place) needs to run standalone -- otherwise foreign
147
+ # content from "Use this template" (stray v<version>/ dirs, a
148
+ # root/latest/ pointing at the source repo's own path) sits untouched
149
+ # until the widget's real first release.
150
+ - name: Clean foreign content (ref-created push published nothing)
151
+ if: steps.plan.outputs.reason == 'ref-created'
152
+ run: node scripts/deploy.mjs cleanup-foreign --site site --repo "$REPO_NAME"
153
+
136
154
  - name: Finalize (versions.json + commit + push)
137
155
  run: |
138
156
  UPDATE_VERSIONS=""
@@ -114,10 +114,15 @@ automatically.
114
114
  >
115
115
  > "Use this template" also immediately fires this workflow once on its own,
116
116
  > the moment the repo is created — before you've cloned it, let alone
117
- > changed anything. That run is recognized (GitHub marks it as the push
118
- > that *created* the `main` ref) and skipped entirely: nothing gets
119
- > published, and it doesn't count as your first release, so the `0.0.1`
120
- > override above still applies in full once you actually push real changes.
117
+ > changed anything. That run is recognized (GitHub's own web-flow bot
118
+ > creating the `main` ref) and skipped entirely: nothing gets published,
119
+ > and it doesn't count as your first release, so the `0.0.1` override above
120
+ > still applies in full once you actually push real changes. If you also
121
+ > checked "Include all branches", that same skipped run still clears out
122
+ > whatever foreign content came along with it — stray `v<version>/` dirs,
123
+ > and a root/`latest/` still pointing at the *source* repo's own path
124
+ > (which would otherwise render blank until your real first release) —
125
+ > without needing to publish anything of its own to do so.
121
126
 
122
127
  **One-time setup** (the workflow can't do this part for you):
123
128
 
@@ -23,14 +23,23 @@
23
23
  // Prints JSON { context: "release"|"dev", version?, base, skip }.
24
24
  // Release is skipped when v<version> already exists on gh-pages
25
25
  // (idempotence: re-pushing main without a version bump is a no-op).
26
- // --created (github.event.created off a push event) additionally skips
27
- // unconditionally, without consuming the first-release version override
28
- // -- see plan()'s own comment.
26
+ // --created additionally skips unconditionally, without consuming the
27
+ // first-release version override -- see plan()'s own comment. Callers
28
+ // must only pass --created for GitHub's own server-side "Use this
29
+ // template" push, never a real user push that merely happens to create
30
+ // a ref for the first time (e.g. a CLI scaffold's first `git push -u
31
+ // origin main`) -- see deploy.yml's wiring for the distinguishing check.
29
32
  //
30
33
  // place --site <dir> --repo <name> --channel <release|dev>
31
34
  // [--version <v>] --dist <dir> --sha <sha> [--ref <ref>]
32
35
  // Copies a freshly built dist into the gh-pages tree.
33
36
  //
37
+ // cleanup-foreign --site <dir> --repo <name>
38
+ // Standalone entry point for `cleanupForeignVersionsIfFirstRelease` --
39
+ // used on a skipped ref-created push (see `plan`), which never reaches
40
+ // `place` (the only other caller of this cleanup) so foreign content
41
+ // from "Use this template" would otherwise sit untouched indefinitely.
42
+ //
34
43
  // remove --site <dir>
35
44
  // Removes dev/ from the gh-pages tree (retire the dev URL when the `dev`
36
45
  // branch is deleted). Never touches a release or latest/.
@@ -237,21 +246,28 @@ function replaceDir(dest, srcDist) {
237
246
 
238
247
  /**
239
248
  * If this repo has never genuinely published a release before (no
240
- * v<version>/ directory whose showcase-meta.json matches this repo), any
241
- * v<version>/ directories present are provably inherited noise -- e.g. from
242
- * copying this template repo including its gh-pages branch (GitHub's "Use
243
- * this template" -> "Include all branches"). Safe to clear them all before
244
- * placing this repo's actual first release: there is no ambiguity, since a
245
- * repo with zero genuine releases can't have any of its own history to lose.
246
- * Never touches dev/, latest/, or site-root files. Once a genuine release
247
- * exists for this repo, buildVersionsManifest is non-empty and this is
248
- * permanently a no-op.
249
+ * v<version>/ directory whose showcase-meta.json matches this repo), *every*
250
+ * top-level entry except `dev/` (the mutable dev channel, legitimately this
251
+ * repo's own regardless of release history) and a small set of
252
+ * pipeline-managed files is provably inherited noise -- e.g. from copying
253
+ * this template repo including its gh-pages branch (GitHub's "Use this
254
+ * template" -> "Include all branches"): stray `v<version>/` directories,
255
+ * but also a root `index.html`/`latest/` still referencing the *source*
256
+ * repo's own base path (found live: a fresh copy's root and `latest/`
257
+ * pointed at `/grist-widget-template/v0.2.22/assets/...`, 404ing on this
258
+ * repo's own Pages site -- a blank page -- because the ref-created push
259
+ * that used to overwrite them with this repo's own build is now skipped
260
+ * entirely, see `plan()`). Safe to clear unconditionally: a repo with zero
261
+ * genuine releases can't have any of its own history to lose. Once a
262
+ * genuine release exists for this repo, buildVersionsManifest is non-empty
263
+ * and this is permanently a no-op.
249
264
  */
250
265
  export function cleanupForeignVersionsIfFirstRelease(siteDir, repo) {
251
266
  if (hasGenuineRelease(siteDir, repo)) return { cleaned: [] }
267
+ const PROTECTED = new Set([".nojekyll", "dev", "versions.json", ".git"])
252
268
  const cleaned = []
253
269
  for (const name of existsSync(siteDir) ? readdirSync(siteDir) : []) {
254
- if (!/^v\d+\.\d+\.\d+/.test(name)) continue
270
+ if (PROTECTED.has(name)) continue
255
271
  rmSync(join(siteDir, name), { recursive: true, force: true })
256
272
  cleaned.push(name)
257
273
  }
@@ -432,6 +448,11 @@ function main() {
432
448
  console.log("remove:", JSON.stringify(res))
433
449
  break
434
450
  }
451
+ case "cleanup-foreign": {
452
+ const res = cleanupForeignVersionsIfFirstRelease(args.site, args.repo)
453
+ console.log("cleanup-foreign:", JSON.stringify(res))
454
+ break
455
+ }
435
456
  case "finalize": {
436
457
  const res = finalize({
437
458
  siteDir: args.site,