googleapis / googleapis/release-please

linked-versions plugin doesn't link components when node-workspace creates forced-bump candidates

Open
#2,707 0 comments 1 reaction 1 assignee Claimed by @chingor13 View on GitHub
priority: p3 type: bug
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.