googleapis / googleapis/release-please-action
Single-package node repo with include-component-in-tag:false deadlocks on tagging — empty component override ignored
- Dominant language
- TypeScript
- Stars
- 2.5k
- Forks
- 327
- PR merge metrics
- No merged PRs in 30d
Description
### TL;DR
For a single-package node repo with `include-component-in-tag: false`, release-please-action **never tags or releases the merged release PR**, even though the PR is correctly labeled `autorelease: pending`. The release-build phase logs:
```
⚠ PR component: undefined does not match configured component:
```
and then the pull-request-build phase logs:
```
⚠ There are untagged, merged release PRs outstanding - aborting
```
The deadlock is unrecoverable through config and recurs on every push. Setting `component: ""` on the package, removing `package-name`, and setting `pull-request-title-pattern` explicitly all fail to break it.
### Expected behaviour
When a release PR (labeled `autorelease: pending`) is merged to `main`, the next workflow run should:
1. Detect the merged-but-untagged PR
2. Create the git tag (`v`)
3. Create the GitHub Release
4. Update the label from `autorelease: pending` to `autorelease: tagged`
… for a single-package repo regardless of whether `package.json#name` matches an empty/unset component config.
### Observed behaviour
Action SHA: `googleapis/release-please-action@45996ed1f6d02564a971a2fa1b5860e934307cf7` (v5.0.0)
release-please version (logged by the action): `17.6.0`
Two consecutive release cycles (v1.1.0 and v1.1.1) on the same single-package repo each opened a release PR correctly, but on merge the action **refused to tag**:
```
✔ Building releases
✔ Building strategies by path
❯ .: node
❯ Found pull request #10: 'chore: release main'
✔ Building release for path: .
❯ type: node
⚠ pullRequestTitlePattern miss the part of '${scope}'
⚠ pullRequestTitlePattern miss the part of '${component}'
❯ targetBranch: main
❯ Fetching package.json from branch main
⚠ PR component: undefined does not match configured component: kujali-chatcare
…
✔ Collecting commits since all latest releases
❯ looking for tagName: v1.1.1
…
⚠ There are untagged, merged release PRs outstanding - aborting
```
Both releases had to be tagged manually (`gh release create vX.Y.Z --target …`) and then the label flipped to `autorelease: tagged` to break the loop.
### Reproduction
`release-please-config.json`:
```json
{
"$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json",
"include-component-in-tag": false,
"include-v-in-tag": true,
"pull-request-title-pattern": "chore: release ${version}",
"packages": {
".": {
"release-type": "node",
"changelog-path": "CHANGELOG.md",
"component": ""
}
}
}
```
`.release-please-manifest.json`:
```json
{ ".": "1.0.0" }
```
`package.json`:
```json
{ "name": "kujali-chatcare", "version": "1.0.0", … }
```
Workflow trigger: push to `main`, single job using the SHA above. Token is a classic PAT with `repo` + `workflow` scopes (the org has fine-grained PATs disabled).
Steps:
1. Push commits with `feat:` / `fix:` types to `main`.
2. release-please opens a release PR titled `chore: release main`, with label `autorelease: pending`.
3. Merge the PR (squash).
4. Next push triggers release-please again — but instead of tagging the merged PR, it logs the component-mismatch warning and aborts.
### What I tried
| Attempt | Result |
|---|---|
| Default config with `package-name: "kujali-chatcare"` | Component mismatch (`undefined ≠ kujali-chatcare`), abort |
| Removed `package-name` from the package config | Same — the node strategy still derives the component from `package.json#name` |
| Added `component: ""` to the package config | Same — empty string is silently ignored, derived component still used |
| Added `pull-request-title-pattern: "chore: release ${version}"` at top level | Pattern ignored; PR title remains `chore: release main`; same abort |
### Root cause hypothesis
The `node` release-type derives an implicit component from `package.json#name`. When `include-component-in-tag: false` is set, the resulting release PR title (`chore: release main` — no `${component}` segment) **does not encode** the component. But on subsequent runs the release-build phase still checks `PR.component (parsed from title → undefined)` against `package.component (derived → kujali-chatcare)`. The mismatch makes release-build skip the tagging path, the pull-request-build phase sees the merged-but-untagged PR, and the whole run aborts.
An explicit empty-string `component: ""` ought to override the derived value, but in `release-please@17.6.0` it appears to be discarded (either by the `??` fallback to the strategy's derived component or by JSON parsing).
### Workaround
Manual tag + release on each merge, then re-label:
```bash
gh release create v1.1.1 --target --title "v1.1.1" --notes-file
gh pr edit --remove-label "autorelease: pending" --add-label "autorelease: tagged"
```
This works because once the PR is labeled `autorelease: tagged`, release-please ignores it on the next run and stops the abort loop. But the manual step defeats the whole point of the action.
### Proposed fix
Either:
- **(a) Honour explicit empty-string `component`** on a package config, so single-package repos with `include-component-in-tag: false` can opt out of component matching entirely; OR
- **(b) Skip component matching when `include-component-in-tag: false`** — if the tag isn't going to encode the component, the PR title shouldn't need to either, so the comparison is moot; OR
- **(c) Detect single-package configs** (`packages` has exactly one entry at `.`) and apply (b) automatically.
Happy to PR (b) or (c) if either is the preferred direction.
### Environment
- Repo: single-package, single-path (`.`), `release-type: node`
- Org: fine-grained PAT requests disabled at org level → classic PAT used
- Action version: `release-please-action@45996ed…` (v5.0.0)
- release-please CLI version (per action log): `17.6.0`
- `package.json#name`: `kujali-chatcare`
- `include-component-in-tag`: `false`
- `include-v-in-tag`: `true`
Contributor guide
Research direction
Start by tracing the release-build and pull-request-build phases for the node strategy, using the component handling shown in the issue. Compare how release-please-config.json, package.json, and the merged PR title are parsed when include-component-in-tag is false. Done means the reproduced single-package workflow tags the merged release PR, creates the GitHub Release, and updates the label without manual intervention.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- github-actions, node.js, typescript
- Domain
- ci-cd, devops, release
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100