-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Summary
The makeConfig function fails to parse custom --version options because yargs' built-in --version flag overrides user-defined options. This causes CLI arguments to return false instead of the provided value.
Environment
- lino-arguments version: latest (from unpkg)
- Node.js version: v20.19.6
- Platform: Linux, macOS, GitHub Actions (CI)
Minimal Reproduction
#!/usr/bin/env node
// Load use-m dynamically
const { use } = eval(
await (await fetch('https://unpkg.com/use-m/use.js')).text()
);
// Import lino-arguments
const { makeConfig } = await use('lino-arguments');
console.log('process.argv:', process.argv);
// Parse CLI arguments using lino-arguments
const config = makeConfig({
yargs: ({ yargs, getenv }) =>
yargs.option('version', {
type: 'string',
default: getenv('VERSION', ''),
describe: 'Version number (e.g., 1.0.0)',
}),
});
console.log('config.version:', JSON.stringify(config.version));
if (config.version === false) {
console.error('❌ BUG: --version returned false instead of the value');
process.exit(1);
} else {
console.log('✅ --version parsed correctly:', config.version);
}Run the reproduction:
node minimal-repro.mjs --version "1.0.0"Expected Output:
process.argv: [ '/usr/bin/node', '/path/to/minimal-repro.mjs', '--version', '1.0.0' ]
config.version: "1.0.0"
✅ --version parsed correctly: 1.0.0
Actual Output:
process.argv: [ '/usr/bin/node', '/path/to/minimal-repro.mjs', '--version', '1.0.0' ]
config.version: false
❌ BUG: --version returned false instead of the value
Root Cause
In src/index.js, the makeConfig function creates two yargs instances:
- Initial parse (lines 337-345): Disables built-in help/version with
.help(false)and.version(false) - Final parse (lines 360-373): Does NOT disable built-in help/version
⚠️
The second yargs instance (which produces the final result) has yargs' built-in --version flag enabled, which conflicts with custom --version options.
Relevant code (src/index.js:360-373):
// Step 5: Configure yargs with user options + getenv helper
const yargsInstance = yargs(hideBin(argv)).option('configuration', {
type: 'string',
describe: 'Path to configuration .lenv file',
alias: 'c',
});
// ⬆️ Missing .version(false) here (it was present in initial parse at line 344)
// Pass getenv helper if enabled
const getenvHelper = getenvEnabled ? getenv : () => '';
const configuredYargs = yargsConfigFn
? yargsConfigFn({ yargs: yargsInstance, getenv: getenvHelper })
: yargsInstance;
// Step 6: Parse final configuration (CLI args have highest priority)
const parsed = configuredYargs.parseSync();Impact
This bug affects any script using lino-arguments with a custom --version option:
- ❌ Release scripts fail in CI (like GitHub Actions)
- ❌ CLI tools can't accept version arguments
- ❌ Scripts silently get wrong values (
falseinstead of user input)
Real-world example: In the test-anywhere repository, release scripts failed because makeConfig returned version: false instead of "0.8.34" (see issues #116 and #118).
Proposed Fix
Add .version(false) to the final yargs instance to match the initial parse:
// Step 5: Configure yargs with user options + getenv helper
const yargsInstance = yargs(hideBin(argv))
+ .version(false) // Disable built-in version to allow custom --version option
.option('configuration', {
type: 'string',
describe: 'Path to configuration .lenv file',
alias: 'c',
});Why this fix works:
- ✅ Consistency: Both initial and final parse behave the same way
- ✅ User control: Users can define their own
--versionand--helpoptions if needed - ✅ Backwards compatible: Doesn't break existing code
- ✅ Simple: No complex detection logic required
Optional: Also add .help(false) to prevent the same issue with --help:
const yargsInstance = yargs(hideBin(argv))
+ .help(false) // Disable built-in help to allow custom --help option
+ .version(false) // Disable built-in version to allow custom --version option
.option('configuration', {Workaround
Until this is fixed, avoid using --version and --help as option names. Use alternatives like --ver, --release-version, etc.
Test Case
After applying the fix, this test should pass:
import { makeConfig } from 'lino-arguments';
import assert from 'assert';
const config = makeConfig({
argv: ['node', 'test.mjs', '--version', '1.0.0'],
yargs: ({ yargs }) =>
yargs.option('version', { type: 'string', default: '' }),
});
assert.strictEqual(config.version, '1.0.0');
console.log('✅ Test passed');