Skip to content

Commit 345c900

Browse files
Merge pull request #245 from contentstack/cl-7169
feat(variables): add launch:variables list, set and unset
2 parents ce75c13 + 161993a commit 345c900

79 files changed

Lines changed: 6202 additions & 89 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.talismanrc‎

Lines changed: 92 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ fileignoreconfig:
88
- filename: src/transport/rest-client.test.ts
99
checksum: 3b5751449c61f7a1d71b978ed03b9472f714e12dd1679f691bbd4dd8f84be923
1010
- filename: src/transport/cma-client.ts
11-
checksum: 035f862697541696a989bf0fb71566ddc3d0663b243156333d1909d1f373d50b
11+
checksum: 87d8c6f8a41ea520ecc5fb4b6f71467d44af95f55d1facec1de4778fe22677b3
1212
- filename: src/transport/auth-strategy.test.ts
1313
checksum: a4f3e3ea7db10dbf82abbac0207d2231ee740916f476fcda836a2268505295ef
1414
- filename: src/projects/types.ts
@@ -90,8 +90,9 @@ fileignoreconfig:
9090
- "formFieldKey"
9191
- "key: 'x-ms-blob-type', value: 'BlockBlob'"
9292
- "key: 'Content-Type', value: 'application/zip'"
93+
checksum: 7e6d6b5ff8189374ff15a93994764c742ca250b80c7c2d1a84cff0f0785b05c6
9394
- filename: test/fixtures/README.md
94-
checksum: 84200663e97129b03a28240a2cb722d4e45c61fff9b0b19cbcef676582cfc1dd
95+
checksum: d801c84c8b7d7f38f967573e9a3a70da4405b7cbcbf10d2a6e5be3d65fb3daa1
9596
allowed_patterns:
9697
- "formFieldKey"
9798
- "\\{key, value\\}"
@@ -121,6 +122,7 @@ fileignoreconfig:
121122
- filename: src/environments/environment.builder.test.ts
122123
ignore_detectors:
123124
- filename
125+
checksum: 8b7e3207630f19170dd08ca639ebca8af6bc0d70db633b98e66eedde6d2ea641
124126
- filename: src/environments/environment.update.ts
125127
checksum: b1e15e174f98a875f97e0683182638f93966ef4c498135d36df620a28338aacb
126128
ignore_detectors:
@@ -229,7 +231,7 @@ fileignoreconfig:
229231
- "a project name passed on argv to the project resolver"
230232
- "expect\\(Object.keys\\(DEPENDENCIES\\)\\).toEqual\\(\\['project', 'env'\\]\\)"
231233
- filename: AGENTS.md
232-
checksum: 7a582c03c5326b0d1c2465a0060da0763944dc295d6f6d7ab1ee4bf5ce047181
234+
checksum: ace82b5dc26aa4b681378ef313ed3e5eeb2a5d7f3ab47d6305dc9c97e885f244
233235
allowed_patterns:
234236
- "Do not add an exemption to a guard to make a new file pass"
235237
- "passes its own error wording to `client.request\\(req, MESSAGES\\)`"
@@ -253,9 +255,9 @@ fileignoreconfig:
253255
- filename: src/git/local-repository.ts
254256
checksum: b9091ed135dfebdf590a5412bbfba2b2f96d4a177cf944a20909b93405268e9f
255257
- filename: test/guards/layering.test.ts
256-
checksum: 58f43e0ed643b9317538d12e44ba449d046e762dee219ff84f3907bd9dea3531
258+
checksum: 6740eea4e84f088081e31ac0c12c0abb2c402dcebbe0eb0ef454f60873da0194
257259
- filename: src/commands/launch/projects/create.test.ts
258-
checksum: 1d5063992d0a7cfb91871ab00f79123bf71806ddc9faac80952cf279d165aec5
260+
checksum: 2c407c366f2a1da2647fc6eb7e6ad1bb8cbe3c7f901090432ab0e27df2e5d4d6
259261
- filename: src/commands/launch/projects/delete.test.ts
260262
checksum: d67d8a804d14f9b809153d10b0cf9d5e52b70f9e0b65678ebb1663a7d2da22c1
261263
- filename: test/integration/projects-delete.test.ts
@@ -299,37 +301,115 @@ fileignoreconfig:
299301
- filename: src/functions/function.logger.test.ts
300302
checksum: 840b2b2b7f938e0862881871e8d568112631c58e12cf6c8a5be32e7552b8cf9e
301303
- filename: src/transport/cma-client.test.ts
302-
checksum: 018e2c76b66485592c1660301a2c4c8c232c4efe082dee98e1baed5a2e6956f5
304+
checksum: 9eb4958cd7fa07822954d14c5860c5ca18f0880e4390716ebfa9c826add49311
303305
- filename: src/core/catalog.test.ts
304306
checksum: bf8c203a8efc40a75f5407ceb29a639ea9a6e1fa081d02260def2d7e0fab958a
305307
- filename: test/credential-guard.setup.ts
306308
checksum: 519ccbeb0552fdb1d5f27308c56477c0258ee6cc0adec8f618e8e5bc047cbf6d
307309
- filename: src/environments/types.ts
308-
checksum: a637325f841e8491a4c058998e6a523461abc7b3b150b9eee0c2f7190a80205e
310+
checksum: 9c2387b8bd819af79b256f8638d54a33c41bccc1ab04f02dfd1cda48c035e6e7
309311
- filename: src/commands/launch/env/get.test.ts
310312
checksum: 26863ca165d20df9a9ea8afac1eda71c9f96be15fe23bddb4fd7ddfcefab2256
311313
- filename: test/integration/environments-delete.test.ts
312314
checksum: 7df1b364699953cad40b7aea3beeaaae6e2b781c72b7ae8f36ea78ebf50887e1
313315
- filename: src/commands/launch/env/delete.test.ts
314316
checksum: 14116789eb5f9000f2a7d6f569cd15aabf2a1ec3b127ed4427afe13fd515f0c2
315317
- filename: src/environments/environment.errors.ts
316-
checksum: 6696c36c85b5b36d6ade7897b196ad554ef52d615f7f5e61faaf825e4f3b3a31
318+
checksum: 37256331379dfda26ae10a3bc46399a716fb2740151d47b34f0f8eaeeeef48da
317319
- filename: src/core/prompt.ts
318-
checksum: 54a94bca9c39545606d51db0966e040ac03b43539315606c61c1cc64d11ec062
320+
checksum: 3285bdbccc31cba5b50eafe8ed8be4750af6339078a3eaee6df1e0630979aa2c
319321
- filename: src/core/prompt.test.ts
320-
checksum: 783aa03b20d8b2b2e7259fc11c2c35dc8318f1b5e0fdd566b0f61693a47bfb14
322+
checksum: 2deacd402e8d7f79458ee6d3917205c6dbe5cd7e6a98a2e5c49e37ac1a9d57c4
321323
- filename: test/integration/environments-update.test.ts
322324
checksum: 650627ec2cc6fed82f000b0e0a368a3725238dbb64ec18a5866c2fa3abb3a27f
323325
- filename: src/commands/launch/env/update.ts
324326
checksum: 06add97108d878eaf415e32160439b8963683e63a0e37ce77a56f66b88383c7a
325327
- filename: src/commands/launch/env/update.test.ts
326328
checksum: 2da219594e7bdd589adc0eff9ff035252a75aaa51dfa20514b18fd3266d7b752
327329
- filename: README.md
328-
checksum: 88e66114eb9049a642a7469458b45b182b19890efe91ef2f6220e9b24ee8814a
330+
checksum: c870bc0f5e1b0c43f8320d2eb9807241353bfc8fab0e1339becc28183067b06d
329331
allowed_patterns:
330332
- "password-protection"
331333
- "-p, --password"
332334
- "-u, --username"
333335
- filename: test/integration/environments-create.test.ts
334-
checksum: 9ffcc5cc8034fff34a19b6f04c737ff02aedbd3d3d919246d51c800aafb17693
336+
checksum: 9582c39ab4732e6ab530c6d80b5a08bac28920ba5421608527479fe5bace8c95
337+
- filename: src/commands/launch/variables/list.test.ts
338+
checksum: 87ccb762f4931326fc50bca1c01aeb4a16d552e4dfa141d00370fdfafa4363be
339+
- filename: src/commands/launch/variables/set.test.ts
340+
checksum: 5f8029b2d49410dd59576b6bda5a2ad5cb452703fa1bf6fd4690f2ac356abea5
341+
- filename: src/commands/launch/variables/unset.test.ts
342+
checksum: 857da0c6e10243477aa78cd112a126770f679b75b7b67eab929eeb2f76a41c9d
343+
- filename: src/commands/launch/variables/unset.ts
344+
checksum: b25c2b1547a1ed5b216c57b26bc18744ad04746e01efcc40e9469d1a5e472537
345+
- filename: src/environments/environment.errors.test.ts
346+
checksum: 33ae71db0a46173c903659438a77d1d441797a8296e0591dbaa48512f32a4cab
347+
- filename: src/stacks/stacks.api.test.ts
348+
checksum: db0c613f10361fa6aafa71cc09d217a3c5a7f924523901469b174807b7b9b237
349+
- filename: src/stacks/stacks.api.ts
350+
checksum: 7241b9c2c6e946c11849bb5fb21842c03eca09f9ed6c901be198fd544ce8f769
351+
- filename: src/variables/variable.chooser.ts
352+
checksum: 15a6b8a1a974c8d0396ac18d8c9d39c8bc9f70efbf41ce0eef79180ce16b2f04
353+
- filename: src/variables/variable.create.test.ts
354+
checksum: 48b9864639a01e05b8c6de9ce5ef1abad7ba990ecfbe7f47d0df3d3e759344b8
355+
- filename: src/variables/variable.dotenv.test.ts
356+
checksum: c3d5e33189736bb42b7c4fac7375cf0307681b34feca4830b49331f55a130f78
357+
- filename: src/variables/variable.dotenv.ts
358+
checksum: 337273d2ce8d987a6e7cf6a0f743df5031c24ac719cbe31e99fff16d7ffefa79
359+
- filename: src/variables/variable.files.test.ts
360+
checksum: d8b0efd6bb448c4d501ba52c47119b352ef29d6b5b66cec0e7d373a0ce91a36c
361+
- filename: src/variables/variable.inputs.test.ts
362+
checksum: 4b3b9a6c353d099a65ef8f522cff8e46e5c0edbf66bcdb59e0d6dd4f87c78c84
363+
- filename: src/variables/variable.inputs.ts
364+
checksum: 0f572a86e0c0edbe707882df623a3a7f69715572812ae655eb6aa5e4579b496b
365+
- filename: src/variables/variable.merge.test.ts
366+
checksum: 581a5cc5d9d23223643bd461525c6755205ebf16f33ae7388c8e88de19461fbf
367+
- filename: src/variables/variable.merge.ts
368+
checksum: f096c83e4894e6d96b620873815bc0f85c2a79c73b353c1a518bb870ca48976b
369+
- filename: src/variables/variable.page.test.ts
370+
checksum: 9a4e63c0dbfd35b499149a98ce5642787097e9491746b4b874b2eda88f1d2b50
371+
- filename: src/variables/variable.parse.test.ts
372+
checksum: 01441ffca77438dbd29420ad38fbfee160dfa535434e4a3eca1c57c47eeebaa0
373+
- filename: src/variables/variable.parse.ts
374+
checksum: 9dbb9e0c8715e319aa70a4b6a49ae255a3a89207081f6bff0f4c21ea91eed7e7
375+
- filename: src/variables/variable.presenter.test.ts
376+
checksum: 62e8b0eff16ed4408d929092ce6808aeabea001a6cc15780d46c4ac4226eec3d
377+
- filename: src/variables/variable.presenter.ts
378+
checksum: ee8e4dcf75ad7e849d1e8e64ce6a6549d13fc62dc9aa322d96eb2e725d629db5
379+
- filename: src/variables/variable.set.test.ts
380+
checksum: f6a59e15775ea4247ec3860d4d3fad495b1624ed8a9d834c79a3fcc3033df58e
381+
- filename: src/variables/variable.sources.test.ts
382+
checksum: 63ad95e998cbc6d33fabe4ce76797e8788b17abec3833b4fed2360eab01a6f79
383+
- filename: src/variables/variable.sources.ts
384+
checksum: c2c7e442c6fed29b11843850ad86c8603540fcc174e1fac79993c8e26d95e8dc
385+
- filename: src/variables/variable.stack.test.ts
386+
checksum: 75db498059c80145ed72ef4ec4c3e787cca31ab1e7e41ad563ec90fa6dfc035d
387+
- filename: src/variables/variable.stack.ts
388+
checksum: 0c5116d39bacccdb6e813357dd091e90274383761832f19d3a9b5433a21d99ae
389+
- filename: src/variables/variable.summary.test.ts
390+
checksum: 8b214a1f1f43ac1a76434b75e4ff1ffd73a9e73dc2a0d6bae9ca43fd678182e5
391+
- filename: src/variables/variable.summary.ts
392+
checksum: 0da287557a5c4280074d1a26aeff4f7d95b205e4266ff47c18b62665134f5bdc
393+
- filename: src/variables/variable.unset.test.ts
394+
checksum: ef31b77f66913a10f1b865b7a6568bef71ff02803c6636971605b840b489671f
395+
- filename: src/variables/variable.unset.ts
396+
checksum: 250ce39c694d745370717771dc16d20e2f6b9516f43043900d4a40bde7fc04db
397+
- filename: src/variables/variable.values.test.ts
398+
checksum: 56725066fdabce3afea373c70bee10a6db4c1409e3a8f6f1e7f191ea6e602419
399+
- filename: src/variables/variable.values.ts
400+
checksum: 70f23d8c993b0f0baf6522a918b2f011485a5d9c038548f06dea6ea1d0e83e0e
401+
- filename: src/variables/variable.writer.test.ts
402+
checksum: 7dcd68d3c1b0df258fa86455b1d02547255be8fe77b656b3a7188824225220ab
403+
- filename: src/variables/variable.writer.ts
404+
checksum: a6fc266af2bae734ff1bb716c854a154b5c3e858a0ba2798fc17d5bdbdfde1b9
405+
- filename: src/variables/variables.api.test.ts
406+
checksum: 33d41fb8383e0908260ca3df1d126227e614330acde0c6f195b877245e51cfd6
407+
- filename: src/variables/variables.api.ts
408+
checksum: 2fca1f8fc784d5f859b13a24bd3cd09bda7aa92e7b3d65c0ecc92d4c0de954fa
409+
- filename: test/fixtures/cms-environment-variables.json
410+
checksum: cb2cbb2d1d858b1cf2115c218a0ecca04ce04baf054fe11fe6123589c1afce27
411+
- filename: test/integration/variables-list.test.ts
412+
checksum: c0ccb0bc394c9013f75b69c4354cc5d52b2f6916a35af902de36bef1cda1648c
413+
- filename: test/integration/variables-set-unset.test.ts
414+
checksum: f211ebcf35f39b26e5a55d81f468287670ade819899c6635a579b4eae68b1c50
335415
version: "1.0"

‎AGENTS.md‎

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,13 @@ src/
141141
EnvironmentBuilder that turns them into a CreateEnvironmentInput, and the
142142
EnvironmentCreator / EnvironmentUpdater behind launch:env:create / :update.
143143
It reaches deployments, git and uploads, for create
144+
stacks/ the Contentstack stack and delivery-token lookups behind --from-stack, through the
145+
CmaSession (no Launch endpoint)
146+
variables/ the shared variable-source resolver (--var, --dotenv, --from-stack, a detected .env file), the
147+
read-modify-write writer behind launch:variables:set / :unset, and the masked
148+
presenter behind :list. It has no repository of its own: it reads and writes through
149+
environments, and reads the stack template through its own VariablesApi. EnvironmentBuilder calls back into it for the create commands, so the
150+
two folders each name the other in the layering allow-list
144151
deployments/ the deployment repository, the status classification, the
145152
wait/stream loop and LogTail that projects:create, deployments:create
146153
and logs:get all drive, and the DeploymentFollower that watches one
@@ -314,6 +321,48 @@ the yellow `Project not deleted.` and exits 3 (`EXIT_CANCELLED`) without the `Er
314321
`CancelledError` would print; Ctrl-C at the question is still a `CancelledError`. The success line is
315322
the green `✔ Project deleted successfully.`, matching `projects:update`.
316323

324+
**Environment variables (`launch:variables:*`).** There is no per-variable endpoint, so `set` and `unset`
325+
are `GET .../environments/:uid`, merge locally, then `PUT` the complete `environmentVariables` array and
326+
nothing else: the update body is partial on the server, so no other environment field can be dropped by it.
327+
Every source is resolved and every value prompted for before the `GET`, so no user interaction sits between
328+
the read and the write; `unset` reads once to validate the keys and name the environment, confirms, then
329+
reads again immediately before the `PUT`. Two writers racing lose one change - the API offers no ETag and no
330+
partial update (CL-7179 is the proposed `PATCH`) - and FR34 asks that this be documented rather than treated
331+
as a defect.
332+
333+
`collectVariables` in `src/variables/variable.sources.ts` is the one resolver: stack (`--from-stack`), then
334+
`--dotenv`, then `--var`, later wins, and the summary line names every source's new keys and every override.
335+
With no source flag, `set` on a terminal shows the `Add variables from` checklist (`chooseSources` in
336+
`src/variables/variable.chooser.ts`, shared with the create commands, which add a `Skip` choice); ticking nothing
337+
prints a yellow `Skipped adding variables.` and sends nothing (sources that supply no variable print a yellow
338+
`No changes made.`). Without a terminal, `set` auto-detects `.env.local` then `.env`
339+
under `--data-dir`, always printing the file it chose, and fails with exit 2 when there is none. A bare `--var KEY` is a hidden prompt on a terminal, a stdin read for exactly one bare key without one, and
340+
exit 2 naming `--dotenv -` for two or more. The API refuses an empty value, so `KEY=` is a usage error naming
341+
the key, and an empty value inside a dotenv file is skipped with its key reported. No value reaches stdout, a
342+
prompt message, a confirmation or an error: `list` masks through `redactedColumn`, and a failed `PUT` is worded from
343+
`ENVIRONMENT_ERROR_MESSAGES`, never from the API's own text.
344+
345+
`projects:create` and `env:create` take `--var` and `--dotenv` and reach the same resolver through
346+
`EnvironmentBuilder`, which asks last - after Contentstack Authentication, where V1 asked - with no auto-detection.
347+
With neither flag it offers a checkbox over the sources plus `Skip adding environment variables`, which cannot be
348+
combined with the others; without a terminal it sends an empty list.
349+
350+
**`--from-stack` and `--alias`.** `--from-stack` is a bare flag on `variables:set`, `projects:create` and
351+
`env:create`; `--alias <name>` (`-a`) names a delivery token saved with `csdx auth:tokens:add`, and is a usage error
352+
without `--from-stack` (`aliasRequiresFromStack`). With an alias the token is read from the `tokens` config object
353+
(indexed by alias, so a dot in the alias is safe) and must be a delivery token with an environment. Without an alias
354+
a terminal gets a stack picker then a delivery-token picker (names only); without a terminal it is a usage error
355+
naming `--alias`. The five variables come from `GET /cms/environment-variables` (API host and CDN, scheme stripped)
356+
plus the stack's API key, the token and its environment. `src/stacks/` owns the Contentstack stack lookups through
357+
`CmaSession.fetchStacks` / `fetchDeliveryTokens`, which page 100 at a time; `variables` may import `stacks` and
358+
`environments` and nothing else (`RESOURCE_EDGES`). A delivery token value is never printed or logged.
359+
360+
Two harness traps. `@oclif/test`'s `runCommand` joins argv with spaces and splits it again, so a value containing a
361+
space must be passed pre-quoted there (`'"MSG=hello world"'`); the real parser keeps it whole, which
362+
`src/variables/variable.inputs.test.ts` proves against `Parser.parse`. And a test that lets a bare key reach the
363+
non-terminal path reads the real `process.stdin` and hangs the run, so such a test must answer on a terminal or
364+
fake `readStdin`.
365+
317366
**A prompt never answers with something that is not on its list.** Two mechanisms, chosen by
318367
whether the choices need searching. `askOption` in `src/core/prompt.ts` is the
319368
default and the only choice helper left; the two prompts that still need a search box build their
@@ -740,10 +789,9 @@ not a total one, so a large archive that is still moving is never cut off.
740789
It uses `node:http`/`node:https` rather than `fetch` so `nock` can intercept it - nock 13 does not see
741790
undici's `fetch`.
742791

743-
**Environment variables and argv.** `environmentVariables` is always `[]` on create: the variable
744-
sources are CL-7169. The shape is built by a function that takes no input at all, so there is no
745-
argv path into it to grow by accident, and a test passes `var`, `env-file` and `from-stack` into the
746-
request to prove the body is unchanged. **No secret may reach argv** (FR30, G16).
792+
**Environment variables and argv.** On create, `environmentVariables` comes only from `variablesForCreate`, called last by
793+
`EnvironmentBuilder`, so the sources are the explicit `--var`, `--dotenv` and `--from-stack` inputs and the prompt
794+
checklist and nothing else; the create summary says `ready to set` because the environment does not exist yet. **No secret may reach argv** (FR30, G16).
747795

748796
**Cross-flag rules.** A rule that is pure flag-versus-flag and evaluable from argv alone belongs in
749797
oclif's native `exclusive` / `relationships` on the flag definition, where it also shows in `--help` -

0 commit comments

Comments
 (0)