googleapis / googleapis/release-please
linked-versions plugin doesn't link components when node-workspace creates forced-bump candidates
- Dominant language
- TypeScript
- Stars
- 7.5k
- Forks
- 588
- Avg merge
- 12h 16m
- Merged PRs (30d)
- 7
Description
**Environment details**
- OS: Ubuntu 24.04 (GitHub Actions runner)
- Node.js version: 20.x (actions runner default)
- npm version: N/A (using `googleapis/release-please-action@v4`)
**Steps to reproduce**
1. Configure a monorepo in manifest mode with both `node-workspace` (merge: false) and `linked-versions` plugins
2. Create a `linked-versions` group linking a `node` release-type component (e.g., `tgp-api`) with a `simple` release-type component (e.g., `tgp-api-helmchart`)
3. Make a commit that bumps a shared workspace dependency (e.g., `@example/common`) but does not directly touch either linked component's path
4. Run release-please
Simplified config:
```
{
"packages": {
"src/apps/plugins/tgp": {
"package-name": "@example/tgp",
"component": "tgp-api"
},
"operations/helm/tgp/api": {
"package-name": "tgp-api-helmchart",
"component": "tgp-api-helmchart",
"release-type": "simple"
},
"src/libs/shared/common": {
"package-name": "@example/common",
"component": "common-library"
}
},
"plugins": [
{ "type": "node-workspace", "merge": false },
{
"type": "linked-versions",
"groupName": "tgp-api",
"components": ["tgp-api", "tgp-api-helmchart"]
}
]
}
```
Expected: Both `tgp-api` and `tgp-api-helmchart` are bumped to the same version.
Actual: `tgp-api` is bumped (forced bump by `node-workspace` due to transitive dependency on `@example/common`), but `tgp-api-helmchart` is not bumped. Log shows `found 0 linked-versions candidates` for the group.
Root cause — two issues in plugin interaction:
1. `node-workspace` drops `config.component` on new candidates
In `src/plugins/node-workspace.ts`, the `newCandidate()` method (inherited from `WorkspacePlugin`) creates candidates with:
```
config: {
releaseType: 'node',
},
```
The `component` field from the repository config is not included.
Then in `src/plugins/linked-versions.ts`, the `run()` method matches candidates by:
`if (this.components.has(candidate.config.component || ''))`
Since `config.component` is `undefined`, this evaluates to `this.components.has('')` → `false`. The forced-bump candidate is invisible to `linked-versions`.
2. `linked-versions` `run()` can't create candidates for missing linked components
Even if bug 1 were fixed, `run()` only merges existing candidates — it doesn't synthesize new candidates for missing components in the group. The `preconfigure()` method handles missing components by injecting fake `Release-As:` commits, but it runs before `node-workspace`, so at that point neither component has a version bump yet.
Why other linked groups aren't affected: Groups where at least one component has direct user-facing commits work correctly because `linked-versions` `preconfigure()` detects the bump and injects fake commits for sibling components before the build phase. The bug only manifests when the sole version bump comes from `node-workspace`'s transitive dependency analysis.
Suggested fix:
Minimal: Include `component` in the config returned by `WorkspacePlugin.newCandidate()`:
```
config: {
releaseType: 'node',
component: this.repositoryConfig[updatedPackage.path]?.component,
},
```
Complete: Additionally, enhance `linked-versions` `run()` to synthesize candidates for missing linked components when at least one component in the group has a candidate (mirroring what `preconfigure()` does, but at post-processing stage).
Workaround: Use `release-as` in the package config to force the version, then remove it after the release PR merges.
Contributor guide
Assessment
This issue has not been assessed yet.