Skip to content

Commit f4fbe7b

Browse files
authored
Merge pull request #23 from link-foundation/issue-22-e5ea3b44ef6b
Fix yargs reserved word conflict for --version option
2 parents 57b3390 + edd41f8 commit f4fbe7b

7 files changed

Lines changed: 3077 additions & 1 deletion

File tree

csharp/scripts/create-github-release.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ const { makeConfig } = await use('lino-arguments');
2828
const config = makeConfig({
2929
yargs: ({ yargs, getenv }) =>
3030
yargs
31+
.version(false) // Disable yargs built-in --version to use our custom version option
3132
.option('version', {
3233
type: 'string',
3334
default: getenv('VERSION', ''),
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
# Case Study: Rust CI/CD Failure - Yargs Reserved Word Conflict
2+
3+
**Issue:** [#22](https://github.com/link-foundation/lino-objects-codec/issues/22)
4+
**Date of Failure:** 2026-01-08
5+
**CI Run:** [#20828012412](https://github.com/link-foundation/lino-objects-codec/actions/runs/20828012412/job/59834479617)
6+
7+
## Executive Summary
8+
9+
The Rust CI/CD pipeline was failing during the "Auto Release" phase because the `create-github-release.mjs` script was unable to parse the `--version` command-line argument. The root cause was that `"version"` is a reserved word in yargs (the CLI argument parsing library used by `lino-arguments`), which caused the argument to be interpreted as yargs' built-in version display command instead of our custom option.
10+
11+
## Timeline of Events
12+
13+
1. **18:48:47 UTC** - CI pipeline triggered by push to main branch
14+
2. **18:48:51 UTC** - "Detect Changes" job completed successfully
15+
3. **18:48:58 - 18:49:48 UTC** - "Lint and Format Check", "Test", and "Build Package" jobs completed successfully
16+
4. **18:50:06 UTC** - "Auto Release" job started
17+
5. **18:50:11 UTC** - Git configured, changelog fragments detected (1 fragment, patch bump)
18+
6. **18:50:11 UTC** - Version check passed (new version 0.2.0 detected)
19+
7. **18:50:19 UTC** - Build and publish steps completed
20+
8. **18:50:19 UTC** - "Create GitHub Release" step started
21+
9. **18:50:24 UTC** - **FAILURE**: Script exited with "Missing required arguments"
22+
23+
## Root Cause Analysis
24+
25+
### The Error
26+
27+
```
28+
Auto Release Create GitHub Release Error: Missing required arguments
29+
Auto Release Create GitHub Release Usage: node scripts/create-github-release.mjs --version <version> --repository <repository>
30+
Auto Release Create GitHub Release ##[error]Process completed with exit code 1.
31+
```
32+
33+
### The Command Executed
34+
35+
```bash
36+
node scripts/create-github-release.mjs \
37+
--version "0.2.0" \
38+
--repository "link-foundation/lino-objects-codec" \
39+
--tag-prefix "rust-v"
40+
```
41+
42+
### Investigation
43+
44+
The arguments were correctly passed to the script, but the script reported "Missing required arguments". This was puzzling because the arguments were clearly present in the command.
45+
46+
Upon testing locally, we discovered that the parsed `version` value was `false` instead of `"0.2.0"`:
47+
48+
```javascript
49+
Parsed config: {
50+
"version": false, // Expected: "0.2.0"
51+
"repository": "test/repo",
52+
"tagPrefix": "v"
53+
}
54+
```
55+
56+
Node.js also printed a warning:
57+
58+
```
59+
Warning: "version" is a reserved word.
60+
Please do one of the following:
61+
- Disable version with `yargs.version(false)` if using "version" as an option
62+
- Use the built-in `yargs.version` method instead (if applicable)
63+
- Use a different option key
64+
```
65+
66+
### Root Cause
67+
68+
The `lino-arguments` library uses [yargs](https://yargs.js.org/) internally for CLI argument parsing. In yargs v17.2.0+, `--version` is a reserved command that displays the application version and exits. When a user defines a custom `version` option, yargs exhibits unexpected behavior - it returns `false` instead of the actual argument value.
69+
70+
This is a known issue documented in:
71+
- [yargs/yargs#2064](https://github.com/yargs/yargs/issues/2064)
72+
- [CycloneDX/cdxgen#83](https://github.com/CycloneDX/cdxgen/issues/83)
73+
74+
## Solution
75+
76+
The fix is to call `.version(false)` on the yargs instance before defining the custom `version` option. This disables yargs' built-in `--version` handling and allows the custom option to be parsed correctly.
77+
78+
### Before (Broken)
79+
80+
```javascript
81+
const config = makeConfig({
82+
yargs: ({ yargs, getenv }) =>
83+
yargs
84+
.option('version', {
85+
type: 'string',
86+
default: getenv('VERSION', ''),
87+
describe: 'Version number (e.g., 1.0.0)',
88+
})
89+
// ... other options
90+
});
91+
```
92+
93+
### After (Fixed)
94+
95+
```javascript
96+
const config = makeConfig({
97+
yargs: ({ yargs, getenv }) =>
98+
yargs
99+
.version(false) // Disable yargs built-in --version handling
100+
.option('version', {
101+
type: 'string',
102+
default: getenv('VERSION', ''),
103+
describe: 'Version number (e.g., 1.0.0)',
104+
})
105+
// ... other options
106+
});
107+
```
108+
109+
## Affected Files
110+
111+
Three scripts were affected by this issue:
112+
113+
1. `rust/scripts/create-github-release.mjs` - **Primary failure point**
114+
2. `rust/scripts/collect-changelog.mjs`
115+
3. `csharp/scripts/create-github-release.mjs`
116+
117+
## Lessons Learned
118+
119+
1. **Reserved Words in Libraries**: When using CLI parsing libraries like yargs, be aware of reserved words that may conflict with your option names. Common reserved words in yargs include `version`, `help`, `$0`.
120+
121+
2. **Warning Messages**: Node.js and libraries often emit warnings before errors occur. In this case, the warning about "version" being a reserved word was available but not visible in the CI output until the failure occurred.
122+
123+
3. **Local Testing**: Testing scripts locally with the same arguments used in CI can help identify argument parsing issues that aren't obvious from CI logs alone.
124+
125+
4. **Error Messages Can Be Misleading**: The error "Missing required arguments" suggested the arguments weren't being passed, but the real issue was that they were being ignored due to a naming conflict.
126+
127+
## Prevention Measures
128+
129+
1. **Avoid Reserved Names**: Consider using alternative option names like `pkg-version`, `release-version`, or `ver` to avoid conflicts with reserved words.
130+
131+
2. **Always Use `.version(false)`**: When defining a custom `version` option in yargs, always disable the built-in version handling first.
132+
133+
3. **Add Integration Tests**: Create tests that verify the CLI scripts correctly parse all expected arguments.
134+
135+
## References
136+
137+
- [Yargs Documentation - version()](https://yargs.js.org/docs/#api-reference-version)
138+
- [yargs/yargs#2064 - Cannot have version as both option and command](https://github.com/yargs/yargs/issues/2064)
139+
- [CycloneDX/cdxgen#83 - Warning: "version" is a reserved word](https://github.com/CycloneDX/cdxgen/issues/83)

0 commit comments

Comments
 (0)