create-deka-app 0.53.4 → 0.53.7-canary-4551de1

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
@@ -41,13 +41,43 @@ two publish together, from the same CI run (`.github/workflows/publish-runtime.y
41
41
  the `deka` family), so a given create-deka-app version always produces the
42
42
  same project: no registry lookup needed to decide the pin.
43
43
 
44
- The one exception is a create-deka-app release whose exact-matching
45
- runtime build isn't published yet (or a scaffolder-only release cut via
46
- `publish.yml`'s `v*` tag path, which has no runtime counterpart at all).
47
- If installing the exact pin fails, create-deka-app falls back to the
48
- latest published `@dekaruntime/deka` version, prints a clear warning, and
49
- never leaves a nonexistent version pinned in the generated
50
- `package.json`.
44
+ There is one publish path for this whole repo: create-deka-app has no
45
+ standalone release of its own. The version in this repo's own
46
+ `package.json` is a `0.0.0` placeholder — it is never bumped by hand or
47
+ committed as part of a release; the workflow stamps the real version into
48
+ it at publish time, in the working tree only.
49
+
50
+ The one exception to the lockstep pin is a create-deka-app release whose
51
+ exact-matching runtime build isn't published yet. If installing the exact
52
+ pin fails, create-deka-app falls back to the latest published
53
+ `@dekaruntime/deka` version, prints a clear warning, and never leaves a
54
+ nonexistent version pinned in the generated `package.json`.
55
+
56
+ ## Channels
57
+
58
+ There are two channels, [rfd#68](https://github.com/dekaruntime/rfd/issues/68):
59
+
60
+ ```sh
61
+ npx create-deka-app@latest myapp # stable (the default)
62
+ npx create-deka-app@canary myapp # canary
63
+ ```
64
+
65
+ **Stable** (`npx create-deka-app@latest`, or just `npx create-deka-app`) pins
66
+ a plain `X.Y.Z` deka runtime — the default, and what everyone not
67
+ deliberately opting in gets.
68
+
69
+ **Canary** (`npx create-deka-app@canary`) pins a prerelease version shaped
70
+ `X.Y.Z-canary-<7-char-commit-sha>` (e.g. `0.59.0-canary-d5661ed`) — every
71
+ merge to deka's `main` branch, published immediately, before a human has
72
+ promoted it to stable. Lockstep versioning holds within a channel: a canary
73
+ create-deka-app pins the *matching* canary `@dekaruntime/deka`, never a
74
+ stable one.
75
+
76
+ A canary's binaries report their **base version** on `deka --version` /
77
+ `dsc --version` — `0.59.0`, never `0.59.0-canary-d5661ed`. Promotion
78
+ republishes the exact same compiled bytes under the plain stable tag, so
79
+ the binary itself never learns it was ever a canary; only the git tag, the
80
+ R2 path and the npm version string say so.
51
81
 
52
82
  ## Platforms
53
83
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-deka-app",
3
- "version": "0.53.4",
3
+ "version": "0.53.7-canary-4551de1",
4
4
  "description": "Scaffold a new deka app",
5
5
  "bin": {
6
6
  "create-deka-app": "./index.js"
package/src/channel.js ADDED
@@ -0,0 +1,36 @@
1
+ // rfd#68 (Release Channels): a version carries its channel in its own
2
+ // string. `X.Y.Z-canary-<sha>` is a canary -- a build published under the
3
+ // `canary` npm dist-tag, from a `vX.Y.Z-canary-<sha>` release tag. Anything
4
+ // else (plain `X.Y.Z`) is stable, published under `latest`.
5
+ //
6
+ // Shared between the CLI this package ships (src/scaffold.js: the lockstep
7
+ // pin and its registry-lookup fallback) and the release pipeline that is
8
+ // NOT shipped (scripts/lib/manifest.js: R2 URL shapes) -- kept in src/ (not
9
+ // scripts/) because scripts/ is excluded from the published npm tarball
10
+ // (see package.json "files"), so anything scaffold.js depends on has to
11
+ // live somewhere that ships.
12
+ // https://github.com/dekaruntime/rfd/issues/68
13
+ const CANARY_SUFFIX = /-canary-[0-9a-f]+$/i
14
+
15
+ export function versionChannel(version) {
16
+ return CANARY_SUFFIX.test(String(version)) ? 'canary' : 'stable'
17
+ }
18
+
19
+ export function distTagFor(channel) {
20
+ return channel === 'canary' ? 'canary' : 'latest'
21
+ }
22
+
23
+ // The base version a canary's own binaries report on `--version`.
24
+ // Promotion republishes the exact same bytes under the plain tag, so a
25
+ // canary build never learns it is a canary -- its `--version` output
26
+ // always names the base version (plus a commit sha), never the
27
+ // "-canary-<sha>" suffix. Manifests written under rfd#68 carry an explicit
28
+ // `base_version` field; a manifest that predates it (or a caller that
29
+ // hasn't fetched one) falls back to stripping the suffix from the full
30
+ // version string.
31
+ export function baseVersionOf(version, manifest) {
32
+ if (manifest && typeof manifest.base_version === 'string' && manifest.base_version) {
33
+ return manifest.base_version
34
+ }
35
+ return String(version).replace(CANARY_SUFFIX, '')
36
+ }
package/src/scaffold.js CHANGED
@@ -3,6 +3,7 @@ import { spawnSync } from 'node:child_process'
3
3
  import path from 'node:path'
4
4
  import { detectPackageManager } from './package-manager.js'
5
5
  import { isSupportedPlatform, platformKey } from './platform.js'
6
+ import { versionChannel, distTagFor } from './channel.js'
6
7
 
7
8
  // Thrown for every expected failure. `message` is written straight to
8
9
  // stderr, so it always says what happened and what to do about it.
@@ -104,21 +105,33 @@ export function buildPackageJson(dirName, runtimeVersion) {
104
105
  // create or bun create, and `npm view` is a read-only registry query with
105
106
  // no project-local side effects.
106
107
  //
107
- // Falls back to the "latest" dist-tag -- never to a version we already
108
- // know is wrong -- if the registry can't be reached (offline, registry
109
- // outage, etc), and says so via `log` so the fallback is visible.
110
- export function resolveLatestRuntimeVersion({ spawn = spawnSync, cwd = process.cwd(), log = console.log } = {}) {
111
- const result = spawn('npm', ['view', RUNTIME_PACKAGE, 'version'], { cwd, encoding: 'utf8' })
108
+ // Falls back to the running version's OWN channel's dist-tag -- never to a
109
+ // version we already know is wrong, and never silently to `latest` for a
110
+ // canary -- if the registry can't be reached (offline, registry outage,
111
+ // etc), and says so via `log` so the fallback is visible.
112
+ //
113
+ // rfd#68: `channel` is the channel of the create-deka-app version that is
114
+ // running (see resolveRuntimeVersion / createApp below) -- `canary` looks
115
+ // up `@dekaruntime/deka@canary`, so `npx create-deka-app@canary myapp`
116
+ // falls back onto another canary build, never quietly onto `latest` stable.
117
+ export function resolveLatestRuntimeVersion({
118
+ spawn = spawnSync,
119
+ cwd = process.cwd(),
120
+ log = console.log,
121
+ channel = 'stable',
122
+ } = {}) {
123
+ const distTag = distTagFor(channel)
124
+ const result = spawn('npm', ['view', `${RUNTIME_PACKAGE}@${distTag}`, 'version'], { cwd, encoding: 'utf8' })
112
125
 
113
126
  const version =
114
127
  result && !result.error && result.status === 0 ? String(result.stdout || '').trim() : ''
115
128
 
116
129
  if (!version) {
117
130
  log(
118
- `> Could not resolve the latest ${RUNTIME_PACKAGE} version from the npm registry ` +
119
- '(offline, or the registry is unreachable); pinning "latest" instead.'
131
+ `> Could not resolve the ${distTag} ${RUNTIME_PACKAGE} version from the npm registry ` +
132
+ `(offline, or the registry is unreachable); pinning "${distTag}" instead.`
120
133
  )
121
- return 'latest'
134
+ return distTag
122
135
  }
123
136
 
124
137
  return version
@@ -199,12 +212,12 @@ export function createApp({
199
212
  // given create-deka-app version always produces the same project).
200
213
  //
201
214
  // The one case this doesn't cover is a create-deka-app release whose
202
- // exact-matching runtime build isn't published yet (or never will be --
203
- // e.g. a scaffolder-only patch released via publish.yml, see its header
204
- // comment). That surfaces as the install below failing, and is handled
205
- // as a fallback: re-resolve against the registry and retry once, never
206
- // silently leaving a nonexistent version pinned in the final
207
- // package.json (the ETARGET bug fixed in 0.0.3).
215
+ // exact-matching runtime build isn't published yet (there is no
216
+ // standalone scaffolder-only release path -- one publish path,
217
+ // .github/workflows/publish-runtime.yml). That surfaces as the install
218
+ // below failing, and is handled as a fallback: re-resolve against the
219
+ // registry and retry once, never silently leaving a nonexistent version
220
+ // pinned in the final package.json (the ETARGET bug fixed in 0.0.3).
208
221
  let runtimeVersion = resolveRuntimeVersion({ ownVersion })
209
222
 
210
223
  const writePackageJson = (version) => {
@@ -234,7 +247,7 @@ export function createApp({
234
247
  `This can happen when create-deka-app@${ownVersion} shipped before its matching runtime build did. ` +
235
248
  'Falling back to the latest published version instead.'
236
249
  )
237
- const fallbackVersion = resolveLatestRuntimeVersion({ spawn, cwd: targetDir, log })
250
+ const fallbackVersion = resolveLatestRuntimeVersion({ spawn, cwd: targetDir, log, channel: versionChannel(ownVersion) })
238
251
  if (fallbackVersion === runtimeVersion) {
239
252
  throw new ScaffoldError(
240
253
  `"${pm.name} install" failed in ${targetDir} (exit code ${install.status}), ` +