feat: migrate from semantic-release to Release Please - #375
Conversation
Replace semantic-release with Release Please to solve branch protection issues by using a PR-based release workflow instead of direct commits to main. Changes: - Add Release Please configuration files (.release-please-manifest.json, release-please-config.json) - Add Release Please workflow (.github/workflows/release-please.yml) - Add marketplace.json sync workflow (.github/workflows/sync-marketplace.yml) - Add marketplace version sync script (scripts/sync-marketplace-version.sh) - Remove semantic-release dependencies from package.json - Remove semantic-release configuration (.releaserc.js) - Simplify CI workflow (remove release job, keep only test job) - Update tests to validate new Release Please workflows Benefits: - No branch protection bypass needed - follows normal PR workflow - Release changes are visible in PR before release - Can review version bumps and changelog before releasing - Same CI process for all changes Breaking Change: Release workflow now requires merging Release Please PRs instead of automatic releases on push to main. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
📝 WalkthroughWalkthroughThis PR replaces semantic-release automation with release-please, removing the old release job from CI workflows, adding Release Please and marketplace sync workflows, and updating configuration files and tests accordingly. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~30 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Fix all issues with AI agents
In @.github/workflows/sync-marketplace.yml:
- Around line 31-35: The workflow uses unquoted $GITHUB_OUTPUT in the echo
commands which can cause word-splitting (ShellCheck SC2086); update both echo
lines that write to GITHUB_OUTPUT (the ones echoing "changed=false" and
"changed=true" after the git diff check) to quote the variable as
"$GITHUB_OUTPUT" so the output file path is treated as a single argument.
In `@release-please-config.json`:
- Around line 5-10: The extra-files entry that uses the glob pattern
"plugins/*/.claude-plugin/plugin.json" is missing the "glob": true flag so
Release Please treats the path as a literal; update the JSON object inside the
"extra-files" array (the entry with "type": "json", "path":
"plugins/*/.claude-plugin/plugin.json", "jsonpath": "$.version") to include
"glob": true so the glob pattern is recognized and plugin manifest versions are
updated.
In `@scripts/sync-marketplace-version.sh`:
- Around line 4-14: Validate the VERSION variable returned by jq (VERSION=$(jq
-r '.version' package.json)) before mutating .claude-plugin/marketplace.json:
check if VERSION is empty or equals "null", and if so write a clear error
message to stderr (use >&2) and exit with non-zero status so the script does not
overwrite marketplace.json; only proceed to run the existing jq update and mv
steps when VERSION is valid. Ensure the error message is descriptive and use the
same .claude-plugin/marketplace.json temporary-write flow when proceeding.
In `@tests/github_workflows.bats`:
- Around line 65-131: The tests in tests/github_workflows.bats currently perform
command substitution and direct [[ ... ]] checks (e.g., jobs=$(yaml_get
"$CI_WORKFLOW" ".jobs | keys | .[]"), release_job=$(yaml_get "$CI_WORKFLOW"
".jobs.release"), and workflow_has_trigger/uses checks) instead of using BATS'
run/$status/$output conventions; update each test to invoke the helper commands
with run (for example run yaml_get "$CI_WORKFLOW" ".jobs | keys | .[]"), assert
success with [ "$status" -eq 0 ], and assert expected text using [[ "$output" =~
"expected" ]] (apply this pattern to tests that call yaml_get,
workflow_has_trigger, and file existence checks that can be run and captured,
e.g., run test -f "${WORKFLOW_DIR}/release-please.yml" then check $status, and
similarly replace direct [[ "$uses" == *"...release-please-action@v4"* ]] with a
run of yaml_get and an output regex assertion).
| run: | | ||
| if git diff --quiet .claude-plugin/marketplace.json; then | ||
| echo "changed=false" >> $GITHUB_OUTPUT | ||
| else | ||
| echo "changed=true" >> $GITHUB_OUTPUT |
There was a problem hiding this comment.
Quote $GITHUB_OUTPUT to avoid word splitting.
Shellcheck SC2086 warns here; quoting is the safe default.
✅ Suggested fix
- if git diff --quiet .claude-plugin/marketplace.json; then
- echo "changed=false" >> $GITHUB_OUTPUT
- else
- echo "changed=true" >> $GITHUB_OUTPUT
- fi
+ if git diff --quiet .claude-plugin/marketplace.json; then
+ echo "changed=false" >> "$GITHUB_OUTPUT"
+ else
+ echo "changed=true" >> "$GITHUB_OUTPUT"
+ fi📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| run: | | |
| if git diff --quiet .claude-plugin/marketplace.json; then | |
| echo "changed=false" >> $GITHUB_OUTPUT | |
| else | |
| echo "changed=true" >> $GITHUB_OUTPUT | |
| run: | | |
| if git diff --quiet .claude-plugin/marketplace.json; then | |
| echo "changed=false" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "changed=true" >> "$GITHUB_OUTPUT" | |
| fi |
🧰 Tools
🪛 actionlint (1.7.10)
[error] 31-31: shellcheck reported issue in this script: SC2086:info:2:27: Double quote to prevent globbing and word splitting
(shellcheck)
[error] 31-31: shellcheck reported issue in this script: SC2086:info:4:26: Double quote to prevent globbing and word splitting
(shellcheck)
🤖 Prompt for AI Agents
In @.github/workflows/sync-marketplace.yml around lines 31 - 35, The workflow
uses unquoted $GITHUB_OUTPUT in the echo commands which can cause word-splitting
(ShellCheck SC2086); update both echo lines that write to GITHUB_OUTPUT (the
ones echoing "changed=false" and "changed=true" after the git diff check) to
quote the variable as "$GITHUB_OUTPUT" so the output file path is treated as a
single argument.
| "extra-files": [ | ||
| { | ||
| "type": "json", | ||
| "path": "plugins/*/.claude-plugin/plugin.json", | ||
| "jsonpath": "$.version" | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
Release Please extra-files glob pattern support documentation
💡 Result:
release-please does support glob patterns for extra-files, but not when extra-files items are plain strings. To use a glob, you must use the object form and set "glob": true (defaults to false). (raw.githubusercontent.com)
Example:
{
"packages": {
".": {
"release-type": "simple",
"extra-files": [
{ "type": "generic", "path": "packages/*/version.txt", "glob": true }
]
}
}
}Notes:
- Object forms exist for targeted updates too (e.g.,
{type: "json"|"yaml"|"toml", path, glob, jsonpath}and{type:"xml", path, glob, xpath}), all with the same"glob"boolean. (raw.githubusercontent.com)
Citations:
- 1: https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json
- 2: https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json
Add "glob": true to enable glob pattern matching.
Release Please requires the "glob": true property to recognize glob patterns in extra-files. Without it, the path plugins/*/.claude-plugin/plugin.json is treated as a literal filename and won't match any files, preventing version updates to plugin manifests.
Corrected configuration
{
"type": "json",
"path": "plugins/*/.claude-plugin/plugin.json",
"jsonpath": "$.version",
"glob": true
}🤖 Prompt for AI Agents
In `@release-please-config.json` around lines 5 - 10, The extra-files entry that
uses the glob pattern "plugins/*/.claude-plugin/plugin.json" is missing the
"glob": true flag so Release Please treats the path as a literal; update the
JSON object inside the "extra-files" array (the entry with "type": "json",
"path": "plugins/*/.claude-plugin/plugin.json", "jsonpath": "$.version") to
include "glob": true so the glob pattern is recognized and plugin manifest
versions are updated.
| # Get version from package.json | ||
| VERSION=$(jq -r '.version' package.json) | ||
|
|
||
| # Update all plugin versions in marketplace.json | ||
| jq --arg version "$VERSION" \ | ||
| '.plugins = [.plugins[] | .version = $version]' \ | ||
| .claude-plugin/marketplace.json > .claude-plugin/marketplace.json.tmp | ||
|
|
||
| mv .claude-plugin/marketplace.json.tmp .claude-plugin/marketplace.json | ||
|
|
||
| echo "Updated marketplace.json to version $VERSION" |
There was a problem hiding this comment.
Guard against missing/invalid version to avoid writing “null”.
jq -r '.version' returns null when missing, which would overwrite marketplace versions incorrectly. Add validation and stderr error output before mutation.
🛡️ Proposed fix
-# Get version from package.json
-VERSION=$(jq -r '.version' package.json)
+# Get version from package.json
+VERSION=$(jq -r '.version // empty' package.json)
+if [[ -z "$VERSION" ]]; then
+ echo "ERROR: package.json is missing .version" >&2
+ exit 1
+fi
+
+if [[ ! -f .claude-plugin/marketplace.json ]]; then
+ echo "ERROR: .claude-plugin/marketplace.json not found" >&2
+ exit 1
+fi
+
+if ! jq -e '.plugins | type=="array"' .claude-plugin/marketplace.json >/dev/null; then
+ echo "ERROR: marketplace.json missing .plugins array" >&2
+ exit 1
+fiAs per coding guidelines: Direct error messages to stderr in hook scripts.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| # Get version from package.json | |
| VERSION=$(jq -r '.version' package.json) | |
| # Update all plugin versions in marketplace.json | |
| jq --arg version "$VERSION" \ | |
| '.plugins = [.plugins[] | .version = $version]' \ | |
| .claude-plugin/marketplace.json > .claude-plugin/marketplace.json.tmp | |
| mv .claude-plugin/marketplace.json.tmp .claude-plugin/marketplace.json | |
| echo "Updated marketplace.json to version $VERSION" | |
| # Get version from package.json | |
| VERSION=$(jq -r '.version // empty' package.json) | |
| if [[ -z "$VERSION" ]]; then | |
| echo "ERROR: package.json is missing .version" >&2 | |
| exit 1 | |
| fi | |
| if [[ ! -f .claude-plugin/marketplace.json ]]; then | |
| echo "ERROR: .claude-plugin/marketplace.json not found" >&2 | |
| exit 1 | |
| fi | |
| if ! jq -e '.plugins | type=="array"' .claude-plugin/marketplace.json >/dev/null; then | |
| echo "ERROR: marketplace.json missing .plugins array" >&2 | |
| exit 1 | |
| fi | |
| # Update all plugin versions in marketplace.json | |
| jq --arg version "$VERSION" \ | |
| '.plugins = [.plugins[] | .version = $version]' \ | |
| .claude-plugin/marketplace.json > .claude-plugin/marketplace.json.tmp | |
| mv .claude-plugin/marketplace.json.tmp .claude-plugin/marketplace.json | |
| echo "Updated marketplace.json to version $VERSION" |
🤖 Prompt for AI Agents
In `@scripts/sync-marketplace-version.sh` around lines 4 - 14, Validate the
VERSION variable returned by jq (VERSION=$(jq -r '.version' package.json))
before mutating .claude-plugin/marketplace.json: check if VERSION is empty or
equals "null", and if so write a clear error message to stderr (use >&2) and
exit with non-zero status so the script does not overwrite marketplace.json;
only proceed to run the existing jq update and mv steps when VERSION is valid.
Ensure the error message is descriptive and use the same
.claude-plugin/marketplace.json temporary-write flow when proceeding.
| @test "CI workflow has only test job (no release job)" { | ||
| ensure_yq | ||
| yaml_get "$CI_WORKFLOW" ".jobs.release" >/dev/null | ||
| } | ||
|
|
||
| @test "CI workflow release job has bot detection condition" { | ||
| ensure_yq | ||
| # The job should have an 'if' condition that filters bot accounts | ||
| local if_condition | ||
| if_condition=$(yaml_get "$CI_WORKFLOW" ".jobs.release.if") | ||
| # CI workflow should only have test job, release is now handled by Release Please | ||
| local jobs | ||
| jobs=$(yaml_get "$CI_WORKFLOW" ".jobs | keys | .[]") | ||
|
|
||
| echo "Actual if condition: $if_condition" | ||
| [[ "$jobs" == "test" ]] | ||
|
|
||
| # The condition should check github.actor | ||
| [[ "$if_condition" == *"github.actor"* ]] | ||
|
|
||
| # The condition should use either: | ||
| # 1. contains() function for universal bot filtering (recommended) | ||
| # 2. or != operator for specific bot filtering (brittle) | ||
| [[ "$if_condition" == *"contains"* ]] || [[ "$if_condition" == *"!="* ]] | ||
| # Verify release job doesn't exist (should return "null") | ||
| local release_job | ||
| release_job=$(yaml_get "$CI_WORKFLOW" ".jobs.release") | ||
| [[ "$release_job" == "null" ]] | ||
| } | ||
|
|
||
| @test "CI workflow has required permissions" { | ||
| @test "CI workflow has read-only permissions" { | ||
| ensure_yq | ||
| local permissions | ||
| permissions=$(yaml_get "$CI_WORKFLOW" ".permissions.contents") | ||
|
|
||
| [[ "$permissions" == "write" ]] | ||
| [[ "$permissions" == "read" ]] | ||
| } | ||
|
|
||
| @test "CI workflow release job runs tests before release" { | ||
| # Check that 'Run tests' step exists in the release job | ||
| # We'll check for the step name in the file | ||
| grep -q "name:.*Run tests" "$CI_WORKFLOW" || grep -q "name:.*test" "$CI_WORKFLOW" | ||
| @test "Release Please workflow exists" { | ||
| [ -f "${WORKFLOW_DIR}/release-please.yml" ] | ||
| } | ||
|
|
||
| @test "CI workflow release job depends on test job" { | ||
| @test "Release Please workflow has valid YAML syntax" { | ||
| ensure_yq | ||
| # The release job should have 'needs: test' to ensure proper execution order | ||
| local needs | ||
| needs=$(yaml_get "$CI_WORKFLOW" ".jobs.release.needs") | ||
|
|
||
| [[ "$needs" == "test" ]] || [[ "$needs" == *"test"* ]] | ||
| yaml_get "${WORKFLOW_DIR}/release-please.yml" "." >/dev/null | ||
| } | ||
|
|
||
| @test "CI workflow release job only runs on main branch" { | ||
| @test "Release Please workflow triggers on push to main" { | ||
| ensure_yq | ||
| # The release job should only run on push to main, not on PRs | ||
| local if_condition | ||
| if_condition=$(yaml_get "$CI_WORKFLOW" ".jobs.release.if") | ||
| workflow_has_trigger "${WORKFLOW_DIR}/release-please.yml" "push" | ||
| local branches | ||
| branches=$(yaml_get "${WORKFLOW_DIR}/release-please.yml" ".on.push.branches.[]") | ||
| [[ "$branches" == "main" ]] | ||
| } | ||
|
|
||
| echo "Actual if condition: $if_condition" | ||
| @test "Release Please workflow has required permissions" { | ||
| ensure_yq | ||
| local contents_perm | ||
| contents_perm=$(yaml_get "${WORKFLOW_DIR}/release-please.yml" ".permissions.contents") | ||
| [[ "$contents_perm" == "write" ]] | ||
|
|
||
| # Should check for main branch | ||
| [[ "$if_condition" == *"main"* ]] | ||
| local pr_perm | ||
| pr_perm=$(yaml_get "${WORKFLOW_DIR}/release-please.yml" ".permissions.pull-requests") | ||
| [[ "$pr_perm" == "write" ]] | ||
| } | ||
|
|
||
| # Should check for push event (not pull_request) | ||
| [[ "$if_condition" == *"push"* ]] | ||
| @test "Marketplace sync workflow exists" { | ||
| [ -f "${WORKFLOW_DIR}/sync-marketplace.yml" ] | ||
| } | ||
|
|
||
| @test "CI workflow filters all bot accounts to prevent infinite loop" { | ||
| @test "Marketplace sync workflow has valid YAML syntax" { | ||
| ensure_yq | ||
| # The job should NOT run when ANY bot account is the actor | ||
| # This prevents infinite loops when auto-update-bot-baleen[bot] merges PRs | ||
| local if_condition | ||
| if_condition=$(yaml_get "$CI_WORKFLOW" ".jobs.release.if") | ||
|
|
||
| echo "Actual if condition: $if_condition" | ||
|
|
||
| # The condition should use contains() to filter ANY bot with [bot] suffix | ||
| # Valid patterns: | ||
| # - !contains(github.actor, '[bot]') | ||
| # - contains(github.actor, '[bot]') == false | ||
|
|
||
| # Check that it uses contains() function for universal bot filtering | ||
| [[ "$if_condition" == *"contains"* ]] | ||
| [[ "$if_condition" == *"[bot]"* ]] | ||
|
|
||
| # Verify it doesn't hardcode specific bot names (like github-actions[bot]) | ||
| # Hardcoding specific bot names will miss other bots like auto-update-bot-baleen[bot] | ||
| if [[ "$if_condition" == *"github-actions[bot]"* ]]; then | ||
| # If it mentions github-actions[bot], it must be a general pattern | ||
| # that would also catch other bots | ||
| if [[ "$if_condition" != *"contains"* ]]; then | ||
| echo "ERROR: Condition hardcodes github-actions[bot] without using contains()" | ||
| echo "This will miss other bots like auto-update-bot-baleen[bot]" | ||
| return 1 | ||
| fi | ||
| fi | ||
| yaml_get "${WORKFLOW_DIR}/sync-marketplace.yml" "." >/dev/null | ||
| } | ||
|
|
||
| @test "CI workflow blocks auto-update-bot-baleen" { | ||
| @test "Release Please workflow uses googleapis action" { | ||
| ensure_yq | ||
| # Specifically verify that auto-update-bot-baleen[bot] would be filtered | ||
| # This is the actual bot causing the infinite loop | ||
| local if_condition | ||
| if_condition=$(yaml_get "$CI_WORKFLOW" ".jobs.release.if") | ||
|
|
||
| echo "Checking if condition blocks auto-update-bot-baleen[bot]: $if_condition" | ||
|
|
||
| # The condition must block any actor with [bot] suffix | ||
| # Valid approaches: | ||
| # 1. !contains(github.actor, '[bot]') | ||
| # 2. github.actor != 'github-actions[bot]' && github.actor != 'auto-update-bot-baleen[bot]' (brittle) | ||
|
|
||
| # Check for the robust solution (contains) | ||
| if [[ "$if_condition" == *"contains"* ]] && [[ "$if_condition" == *"[bot]"* ]]; then | ||
| # This is the good approach - catches all bots | ||
| return 0 | ||
| fi | ||
|
|
||
| # If using specific bot names, check if auto-update-bot-baleen[bot] is included | ||
| if [[ "$if_condition" == *"github-actions[bot]"* ]] && [[ "$if_condition" != *"contains"* ]]; then | ||
| # Hardcoded approach - must explicitly list auto-update-bot-baleen[bot] | ||
| if [[ "$if_condition" != *"auto-update-bot-baleen"* ]]; then | ||
| echo "ERROR: Condition filters github-actions[bot] but not auto-update-bot-baleen[bot]" | ||
| echo "This will cause infinite loops when auto-update-bot merges PRs" | ||
| return 1 | ||
| fi | ||
| fi | ||
| # Verify that the workflow uses the official release-please action | ||
| local uses | ||
| uses=$(yaml_get "${WORKFLOW_DIR}/release-please.yml" ".jobs.release-please.steps.[0].uses") | ||
|
|
||
| return 0 | ||
| [[ "$uses" == *"googleapis/release-please-action@v4"* ]] | ||
| } |
There was a problem hiding this comment.
Use run + status/output assertions for the new tests.
Current assertions bypass BATS’ run and $status/$output conventions. Apply the pattern below across the new tests.
♻️ Example refactor pattern
- local jobs
- jobs=$(yaml_get "$CI_WORKFLOW" ".jobs | keys | .[]")
-
- [[ "$jobs" == "test" ]]
+ run yaml_get "$CI_WORKFLOW" ".jobs | keys | .[]"
+ [ "$status" -eq 0 ]
+ [[ "$output" =~ ^test$ ]]As per coding guidelines: Use the run command to execute and capture output in BATS tests; Use [$status -eq 0] for exit code assertions; Use [[ "$output" =~ "expected" ]] for output assertions in BATS tests.
🤖 Prompt for AI Agents
In `@tests/github_workflows.bats` around lines 65 - 131, The tests in
tests/github_workflows.bats currently perform command substitution and direct [[
... ]] checks (e.g., jobs=$(yaml_get "$CI_WORKFLOW" ".jobs | keys | .[]"),
release_job=$(yaml_get "$CI_WORKFLOW" ".jobs.release"), and
workflow_has_trigger/uses checks) instead of using BATS' run/$status/$output
conventions; update each test to invoke the helper commands with run (for
example run yaml_get "$CI_WORKFLOW" ".jobs | keys | .[]"), assert success with [
"$status" -eq 0 ], and assert expected text using [[ "$output" =~ "expected" ]]
(apply this pattern to tests that call yaml_get, workflow_has_trigger, and file
existence checks that can be run and captured, e.g., run test -f
"${WORKFLOW_DIR}/release-please.yml" then check $status, and similarly replace
direct [[ "$uses" == *"...release-please-action@v4"* ]] with a run of yaml_get
and an output regex assertion).
# [5.0.0](v4.3.0...v5.0.0) (2026-02-05) ### Bug Fixes * **ci:** disable strict status checks to allow semantic-release commits ([7b296a4](7b296a4)) * **ci:** merge Release workflow into CI workflow with proper dependency ([906673e](906673e)) * **ci:** trigger CI on release-please PRs using workflow_run ([33ff7d3](33ff7d3)) * **ci:** update branch protection to match GitHub Actions status check format ([13efcf5](13efcf5)) * enable glob pattern for plugin.json version updates ([86fd628](86fd628)) * **handoff:** output notification to stderr to exclude from LLM context ([463bb08](463bb08)) * **marketplace:** remove databricks plugin reference ([f0bc6b8](f0bc6b8)) * **ralph-loop:** fix hooks matcher and stdin handling ([326a570](326a570)) * set release-please manifest to start from 4.3.0 ([#377](#377)) ([23a6cba](23a6cba)) ### Features * **bash-lsp:** add Bash Language Server plugin ([#394](#394)) ([7770f3d](7770f3d)) * **ci:** replace release-please with semantic-release ([35d346f](35d346f)) * **conversation-memory:** add automatic npm install when node_modules missing ([db55514](db55514)) * **conversation-memory:** add marked dependency for markdown rendering ([1887174](1887174)) * **conversation-memory:** improve MCP installation error handling ([#373](#373)) ([16eb7b7](16eb7b7)) * **conversation-memory:** reduce token usage in summarization ([d921bc7](d921bc7)) * **conversation-memory:** reduce token usage in summarization ([b3a245b](b3a245b)) * **handoff:** add session handoff plugin for context transfer ([#374](#374)) ([35cfb0c](35cfb0c)) * **me:** add tdd and spawn commands ([#371](#371)) ([9af9bbe](9af9bbe)) * migrate from semantic-release to Release Please ([#375](#375)) ([d20c736](d20c736)) * **release-please:** add auto-merge for release PRs ([cef4678](cef4678)) * **test-helpers:** extract shared BATS helpers to @baleen/bats-helpers package ([19f2a62](19f2a62)) * **tests:** run plugin tests in parallel using background processes ([04be773](04be773)) ### Performance Improvements * **tests:** add caching to improve test execution speed ([9bbee5b](9bbee5b)) ### BREAKING CHANGES * Release workflow now requires merging Release Please PRs instead of automatic releases on push to main. Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
* chore: prepare for 5.0.0 release * chore(release): 5.0.0 # [5.0.0](v4.3.0...v5.0.0) (2026-02-05) ### Bug Fixes * **ci:** disable strict status checks to allow semantic-release commits ([7b296a4](7b296a4)) * **ci:** merge Release workflow into CI workflow with proper dependency ([906673e](906673e)) * **ci:** trigger CI on release-please PRs using workflow_run ([33ff7d3](33ff7d3)) * **ci:** update branch protection to match GitHub Actions status check format ([13efcf5](13efcf5)) * enable glob pattern for plugin.json version updates ([86fd628](86fd628)) * **handoff:** output notification to stderr to exclude from LLM context ([463bb08](463bb08)) * **marketplace:** remove databricks plugin reference ([f0bc6b8](f0bc6b8)) * **ralph-loop:** fix hooks matcher and stdin handling ([326a570](326a570)) * set release-please manifest to start from 4.3.0 ([#377](#377)) ([23a6cba](23a6cba)) ### Features * **bash-lsp:** add Bash Language Server plugin ([#394](#394)) ([7770f3d](7770f3d)) * **ci:** replace release-please with semantic-release ([35d346f](35d346f)) * **conversation-memory:** add automatic npm install when node_modules missing ([db55514](db55514)) * **conversation-memory:** add marked dependency for markdown rendering ([1887174](1887174)) * **conversation-memory:** improve MCP installation error handling ([#373](#373)) ([16eb7b7](16eb7b7)) * **conversation-memory:** reduce token usage in summarization ([d921bc7](d921bc7)) * **conversation-memory:** reduce token usage in summarization ([b3a245b](b3a245b)) * **handoff:** add session handoff plugin for context transfer ([#374](#374)) ([35cfb0c](35cfb0c)) * **me:** add tdd and spawn commands ([#371](#371)) ([9af9bbe](9af9bbe)) * migrate from semantic-release to Release Please ([#375](#375)) ([d20c736](d20c736)) * **release-please:** add auto-merge for release PRs ([cef4678](cef4678)) * **test-helpers:** extract shared BATS helpers to @baleen/bats-helpers package ([19f2a62](19f2a62)) * **tests:** run plugin tests in parallel using background processes ([04be773](04be773)) ### Performance Improvements * **tests:** add caching to improve test execution speed ([9bbee5b](9bbee5b)) ### BREAKING CHANGES * Release workflow now requires merging Release Please PRs instead of automatic releases on push to main. Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com> * refactor(bash-lsp): migrate from MCP to LSP configuration - Remove .mcp.json file - Add lspServers field to plugin.json with bash-language-server config - Add .bats extension support for BATS test files Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test(bats): add lspServers to allowed plugin.json fields - Add lspServers to json_field_is_allowed function - Update error message to include lspServers in allowed fields list Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: semantic-release-bot <semantic-release-bot@martynus.net> Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
# [5.0.0](v4.3.0...v5.0.0) (2026-02-05) ### Bug Fixes * **ci:** disable strict status checks to allow semantic-release commits ([7b296a4](7b296a4)) * **ci:** merge Release workflow into CI workflow with proper dependency ([906673e](906673e)) * **ci:** trigger CI on release-please PRs using workflow_run ([33ff7d3](33ff7d3)) * **ci:** update bats-action to latest commit ([106b1f3](106b1f3)) * **ci:** update branch protection to match GitHub Actions status check format ([13efcf5](13efcf5)) * **ci:** use full commit SHA for bats-action ([9a70f52](9a70f52)) * **commands:** correct sdd command skill reference ([#403](#403)) ([a4db99c](a4db99c)) * enable glob pattern for plugin.json version updates ([86fd628](86fd628)) * **handoff:** output notification to stderr to exclude from LLM context ([463bb08](463bb08)) * **marketplace:** remove databricks plugin reference ([f0bc6b8](f0bc6b8)) * **ralph-loop:** fix hooks matcher and stdin handling ([326a570](326a570)) * **release:** add owner parameter to GitHub App token generation ([#401](#401)) ([b910a20](b910a20)) * **release:** remove GitHub App token generation ([ced7b17](ced7b17)) * **release:** restore GitHub App token generation ([45dd490](45dd490)) * **release:** use GitHub App token with Administration permission ([4077ecd](4077ecd)) * **release:** use GitHub App token with Administration permission ([#411](#411)) ([e6b1e9c](e6b1e9c)) * **release:** use GITHUB_TOKEN directly with github-actions[bot] bypass ([c7b517c](c7b517c)) * **release:** use GITHUB_TOKEN instead of custom GitHub App ([76a2a00](76a2a00)) * **release:** use secrets.GITHUB_TOKEN directly ([a2aaf50](a2aaf50)) * set release-please manifest to start from 4.3.0 ([#377](#377)) ([23a6cba](23a6cba)) ### Features * **bash-lsp:** add Bash Language Server plugin ([#394](#394)) ([7770f3d](7770f3d)) * **ci:** replace release-please with semantic-release ([35d346f](35d346f)) * **conversation-memory:** add automatic npm install when node_modules missing ([db55514](db55514)) * **conversation-memory:** add file-based logging system ([81f65bd](81f65bd)) * **conversation-memory:** add marked dependency for markdown rendering ([1887174](1887174)) * **conversation-memory:** improve MCP installation error handling ([#373](#373)) ([16eb7b7](16eb7b7)) * **conversation-memory:** reduce token usage in summarization ([d921bc7](d921bc7)) * **conversation-memory:** reduce token usage in summarization ([b3a245b](b3a245b)) * **databricks-devtools:** add Databricks CLI wrapper plugin ([#408](#408)) ([7baf422](7baf422)) * **handoff:** add session handoff plugin for context transfer ([#374](#374)) ([35cfb0c](35cfb0c)) * **lsp-support:** add Kotlin, Lua, Nix LSP servers, merge bash-lsp ([8f1ee4f](8f1ee4f)) * **me:** add commit skill ([8d0cf1c](8d0cf1c)) * **me:** add tdd and spawn commands ([#371](#371)) ([9af9bbe](9af9bbe)) * migrate from semantic-release to Release Please ([#375](#375)) ([d20c736](d20c736)) * **release-please:** add auto-merge for release PRs ([cef4678](cef4678)) * **test-helpers:** extract shared BATS helpers to @baleen/bats-helpers package ([19f2a62](19f2a62)) * **tests:** run plugin tests in parallel using background processes ([04be773](04be773)) ### Performance Improvements * **tests:** add caching to improve test execution speed ([9bbee5b](9bbee5b)) ### BREAKING CHANGES * Release workflow now requires merging Release Please PRs instead of automatic releases on push to main. Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
* chore: prepare for 5.0.0 release * chore(release): 5.0.0 # [5.0.0](baleen37/bstack@v4.3.0...v5.0.0) (2026-02-05) ### Bug Fixes * **ci:** disable strict status checks to allow semantic-release commits ([7b296a4](baleen37/bstack@7b296a4)) * **ci:** merge Release workflow into CI workflow with proper dependency ([906673e](baleen37/bstack@906673e)) * **ci:** trigger CI on release-please PRs using workflow_run ([33ff7d3](baleen37/bstack@33ff7d3)) * **ci:** update branch protection to match GitHub Actions status check format ([13efcf5](baleen37/bstack@13efcf5)) * enable glob pattern for plugin.json version updates ([86fd628](baleen37/bstack@86fd628)) * **handoff:** output notification to stderr to exclude from LLM context ([463bb08](baleen37/bstack@463bb08)) * **marketplace:** remove databricks plugin reference ([f0bc6b8](baleen37/bstack@f0bc6b8)) * **ralph-loop:** fix hooks matcher and stdin handling ([326a570](baleen37/bstack@326a570)) * set release-please manifest to start from 4.3.0 ([#377](baleen37/bstack#377)) ([23a6cba](baleen37/bstack@23a6cba)) ### Features * **bash-lsp:** add Bash Language Server plugin ([#394](baleen37/bstack#394)) ([7770f3d](baleen37/bstack@7770f3d)) * **ci:** replace release-please with semantic-release ([35d346f](baleen37/bstack@35d346f)) * **conversation-memory:** add automatic npm install when node_modules missing ([db55514](baleen37/bstack@db55514)) * **conversation-memory:** add marked dependency for markdown rendering ([1887174](baleen37/bstack@1887174)) * **conversation-memory:** improve MCP installation error handling ([#373](baleen37/bstack#373)) ([16eb7b7](baleen37/bstack@16eb7b7)) * **conversation-memory:** reduce token usage in summarization ([d921bc7](baleen37/bstack@d921bc7)) * **conversation-memory:** reduce token usage in summarization ([b3a245b](baleen37/bstack@b3a245b)) * **handoff:** add session handoff plugin for context transfer ([#374](baleen37/bstack#374)) ([35cfb0c](baleen37/bstack@35cfb0c)) * **me:** add tdd and spawn commands ([#371](baleen37/bstack#371)) ([9af9bbe](baleen37/bstack@9af9bbe)) * migrate from semantic-release to Release Please ([#375](baleen37/bstack#375)) ([d20c736](baleen37/bstack@d20c736)) * **release-please:** add auto-merge for release PRs ([cef4678](baleen37/bstack@cef4678)) * **test-helpers:** extract shared BATS helpers to @baleen/bats-helpers package ([19f2a62](baleen37/bstack@19f2a62)) * **tests:** run plugin tests in parallel using background processes ([04be773](baleen37/bstack@04be773)) ### Performance Improvements * **tests:** add caching to improve test execution speed ([9bbee5b](baleen37/bstack@9bbee5b)) ### BREAKING CHANGES * Release workflow now requires merging Release Please PRs instead of automatic releases on push to main. Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com> * refactor(bash-lsp): migrate from MCP to LSP configuration - Remove .mcp.json file - Add lspServers field to plugin.json with bash-language-server config - Add .bats extension support for BATS test files Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test(bats): add lspServers to allowed plugin.json fields - Add lspServers to json_field_is_allowed function - Update error message to include lspServers in allowed fields list Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: semantic-release-bot <semantic-release-bot@martynus.net> Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Summary
Replace semantic-release with Release Please to solve branch protection issues by using a PR-based release workflow instead of direct commits to main.
Problem Solved
Solution: Release Please PR-Based Workflow
Release Please creates release PRs instead of pushing commits directly:
Changes Made
.release-please-manifest.json,release-please-config.json).github/workflows/release-please.yml).github/workflows/sync-marketplace.yml)scripts/sync-marketplace-version.sh)package.json.releaserc.js)Benefits
Breaking Change
Next Steps
After merging this PR, Release Please will:
Test Plan
🤖 Generated with Claude Code
Summary by CodeRabbit
Release Notes