Repository navigation
Conversation
…env var to locate openapitools.json - resolution order: explicit flag (-c/--config or --openapitools) > OPENAPI_GENERATOR_CLI_CONFIG env var > ./openapitools.json (default, unchanged when neither is set) - relative paths are resolved against the cwd - fail fast with a clear error when an explicitly set config path does not exist - version-manager resolve argv detection now also skips the new option forms Fixes OpenAPITools#782
There was a problem hiding this comment.
All reported issues were addressed across 5 files
Reply with feedback, questions, or to request a fix.
View guided diff | Re-trigger cubic
…mand name
The global '-c, --config <path>' option collided with the Java generator's
own 'generate -c, --config <config file>' option (upstream Generate.java
defines name = {"-c", "--config"} for its generator configuration file).
Commander consumes registered root options from the whole argv - in both
parseOptions (used by ConfigService) and parse - so '-c' after 'generate'
was captured as the openapitools.json path: the CLI exited with 1 when
that path did not exist, and the generator config never reached the Java
process because commander had removed it from the subcommand arguments.
Of the two discussed options, excluding the invoked command's argv from
the global -c parsing (option a) is the only correct minimal fix: keeping
the option registered would keep the collision, and dropping only the
short alias would not be enough because the Java generate command also
defines the long '--config' form. The documented UX is preserved:
- the global -c/--config option is no longer registered with commander;
it is still listed in the root help and only honored BEFORE the command
name via extractGlobalConfigArgs(), which understands all option forms
(-c <path>, -c<path>, --config <path>, --config=<path>). Everything
after the first positional argument belongs to the invoked command and
is passed through untouched, which also covers commands other than
'generate'.
- AppModule hands commander an argv without the global config options, so
an unrecognized option before the command name cannot bury the command
(commander would otherwise skip its dispatch and print help).
- --openapitools keeps its existing behavior (registered root option,
honored in any position).
Also clear the shared 'error' mock between tests in
config.service.spec.ts so each missing-file assertion only sees its own
test's log output.
There was a problem hiding this comment.
3 issues found across 5 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="apps/generator-cli/src/app/services/config.service.spec.ts">
<violation number="1" location="apps/generator-cli/src/app/services/config.service.spec.ts:25">
P2: The top-level `beforeEach` does not clear `OPENAPI_GENERATOR_CLI_CONFIG`, so a developer or CI shell that exports it makes every `ConfigService` construction in this suite run the not-found path. `fs.existsSync` is automocked and returns `undefined`, so `process.exit(1)` runs for real. Delete the variable in the top-level `beforeEach` as well, the same way the argv is pinned there.</violation>
</file>
<file name="apps/generator-cli/src/app/services/config.service.ts">
<violation number="1" location="apps/generator-cli/src/app/services/config.service.ts:68">
P2: A root-level `--custom-generator` before `-c` stops this scan, so the explicit config path is ignored and the environment/default config is used. Skip recognized root options and their values before treating an argument as the command name.</violation>
<violation number="2" location="apps/generator-cli/src/app/services/config.service.ts:81">
P2: A trailing `-c` or `--config` assigns `undefined`, so the CLI silently falls back to the environment or default config instead of rejecting the missing required path. Reject the missing value here.</violation>
</file>
Reply with feedback, questions, or to request a fix.
View guided diff | Re-trigger cubic
| // invocation so the runner's own arguments (e.g. jest's --config) are not | ||
| // mistaken for cli options | ||
| originalArgv = process.argv; | ||
| process.argv = ['node', 'openapi-generator-cli']; |
There was a problem hiding this comment.
P2: The top-level beforeEach does not clear OPENAPI_GENERATOR_CLI_CONFIG, so a developer or CI shell that exports it makes every ConfigService construction in this suite run the not-found path. fs.existsSync is automocked and returns undefined, so process.exit(1) runs for real. Delete the variable in the top-level beforeEach as well, the same way the argv is pinned there.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At apps/generator-cli/src/app/services/config.service.spec.ts, line 25:
<comment>The top-level `beforeEach` does not clear `OPENAPI_GENERATOR_CLI_CONFIG`, so a developer or CI shell that exports it makes every `ConfigService` construction in this suite run the not-found path. `fs.existsSync` is automocked and returns `undefined`, so `process.exit(1)` runs for real. Delete the variable in the top-level `beforeEach` as well, the same way the argv is pinned there.</comment>
<file context>
@@ -15,7 +15,15 @@ describe('ConfigService', () => {
+ // invocation so the runner's own arguments (e.g. jest's --config) are not
+ // mistaken for cli options
+ originalArgv = process.argv;
+ process.argv = ['node', 'openapi-generator-cli'];
+
program = createCommand();
</file context>
| process.argv = ['node', 'openapi-generator-cli']; | |
| process.argv = ['node', 'openapi-generator-cli']; | |
| delete process.env[ConfigService.envConfigVariable]; |
| configArgs.add(index); | ||
| if (hasSeparateValue) { | ||
| configArgs.add(index + 1); | ||
| configPath = args[index + 1]; |
There was a problem hiding this comment.
P2: A trailing -c or --config assigns undefined, so the CLI silently falls back to the environment or default config instead of rejecting the missing required path. Reject the missing value here.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At apps/generator-cli/src/app/services/config.service.ts, line 81:
<comment>A trailing `-c` or `--config` assigns `undefined`, so the CLI silently falls back to the environment or default config instead of rejecting the missing required path. Reject the missing value here.</comment>
<file context>
@@ -4,6 +4,97 @@ import { COMMANDER_PROGRAM, LOGGER } from '../constants';
+ configArgs.add(index);
+ if (hasSeparateValue) {
+ configArgs.add(index + 1);
+ configPath = args[index + 1];
+ } else if (args[index].startsWith('--config=')) {
+ configPath = args[index].slice('--config='.length);
</file context>
| configPath = args[index + 1]; | |
| configPath = args[index + 1]; | |
| if (!configPath) { | |
| throw new Error('The -c/--config option requires a path'); | |
| } |
|
|
||
| // the command name or an option of the invoked command: | ||
| // everything from here on belongs to the command | ||
| break; |
There was a problem hiding this comment.
P2: A root-level --custom-generator before -c stops this scan, so the explicit config path is ignored and the environment/default config is used. Skip recognized root options and their values before treating an argument as the command name.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At apps/generator-cli/src/app/services/config.service.ts, line 68:
<comment>A root-level `--custom-generator` before `-c` stops this scan, so the explicit config path is ignored and the environment/default config is used. Skip recognized root options and their values before treating an argument as the command name.</comment>
<file context>
@@ -4,6 +4,97 @@ import { COMMANDER_PROGRAM, LOGGER } from '../constants';
+
+ // the command name or an option of the invoked command:
+ // everything from here on belongs to the command
+ break;
+ }
+
</file context>
Fixes #782
What
Adds a way to point
openapi-generator-cliat anopenapitools.jsonoutside the current working directory (monorepo use-case):-c, --config <path>on the root command — the existing--openapitools <openapitools.json>option is kept and works as an aliasOPENAPI_GENERATOR_CLI_CONFIGenvironment variable as a fallback, so the path can be supplied without changing the command line (e.g. in CI)Resolution order: explicit flag >
OPENAPI_GENERATOR_CLI_CONFIG>./openapitools.json(default).Behavior guarantees:
./openapitools.jsonis used and created on first run, exactly as beforeDesign note: design comment on #782.
How
ConfigService.configFileOrDefault()resolves the location (flag > env var > default). It remains the single source of truth for every read/write ofopenapitools.json, so all commands (version-manager list/set/resolve,use,generate, pass-through) pick it up without further changes.AppModuleregisters the new option on the root program, andisVersionManagerResolveCommand()now also skips the new option forms (-c <path>,--config <path>,--config=<path>,-c<path>) when scanning argv.Tests
Unit tests (
config.service.spec.ts,app.module.spec.ts):-c/--configand via--openapitools(existing behavior kept)OPENAPI_GENERATOR_CLI_CONFIG./openapitools.jsonunchanged when neither is setprocess.exit(1)version-manager resolvedetection skips the new option formsFull suite: 263 tests / 7 suites passing, plus lint and build, run in a
node:20Docker container. Manually smoke-tested the built CLI: valid flag, valid env var, precedence (flag wins), missing-path error paths, and the untouched default flow.Summary by cubic
Lets the CLI point at an
openapitools.jsonoutside the current working directory, for monorepos and CI.-c, --config <path>option before the command name, with--openapitoolskept as a working alias; it is not registered with commander to avoid colliding with the Java generator's owngenerate -c/--configoption, but is listed in help and stripped from the argv handed to commander.OPENAPI_GENERATOR_CLI_CONFIGenv var as a fallback; resolution order is flag, env var, then the default./openapitools.json(unchanged when neither is set).-c/--configafter it belong to the invoked command and pass through untouched.Written for commit 584f43f. Summary will update on new commits.