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: <package.json#name>
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:
- Detect the merged-but-untagged PR
- Create the git tag (
v<version>)
- Create the GitHub Release
- 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 <merge-sha> …) and then the label flipped to autorelease: tagged to break the loop.
Reproduction
release-please-config.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:
package.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:
- Push commits with
feat: / fix: types to main.
- release-please opens a release PR titled
chore: release main, with label autorelease: pending.
- Merge the PR (squash).
- 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:
gh release create v1.1.1 --target <merge-sha> --title "v1.1.1" --notes-file <changelog-extract>
gh pr edit <pr#> --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
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 labeledautorelease: pending. The release-build phase logs:and then the pull-request-build phase logs:
The deadlock is unrecoverable through config and recurs on every push. Setting
component: ""on the package, removingpackage-name, and settingpull-request-title-patternexplicitly all fail to break it.Expected behaviour
When a release PR (labeled
autorelease: pending) is merged tomain, the next workflow run should:v<version>)autorelease: pendingtoautorelease: tagged… for a single-package repo regardless of whether
package.json#namematches 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.0Two 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:
Both releases had to be tagged manually (
gh release create vX.Y.Z --target <merge-sha> …) and then the label flipped toautorelease: taggedto break the loop.Reproduction
release-please-config.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:{ ".": "1.0.0" }package.json:{ "name": "kujali-chatcare", "version": "1.0.0", … }Workflow trigger: push to
main, single job using the SHA above. Token is a classic PAT withrepo+workflowscopes (the org has fine-grained PATs disabled).Steps:
feat:/fix:types tomain.chore: release main, with labelautorelease: pending.What I tried
package-name: "kujali-chatcare"undefined ≠ kujali-chatcare), abortpackage-namefrom the package configpackage.json#namecomponent: ""to the package configpull-request-title-pattern: "chore: release ${version}"at top levelchore: release main; same abortRoot cause hypothesis
The
noderelease-type derives an implicit component frompackage.json#name. Wheninclude-component-in-tag: falseis 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 checksPR.component (parsed from title → undefined)againstpackage.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 inrelease-please@17.6.0it 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:
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:
componenton a package config, so single-package repos withinclude-component-in-tag: falsecan opt out of component matching entirely; ORinclude-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; ORpackageshas exactly one entry at.) and apply (b) automatically.Happy to PR (b) or (c) if either is the preferred direction.
Environment
.),release-type: noderelease-please-action@45996ed…(v5.0.0)17.6.0package.json#name:kujali-chatcareinclude-component-in-tag:falseinclude-v-in-tag:true