From f7b865cd06986ed8811686576ac55727c386df37 Mon Sep 17 00:00:00 2001 From: Harshi-Shah-CS Date: Wed, 4 Nov 2026 15:23:08 +0530 Subject: [PATCH 1/2] fix(variables): skip the create checklist on a bare Enter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit projects:create and env:create on a terminal ask "Add environment variables" when no variable source is given. The checkbox refused an empty answer, so skipping meant moving to "Skip adding environment variables", ticking it and pressing Enter. A bare Enter with nothing ticked now skips the same way and prints the same "Skipped adding environment variables." line. The Skip choice stays, and combining it with a source is still a usage error. variables:set already accepted an empty answer and keeps its own message. #claude_code# 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Co-authored-by: Sakshi Koli --- src/variables/variable.chooser.ts | 18 ++++++++---------- src/variables/variable.create.test.ts | 13 +++++++++++-- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/variables/variable.chooser.ts b/src/variables/variable.chooser.ts index 8702d1c7..e5be2165 100644 --- a/src/variables/variable.chooser.ts +++ b/src/variables/variable.chooser.ts @@ -66,19 +66,17 @@ export async function chooseSources( { name: TYPED_CHOICE, value: TYPED_CHOICE }, ...(prompt.skippable ? [{ name: SKIP_CHOICE, value: SKIP_CHOICE }] : []), ]; - const picked = await askChoices(services.ux, prompt.message, choices, { requireOne: prompt.skippable }); + const picked = await askChoices(services.ux, prompt.message, choices, { requireOne: false }); - if (picked.includes(SKIP_CHOICE)) { - if (picked.length > 1) { - throw new UsageError(`'${SKIP_CHOICE}' cannot be combined with the other options.`); - } - - services.ux.print('Skipped adding environment variables.'); - - return undefined; + if (picked.includes(SKIP_CHOICE) && picked.length > 1) { + throw new UsageError(`'${SKIP_CHOICE}' cannot be combined with the other options.`); } - if (picked.length === 0) { + if (picked.length === 0 || picked.includes(SKIP_CHOICE)) { + if (prompt.skippable) { + services.ux.print('Skipped adding environment variables.'); + } + return undefined; } diff --git a/src/variables/variable.create.test.ts b/src/variables/variable.create.test.ts index 78f184e2..7c2bf69d 100644 --- a/src/variables/variable.create.test.ts +++ b/src/variables/variable.create.test.ts @@ -128,6 +128,15 @@ describe('variable create', () => { }); }); + it('lets a bare Enter through the checkbox with nothing selected', async () => { + const { services, io, asked } = fakes({ answers: { 'Add environment variables': [] } }); + + await variablesForCreate(NONE, services, io); + + const validate = asked[0].payload.validate as (picked: unknown) => true | string; + expect(validate([])).toBe(true); + }); + it('returns nothing and says so when Skip is chosen', async () => { const { services, io, printed } = fakes({ answers: { 'Add environment variables': [SKIP] } }); @@ -233,11 +242,11 @@ describe('variable create', () => { expect(output).not.toContain('never-printed-value'); }); - it.each([[undefined], [[]]])('returns nothing and prints no summary when nothing was selected (%p)', async (answer) => { + it.each([[undefined], [[]]])('skips and says so, as Skip does, when nothing was selected (%p)', async (answer) => { const { services, io, printed } = fakes({ answers: { 'Add environment variables': answer } }); expect(await variablesForCreate(NONE, services, io)).toEqual([]); - expect(printed).toEqual([]); + expect(printed).toEqual(['Skipped adding environment variables.']); }); it('propagates a cancelled path prompt, an unreadable file and a malformed typed line', async () => { From f1d22158eb08aa81cbbf5d60b506fe0ef3de7e85 Mon Sep 17 00:00:00 2001 From: Harshi-Shah-CS Date: Wed, 4 Nov 2026 15:23:32 +0530 Subject: [PATCH 2/2] fix(variables): drop --no-vars from projects:create and env:create MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Variables are never required: without a terminal a create with no variable source sends an empty list and asks nothing, and on a terminal a bare Enter at "Add environment variables" now skips it. --no-vars only skipped that one checklist, so it goes, with the noVarsAlone rule and the noVars request field. Passing it is now oclif's unknown-flag error with exit 2. AGENTS.md and the README follow. The .talismanrc checksums are refreshed for every changed file the pre-push Talisman scan flags (file names, flag names and the words secret/token in prose; no secret). #claude_code# 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Co-authored-by: Sakshi Koli --- .talismanrc | 20 ++++++++++---------- AGENTS.md | 7 +++---- README.md | 6 ++---- src/commands/launch/env/create.test.ts | 5 ++--- src/commands/launch/env/create.ts | 6 ++---- src/commands/launch/projects/create.test.ts | 5 ++--- src/commands/launch/projects/create.ts | 6 ++---- src/environments/environment.builder.ts | 1 - src/environments/types.ts | 1 - src/variables/variable.create.test.ts | 9 --------- src/variables/variable.create.ts | 5 ----- src/variables/variable.inputs.test.ts | 15 ++------------- src/variables/variable.inputs.ts | 4 ---- src/variables/variable.rules.test.ts | 19 +------------------ src/variables/variable.rules.ts | 10 ---------- test/integration/environments-create.test.ts | 9 +++++---- test/integration/projects-create.test.ts | 12 ++++++------ 17 files changed, 37 insertions(+), 103 deletions(-) diff --git a/.talismanrc b/.talismanrc index 371c4f04..84e0e091 100644 --- a/.talismanrc +++ b/.talismanrc @@ -93,7 +93,7 @@ fileignoreconfig: - "'SECRET=hunter2'" - "formFieldKey" - filename: test/integration/projects-create.test.ts - checksum: 4826ca20f0c7fe1f23b82598ceed0a374199e2bb8b604b676efcf720244ff961 + checksum: c567d31fb18d0910410ce455c0a1b2f8ce6c8d46038396ec813ef73bd5fb8105 - filename: test/fixtures/README.md checksum: d801c84c8b7d7f38f967573e9a3a70da4405b7cbcbf10d2a6e5be3d65fb3daa1 allowed_patterns: @@ -236,7 +236,7 @@ fileignoreconfig: - "a project name passed on argv to the project resolver" - "expect\\(Object.keys\\(DEPENDENCIES\\)\\).toEqual\\(\\['project', 'env'\\]\\)" - filename: AGENTS.md - checksum: ba37b6b17d97940a6f7d5e69a531796ab0ee5b6859a9cd5cbdec56e4b7731b26 + checksum: 3379e8c597c8306e7377e60667f7df6e599e45e289928bc88b217356aa43feb1 allowed_patterns: - "Do not add an exemption to a guard to make a new file pass" - "passes its own error wording to `client.request\\(req, MESSAGES\\)`" @@ -259,7 +259,7 @@ fileignoreconfig: - filename: test/guards/layering.test.ts checksum: 55893e6e919b1e462afc989110cb9360e38aa18d06de932587beaa9006042639 - filename: src/commands/launch/projects/create.test.ts - checksum: 9c40b4b6ed4f7d678ecb921a71f5af7284cd685c1337f47144456ae43a38b1ad + checksum: 2c407c366f2a1da2647fc6eb7e6ad1bb8cbe3c7f901090432ab0e27df2e5d4d6 - filename: src/commands/launch/projects/delete.test.ts checksum: d67d8a804d14f9b809153d10b0cf9d5e52b70f9e0b65678ebb1663a7d2da22c1 - filename: test/integration/projects-delete.test.ts @@ -311,7 +311,7 @@ fileignoreconfig: - filename: test/credential-guard.setup.ts checksum: 519ccbeb0552fdb1d5f27308c56477c0258ee6cc0adec8f618e8e5bc047cbf6d - filename: src/environments/types.ts - checksum: 6c054295075e51e9ce0f4514ebdc86a48bb74db9932a2baaa9f9158e9c14c6e8 + checksum: 2825d0e70757022e518465b134878b8cc8f9eccaf4e9ad088d73a31b9a35a826 - filename: src/commands/launch/env/get.test.ts checksum: 6e739ef12bc0d887e652e23ee54d9fac30dd6a3505cf464cdaefc0e696cf3e51 - filename: test/integration/environments-delete.test.ts @@ -331,13 +331,13 @@ fileignoreconfig: - filename: src/commands/launch/env/update.test.ts checksum: 2da219594e7bdd589adc0eff9ff035252a75aaa51dfa20514b18fd3266d7b752 - filename: README.md - checksum: 112b973a24e59f79786df1b85b83ea35b1e355c52a8cbf3b28d98511959c60c8 + checksum: d955f95b66f10259eb2ddbe1935a67ce3c7f3a28187f0398e0af39ff75267c01 allowed_patterns: - "password-protection" - "-p, --password" - "-u, --username" - filename: test/integration/environments-create.test.ts - checksum: 0c64a4408d3c150a33c442403688d1e1d058f415cfdba704e372455927daa7e4 + checksum: 538527a26bc002aa21319aa615c9a9f00aaed494d0bdefc8db75c0eff3f8ec54 - filename: src/commands/launch/variables/list.test.ts checksum: 87ccb762f4931326fc50bca1c01aeb4a16d552e4dfa141d00370fdfafa4363be - filename: src/commands/launch/variables/set.test.ts @@ -353,9 +353,9 @@ fileignoreconfig: - filename: src/stacks/stacks.api.ts checksum: d59622ca6411b93d5469a1895b08ccde4b9cd83fbb909c82076ea70d74b5e1e4 - filename: src/variables/variable.chooser.ts - checksum: c776a4184eb1819055622784bc6f3342b67bc1babdca0cdbbe72a4a871cc2498 + checksum: 767bbcee93b0c10c5c9d0b526ce57770cc6323be52d8a4cc1c0452c880b5ab8e - filename: src/variables/variable.create.test.ts - checksum: c888e2a4aca9c6855c79d743368387aeb0ab5db907beca8bef1113bc05a5260d + checksum: a2650ca8e081afcf76c801d20e2df4baa96f814d1513080ba24971db0ae3a1bf - filename: src/variables/variable.dotenv.test.ts checksum: c3d5e33189736bb42b7c4fac7375cf0307681b34feca4830b49331f55a130f78 - filename: src/variables/variable.dotenv.ts @@ -365,9 +365,9 @@ fileignoreconfig: - filename: src/variables/variable.files.test.ts checksum: d8b0efd6bb448c4d501ba52c47119b352ef29d6b5b66cec0e7d373a0ce91a36c - filename: src/variables/variable.inputs.test.ts - checksum: c434fd7f32ab0bd17db8f214ba54861b7d8ae8d8481dbbc1978f9dab35fd2429 + checksum: 4b3b9a6c353d099a65ef8f522cff8e46e5c0edbf66bcdb59e0d6dd4f87c78c84 - filename: src/variables/variable.inputs.ts - checksum: 050b93e158a1ff29f309f1531b085aa9f0327b47a8029038356869b2864531b2 + checksum: 0f572a86e0c0edbe707882df623a3a7f69715572812ae655eb6aa5e4579b496b - filename: src/variables/variable.merge.test.ts checksum: 581a5cc5d9d23223643bd461525c6755205ebf16f33ae7388c8e88de19461fbf - filename: src/variables/variable.merge.ts diff --git a/AGENTS.md b/AGENTS.md index 8ff3847f..83c0c9bd 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -361,10 +361,9 @@ than return a truncated list. `projects:create` and `env:create` take `--var` and `--dotenv` and reach the same resolver through `EnvironmentBuilder`, which asks last - after Contentstack Authentication, where V1 asked - with no auto-detection. With neither flag it offers a checkbox over the sources plus `Skip adding environment variables`, which cannot be -combined with the others; without a terminal it sends an empty list. `--no-vars` is the flag form of that Skip -choice, so a fully flagged create on a terminal asks nothing: it sends an empty list without the checkbox. Combined -with `--var`, `--dotenv` or `--from-stack` it is a usage error from the `noVarsAlone` rule rather than oclif's -`exclusive`, whose `--help` usage line would show those three sources excluding each other. +combined with the others; a bare Enter with nothing ticked skips the same way, and without a terminal it sends an +empty list. There is no `--no-vars` flag: variables are never required, so a fully flagged create on a terminal +stops only at that checkbox, and a pipe or CI run skips it. **`--from-stack` and `--alias`.** `--from-stack` is a bare flag on `variables:set`, `projects:create` and `env:create`; `--alias ` (`-a`) names a delivery token saved with `csdx auth:tokens:add`, and is a usage error diff --git a/README.md b/README.md index d4e28add..da7eeeae 100644 --- a/README.md +++ b/README.md @@ -319,7 +319,7 @@ USAGE $ csdx launch:env:create [-c ] [-d ] [--org ] [--project ] [--name ] [--description ] [--branch ] [--framework ] [--build-cmd ] [--server-cmd ] [--output-dir ] [--res-mode ] [--auto-deploy ] [--cs-auth ] [--var ...] [--dotenv - ...] [--from-stack] [-a ] [--no-vars] + ...] [--from-stack] [-a ] FLAGS -a, --alias= Alias of a delivery token saved with csdx auth:tokens:add, used with --from-stack without a @@ -337,7 +337,6 @@ FLAGS --from-stack Import the variables of a Contentstack stack. Asks for the stack and a delivery token on a terminal --name= Environment name (200 characters or fewer) - --no-vars Create the environment with no variables, without asking for them on a terminal --org= Organization UID --output-dir= Output directory --project= Project name or UID @@ -611,7 +610,7 @@ USAGE $ csdx launch:projects:create [-c ] [-d ] [--org ] [--type ] [--name ] [--description ] [--env-name ] [--branch ] [--framework ] [--build-cmd ] [--server-cmd ] [--output-dir ] [--res-mode ] [--auto-deploy ] [--cs-auth ] [--var ...] [--dotenv - ...] [--from-stack] [-a ] [--no-vars] + ...] [--from-stack] [-a ] FLAGS -a, --alias= Alias of a delivery token saved with csdx auth:tokens:add, used with --from-stack without a @@ -630,7 +629,6 @@ FLAGS --from-stack Import the variables of a Contentstack stack. Asks for the stack and a delivery token on a terminal --name= Project name (200 characters or fewer) - --no-vars Create the environment with no variables, without asking for them on a terminal --org= Organization UID --output-dir= Output directory --res-mode= Response mode (buffered | streaming) diff --git a/src/commands/launch/env/create.test.ts b/src/commands/launch/env/create.test.ts index 55ce6aa0..95fcc68b 100644 --- a/src/commands/launch/env/create.test.ts +++ b/src/commands/launch/env/create.test.ts @@ -7,7 +7,7 @@ import { catalog, resolution } from '../../../resources'; import { DEPLOYMENT_WAIT_TIMEOUT_MS } from '../../../deployments/deployment.watcher'; import { EnvironmentCreator } from '../../../environments/environment.create'; import { serverCommandFrameworkGate } from '../../../environments/environment.inputs'; -import { aliasRequiresFromStack, noVarsAlone } from '../../../variables/variable.rules'; +import { aliasRequiresFromStack } from '../../../variables/variable.rules'; import EnvironmentsCreate from './create'; function commandUnderTest(resolved: Record) { @@ -102,10 +102,9 @@ describe('launch:env:create', () => { dotenv: {}, 'from-stack': {}, alias: {}, - 'no-vars': {}, }); expect(Object.keys(EnvironmentsCreate.flags).sort()).toEqual(Object.keys(EnvironmentsCreate.inputs).sort()); - expect(EnvironmentsCreate.rules).toEqual([serverCommandFrameworkGate, aliasRequiresFromStack, noVarsAlone]); + expect(EnvironmentsCreate.rules).toEqual([serverCommandFrameworkGate, aliasRequiresFromStack]); }); it('describes --name and --description as the environment its own, leaving the project wording alone', () => { diff --git a/src/commands/launch/env/create.ts b/src/commands/launch/env/create.ts index 441c0072..1c8e9bed 100644 --- a/src/commands/launch/env/create.ts +++ b/src/commands/launch/env/create.ts @@ -3,7 +3,7 @@ import { flagsFor, inputs } from '../../../core/inputs'; import { defaultWatchTiming } from '../../../deployments/deployment.watcher'; import { EnvironmentCreator } from '../../../environments/environment.create'; import { serverCommandFrameworkGate, withEnvironmentWording } from '../../../environments/environment.inputs'; -import { aliasRequiresFromStack, noVarsAlone } from '../../../variables/variable.rules'; +import { aliasRequiresFromStack } from '../../../variables/variable.rules'; const createInputs = inputs({ org: { required: true }, @@ -22,7 +22,6 @@ const createInputs = inputs({ dotenv: {}, 'from-stack': {}, alias: {}, - 'no-vars': {}, }); export default class EnvironmentsCreate extends LaunchCommand { @@ -39,7 +38,7 @@ export default class EnvironmentsCreate extends LaunchCommand { const resolved = this.resolved; @@ -63,7 +62,6 @@ export default class EnvironmentsCreate extends LaunchCommand; @@ -101,7 +101,7 @@ describe('launch:projects:create', () => { }); it('declares only the framework gate as a rule, leaving GitHub-only flags on FileUpload to a confirmation', () => { - expect(ProjectsCreate.rules).toEqual([serverCommandFrameworkGate, aliasRequiresFromStack, noVarsAlone]); + expect(ProjectsCreate.rules).toEqual([serverCommandFrameworkGate, aliasRequiresFromStack]); }); it('declares every flag it reads and requires only the organization', () => { @@ -123,7 +123,6 @@ describe('launch:projects:create', () => { 'dotenv', 'from-stack', 'alias', - 'no-vars', ]); expect(Object.keys(ProjectsCreate.flags).sort()).toEqual(Object.keys(ProjectsCreate.inputs).sort()); expect( diff --git a/src/commands/launch/projects/create.ts b/src/commands/launch/projects/create.ts index 47408413..e4d3613b 100644 --- a/src/commands/launch/projects/create.ts +++ b/src/commands/launch/projects/create.ts @@ -3,7 +3,7 @@ import { flagsFor, inputs } from '../../../core/inputs'; import { defaultWatchTiming } from '../../../deployments/deployment.watcher'; import { serverCommandFrameworkGate } from '../../../environments/environment.inputs'; import { ProjectCreator } from '../../../projects/project.create'; -import { aliasRequiresFromStack, noVarsAlone } from '../../../variables/variable.rules'; +import { aliasRequiresFromStack } from '../../../variables/variable.rules'; const createInputs = inputs({ org: { required: true }, @@ -23,7 +23,6 @@ const createInputs = inputs({ dotenv: {}, 'from-stack': {}, alias: {}, - 'no-vars': {}, }); export default class ProjectsCreate extends LaunchCommand { @@ -42,7 +41,7 @@ export default class ProjectsCreate extends LaunchCommand { static flags = flagsFor(createInputs); - static rules = [serverCommandFrameworkGate, aliasRequiresFromStack, noVarsAlone]; + static rules = [serverCommandFrameworkGate, aliasRequiresFromStack]; async run(): Promise { const resolved = this.resolved; @@ -67,7 +66,6 @@ export default class ProjectsCreate extends LaunchCommand { envFiles: resolved['dotenv'], fromStack: resolved['from-stack'], alias: resolved.alias, - noVars: resolved['no-vars'], }); } } diff --git a/src/environments/environment.builder.ts b/src/environments/environment.builder.ts index 46f72bf2..5372fe3a 100644 --- a/src/environments/environment.builder.ts +++ b/src/environments/environment.builder.ts @@ -64,7 +64,6 @@ export class EnvironmentBuilder { envFiles: request.envFiles, fromStack: request.fromStack, alias: request.alias, - noVars: request.noVars, dataDir: request.dataDir ?? '.', }, this.services, diff --git a/src/environments/types.ts b/src/environments/types.ts index 52562664..c725e78f 100644 --- a/src/environments/types.ts +++ b/src/environments/types.ts @@ -114,7 +114,6 @@ export interface EnvironmentRequest { envFiles?: string[]; fromStack?: boolean; alias?: string; - noVars?: boolean; framework?: FrameworkPreset; buildCmd?: string; outputDir?: string; diff --git a/src/variables/variable.create.test.ts b/src/variables/variable.create.test.ts index 7c2bf69d..f903745f 100644 --- a/src/variables/variable.create.test.ts +++ b/src/variables/variable.create.test.ts @@ -96,15 +96,6 @@ describe('variable create', () => { expect(printed).toEqual([]); }); - it('returns nothing on a terminal with --no-vars, asking nothing, reading nothing and printing nothing', async () => { - const { services, io, asked, reads, printed } = fakes({ files: { '/work/.env': 'X=1' } }); - - expect(await variablesForCreate({ ...NONE, noVars: true }, services, io)).toEqual([]); - expect(asked).toEqual([]); - expect(reads).toEqual([]); - expect(printed).toEqual([]); - }); - it('treats empty flag lists as no flags', async () => { const { services, io, asked } = fakes({ answers: { 'Add environment variables': [SKIP] } }); diff --git a/src/variables/variable.create.ts b/src/variables/variable.create.ts index 73eb759e..537322d0 100644 --- a/src/variables/variable.create.ts +++ b/src/variables/variable.create.ts @@ -15,7 +15,6 @@ export interface CreateVariablesRequest { org: string; fromStack?: boolean; alias?: string; - noVars?: boolean; } const CHOOSE_MESSAGE = 'Add environment variables'; @@ -46,10 +45,6 @@ export async function variablesForCreate( io: VariableIo = DEFAULT_VARIABLE_IO, savedToken: (alias: string) => SavedToken | undefined = readSavedToken, ): Promise { - if (request.noVars === true) { - return []; - } - const stack: StackImporter = (alias) => importFromStack({ org: request.org, alias }, { services, savedToken }); if (given(request.vars) || given(request.envFiles) || request.fromStack === true) { diff --git a/src/variables/variable.inputs.test.ts b/src/variables/variable.inputs.test.ts index 7ecfa917..a1edce97 100644 --- a/src/variables/variable.inputs.test.ts +++ b/src/variables/variable.inputs.test.ts @@ -5,14 +5,14 @@ import { variableFlags, variableResolution } from './variable.inputs'; describe('variable inputs', () => { it('names each flag as the Commands Details "All flags" tables name it', () => { - expect(Object.keys(variableFlags)).toEqual(['var', 'dotenv', 'key', 'from-stack', 'alias', 'no-vars']); + expect(Object.keys(variableFlags)).toEqual(['var', 'dotenv', 'key', 'from-stack', 'alias']); }); it.each(['var', 'dotenv', 'key'] as const)('declares %s repeatable so each occurrence and each value is kept', (name) => { expect(variableFlags[name].multiple).toBe(true); }); - it.each(['var', 'dotenv', 'key', 'from-stack', 'alias', 'no-vars'] as const)('never marks %s required at parse time', (name) => { + it.each(['var', 'dotenv', 'key', 'from-stack', 'alias'] as const)('never marks %s required at parse time', (name) => { expect(variableFlags[name].required).toBeFalsy(); }); @@ -40,17 +40,6 @@ describe('variable inputs', () => { expect(parsed.flags.alias).toBe('my-prod'); }); - it('parses --no-vars as a presence-only flag', async () => { - const parsed = await Parser.parse(['--no-vars'], { flags: { 'no-vars': variableFlags['no-vars'] } }); - - expect(variableFlags['no-vars'].type).toBe('boolean'); - expect(parsed.flags['no-vars']).toBe(true); - }); - - it('leaves the sources out of an oclif exclusive group, since --help would show them excluding each other', () => { - expect(variableFlags['no-vars'].exclusive).toBeUndefined(); - }); - it('describes --var without showing a value that looks like a secret', () => { expect(variableFlags.var.description).toContain('KEY=VALUE'); expect(variableFlags.var.description).not.toMatch(/sk_|ghp_|password/i); diff --git a/src/variables/variable.inputs.ts b/src/variables/variable.inputs.ts index 8631914d..9fdf8e3b 100644 --- a/src/variables/variable.inputs.ts +++ b/src/variables/variable.inputs.ts @@ -21,9 +21,6 @@ export const variableFlags = { char: 'a', description: 'Alias of a delivery token saved with csdx auth:tokens:add, used with --from-stack without a prompt', }), - 'no-vars': Flags.boolean({ - description: 'Create the environment with no variables, without asking for them on a terminal', - }), }; export const variableResolution = { @@ -32,5 +29,4 @@ export const variableResolution = { key: {} satisfies ResolutionSpec, 'from-stack': {} satisfies ResolutionSpec, alias: {} satisfies ResolutionSpec, - 'no-vars': {} satisfies ResolutionSpec, }; diff --git a/src/variables/variable.rules.test.ts b/src/variables/variable.rules.test.ts index 6712f1e1..61fda24e 100644 --- a/src/variables/variable.rules.test.ts +++ b/src/variables/variable.rules.test.ts @@ -1,5 +1,5 @@ import { UsageError } from '../core/errors'; -import { aliasRequiresFromStack, noVarsAlone } from './variable.rules'; +import { aliasRequiresFromStack } from './variable.rules'; describe('variable rules', () => { it('refuses --alias without --from-stack, naming both', () => { @@ -27,21 +27,4 @@ describe('variable rules', () => { it('accepts --from-stack on its own', () => { expect(() => aliasRequiresFromStack({ 'from-stack': true }, {})).not.toThrow(); }); - - it.each([[{ var: ['A=1'] }], [{ dotenv: ['a.env'] }], [{ 'from-stack': true }]])( - 'refuses --no-vars with a variable source (%p)', - (source) => { - expect(() => noVarsAlone({ 'no-vars': true, ...source }, {})).toThrow(UsageError); - expect(() => noVarsAlone({ 'no-vars': true, ...source }, {})).toThrow( - '--no-vars cannot be combined with --var, --dotenv or --from-stack.', - ); - }, - ); - - it.each([[{ 'no-vars': true }], [{ 'no-vars': false, var: ['A=1'] }], [{ var: [], dotenv: [], 'from-stack': false, 'no-vars': true }]])( - 'accepts --no-vars alone and the sources without it (%p)', - (resolved) => { - expect(() => noVarsAlone(resolved, {})).not.toThrow(); - }, - ); }); diff --git a/src/variables/variable.rules.ts b/src/variables/variable.rules.ts index a8d11796..4924027c 100644 --- a/src/variables/variable.rules.ts +++ b/src/variables/variable.rules.ts @@ -7,13 +7,3 @@ export const aliasRequiresFromStack: Rule = (resolved) => { throw new UsageError('--alias is only used with --from-stack.'); } }; - -function hasValues(value: unknown): boolean { - return Array.isArray(value) ? value.length > 0 : value === true; -} - -export const noVarsAlone: Rule = (resolved) => { - if (resolved['no-vars'] === true && [resolved.var, resolved.dotenv, resolved['from-stack']].some(hasValues)) { - throw new UsageError('--no-vars cannot be combined with --var, --dotenv or --from-stack.'); - } -}; diff --git a/test/integration/environments-create.test.ts b/test/integration/environments-create.test.ts index fb662313..9c6254a1 100644 --- a/test/integration/environments-create.test.ts +++ b/test/integration/environments-create.test.ts @@ -281,16 +281,17 @@ describe('integration: launch:env:create on the wire', () => { expect(sent[0].environmentVariables).toEqual([]); }); - it('creates with no variables and asks nothing when --no-vars is given on a terminal', async () => { - const prompts = answerPrompts({}); + it('creates with no variables when Enter is pressed with nothing selected', async () => { + const prompts = answerPrompts({ 'Add environment variables': [] }); const sent: { environmentVariables?: unknown }[] = []; stubCreate(sent); stubFollowUp('LIVE'); - const { error } = await onTerminal(() => runCommand([...WITH_AUTH, '--no-vars'], config)); + const { error, stdout } = await onTerminal(() => runCommand(WITH_AUTH, config)); expect(error).toBeUndefined(); - expect(prompts.messages).toEqual([]); + expect(prompts.messages).toEqual(['Add environment variables']); + expect(stdout).toContain('Skipped adding environment variables.'); expect(sent[0].environmentVariables).toEqual([]); }); diff --git a/test/integration/projects-create.test.ts b/test/integration/projects-create.test.ts index 93c3ef19..63675f85 100644 --- a/test/integration/projects-create.test.ts +++ b/test/integration/projects-create.test.ts @@ -779,9 +779,9 @@ describe('integration: launch:projects:create on the wire', () => { expect(onWire).toEqual([]); }); - it('asks nothing on a terminal when every value is a flag and --no-vars says there are no variables', async () => { + it('asks only for variables on a terminal when every other value is a flag, and a bare Enter skips them', async () => { let body: { environment?: { environmentVariables?: unknown } } | undefined; - const prompts = answerPrompts({}); + const prompts = answerPrompts({ 'Add environment variables': [] }); stubGitLookups(); const create = hub() .post('/manage/projects', (sent: typeof body) => { @@ -792,17 +792,17 @@ describe('integration: launch:projects:create on the wire', () => { .reply(201, { project: CREATED_PROJECT }); stubFollowUp('LIVE'); - const { error } = await onTerminal(() => runCommand([...gitFlags(), '--no-vars'], config)); + const { error } = await onTerminal(() => runCommand(gitFlags(), config)); expect(error).toBeUndefined(); - expect(prompts.messages).toEqual([]); + expect(prompts.messages).toEqual(['Add environment variables']); expect(create.isDone()).toBe(true); expect(body?.environment?.environmentVariables).toEqual([]); expect(onWire).toEqual([]); }); - it('refuses --no-vars with --var with exit 2 before any request', async () => { - const { error } = await runCommand([...gitFlags(), '--no-vars', '--var', 'A=1'], config); + it('refuses the removed --no-vars as an unknown flag with exit 2 before any request', async () => { + const { error } = await runCommand([...gitFlags(), '--no-vars'], config); expect(error?.oclif?.exit).toBe(2); expect(error?.message).toContain('--no-vars');