Summary
- Replace
intuit/auto and @bepower/auto-config with release-please as the standard release tool for all ~30 library repositories publishing to GitHub Packages.
- Adopt the
develop/main locked-branch model (already our standard for AWS project repos) for library repos as well.
- Use
develop for prerelease publishes (@next dist-tag) and main for stable releases (@latest dist-tag).
- Deprecate
@bepower/auto-config.
Motivation
intuit/auto is effectively abandoned
- Last release: v11.3.6 (no new releases in over a year)
- 122 open issues, 38 open PRs, near-zero development activity
- Not formally archived, but no maintainer is actively triaging or merging
- Our
@auto-it/* dependencies (^11.0.5) will never receive security patches or compatibility fixes
- Staying on
auto across ~30 repos means accumulating risk with every Node.js and npm update
Inconsistent branching model
Our AWS project repos already use a locked main + develop branch model. Our library repos don't. This creates cognitive overhead when switching between project types. Aligning the two means one workflow to learn, one model to enforce.
No prerelease channel
With auto, we have no way to publish a prerelease version for testing before promoting to stable. Teams that want to test a library change in a downstream project have to either publish a full release or use npm link / local paths.
Why release-please
Active maintenance
- Current version: v17.6.0 (released April 13, 2026)
- Multiple releases per month, actively maintained by Google
- 6.7k GitHub stars, 539 forks
Fit for our workflow
| Requirement |
release-please |
| Conventional Commits |
✅ Native (we already use them everywhere) |
| Changelog generation |
✅ Automatic, from commit history |
| GitHub Releases + tags |
✅ Built-in |
| Publish to GitHub Packages |
✅ Decoupled — we handle npm publish ourselves |
| Prerelease versions |
✅ Native support for non-default branches |
| Review before release |
✅ Creates a Release PR the team can review |
| Monorepo (independent versions) |
✅ Manifest-based, per-package versioning |
Why not the alternatives?
| Tool |
Why not |
| semantic-release |
No Release PR review step. Every merge publishes immediately. Monorepo support is community-plugin only. |
| Changesets |
Requires manual changeset files per PR. More ceremony than we need. JS-only. |
Proposed branching model (all library repos)
Flow
feature-branch → PR → develop
│
release-please opens Release PR (v2.1.0-beta.1)
│
merge Release PR → publish @next to GitHub Packages
│
develop → PR → main
│
release-please opens Release PR (v2.1.0)
│
merge Release PR → publish @latest to GitHub Packages
Branch rules
| Branch |
Push |
Purpose |
main |
🔒 PR only |
Stable releases (@latest) |
develop |
🔒 PR only |
Prerelease versions (@next) |
feature/*, fix/*, etc. |
✅ Free push |
Day-to-day work |
Merge strategy
When merging develop → main, use merge commit (no squash, no rebase). release-please traverses merge commits and reads the individual conventional commits inside. Squash merging would collapse all commits into one, losing changelog granularity.
Default branch
Keep main as the default branch in GitHub. This is important because release-please treats the default branch as the stable release branch. If develop were the default, release-please would generate stable versions there instead of prereleases.
Developers target develop for feature PRs by convention, enforced by branch protection rules.
How release-please works
Configuration
Each repo needs exactly 2 config files + 1 workflow.
release-please-config.json (repo root)
{
"release-type": "node",
"prerelease": true,
"packages": {
".": {}
}
}
"release-type": "node" — updates package.json version fields
"prerelease": true — on non-default branches (develop), generates versions like 2.1.0-beta.1; on main, this flag is ignored and stable versions are generated
"packages" — for single-package repos use ".", for monorepos list each package path
.release-please-manifest.json (repo root)
Set this once to match the current published version. After the first release, release-please maintains it automatically.
Where is what configured
| What |
Where |
| Which packages to release |
release-please-config.json |
| Current version per package |
.release-please-manifest.json |
| Enable prerelease on non-default branches |
"prerelease": true in config JSON |
| Which branches trigger release-please |
Workflow YAML (on.push.branches) |
| Which branch is stable vs prerelease |
Automatic: repo's default branch = stable, all others = prerelease |
No CLI commands to run manually after setup. Everything is file-driven.
Pilot: bep-cdk
We'll use bep-cdk as the pilot repo. It's a good candidate because:
- It's a monorepo with 2 independently versioned packages (
@bepower/bep-cdk at v7.124.4, @bepower/bep-cdk-lib at v10.99.4)
- It already uses
@bepower/auto-config, lerna, conventional commits, and publishes to GitHub Packages
- It has a CI workflow + a release workflow — representative of all our library repos
Current setup (before)
auto.config.ts:
import base, { coverage, packages } from '@bepower/auto-config';
export default function config(): AutoRc {
base.plugins?.push(packages);
base.plugins?.push([coverage, coverageOptions]);
return base;
}
npm.yaml (release workflow): runs auto shipit on push to main.
ci.yaml: tests on Node 20, 22, 24.
Dependencies: @bepower/auto-config, auto, @auto-it/* (5+ packages), lerna.
Proposed setup (after)
release-please-config.json:
{
"release-type": "node",
"prerelease": true,
"packages": {
"packages/bep-cdk": {},
"packages/bep-cdk-lib": {}
}
}
.release-please-manifest.json:
{
"packages/bep-cdk": "7.124.4",
"packages/bep-cdk-lib": "10.99.4"
}
ci.yaml (replaces both ci.yaml and npm.yaml):
name: CI
on:
push:
branches:
- main
- develop
pull_request:
branches:
- main
- develop
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node: [22, 24]
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node }}
registry-url: 'https://npm.pkg.github.com'
scope: '@bepower'
cache: npm
- run: npm ci
env:
GITHUB_TOKEN: ${{ github.token }}
- run: npm test
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: 'lts/*'
registry-url: 'https://npm.pkg.github.com'
scope: '@bepower'
cache: npm
- run: npm ci
env:
GITHUB_TOKEN: ${{ github.token }}
- run: npm run lint
- name: Check if nothing changed
run: git diff --name-only --exit-code
release-please:
if: github.event_name == 'push'
needs: [test, lint]
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
outputs:
releases_created: ${{ steps.release.outputs['packages/bep-cdk--release_created'] == 'true' || steps.release.outputs['packages/bep-cdk-lib--release_created'] == 'true' }}
steps:
- uses: googleapis/release-please-action@v4
id: release
with:
token: ${{ secrets.GITHUB_TOKEN }}
target-branch: ${{ github.ref_name }}
publish:
if: needs.release-please.outputs.releases_created == 'true'
needs: release-please
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: 'lts/*'
registry-url: 'https://npm.pkg.github.com'
scope: '@bepower'
cache: npm
- run: npm ci
env:
GITHUB_TOKEN: ${{ github.token }}
- run: npm run build
- name: Publish packages with appropriate dist-tag
run: |
TAG="latest"
if [ "${{ github.ref_name }}" != "main" ]; then
TAG="next"
fi
npm publish -w packages/bep-cdk --tag "$TAG" || true
npm publish -w packages/bep-cdk-lib --tag "$TAG" || true
env:
NODE_AUTH_TOKEN: ${{ github.token }}
Note: || true on publish commands prevents failure if only one of the two packages has a new version. npm publish will fail with "already published" for the unchanged package — this is expected.
Note on the Action vs CLI: the workflow uses googleapis/release-please-action@v4. For monorepos, use the per-package output <path>--release_created (not the global releases_created). If the team prefers the CLI approach:
- run: npx release-please release-pr --token=${{ secrets.GITHUB_TOKEN }} --repo-url=BePower/bep-cdk --target-branch=${{ github.ref_name }}
- run: npx release-please github-release --token=${{ secrets.GITHUB_TOKEN }} --repo-url=BePower/bep-cdk --target-branch=${{ github.ref_name }}
What gets removed from bep-cdk
| File/dependency |
Action |
auto.config.ts |
Delete |
lerna.json |
Delete |
@bepower/auto-config |
npm uninstall |
"release" script in package.json |
Remove |
.github/workflows/npm.yaml |
Delete (merged into ci.yaml) |
What gets added
| File |
Purpose |
release-please-config.json |
Package + release config |
.release-please-manifest.json |
Current versions |
Updated .github/workflows/ci.yaml |
CI + release-please + publish |
Migration playbook (per repo)
After the pilot is validated, each repo follows these steps:
1. Create develop branch
git checkout main && git pull
git checkout -b develop
git push -u origin develop
2. Add release-please config files
release-please-config.json — adapt packages to your repo:
{
"release-type": "node",
"prerelease": true,
"packages": {
".": {}
}
}
.release-please-manifest.json — set current published version:
3. Replace the GitHub Actions workflow
Use the template from the pilot section above. Adapt test/lint jobs to match your repo.
4. Remove auto configuration and dependencies
rm -f .autorc .autorc.js .autorc.ts .autorc.json auto.config.ts lerna.json
npm uninstall auto @auto-it/core @auto-it/conventional-commits @auto-it/all-contributors \
@auto-it/first-time-contributor @auto-it/magic-zero @bepower/auto-config lerna
Remove the "release" script from package.json.
5. Lock branches in GitHub repo settings
- Settings → Branches → Branch protection rules
main: require PR, require status checks, no direct push
develop: require PR, require status checks, no direct push
6. Commit and push
git add release-please-config.json .release-please-manifest.json .github/workflows/
git commit -m "feat: migrate from auto to release-please"
git push
Checklist
[ ] Create develop branch from main
[ ] Add release-please-config.json
[ ] Add .release-please-manifest.json (with current version)
[ ] Replace/update GitHub Actions workflow
[ ] Delete auto config file (.autorc* / auto.config.ts)
[ ] Delete lerna.json
[ ] Remove auto / @auto-it/* / @bepower/auto-config / lerna dependencies
[ ] Remove "release" script from package.json
[ ] Lock main branch (require PR)
[ ] Lock develop branch (require PR)
[ ] Verify first Release PR is created correctly
Rollout plan
| Phase |
Timeline |
Scope |
| Pilot |
Week 1 |
Migrate bep-cdk. Validate end-to-end: Release PR creation, changelog, tag, GitHub Release, publish to GitHub Packages. |
| Early adopters |
Week 2-3 |
Migrate 3-5 repos volunteered by team members. Collect feedback, refine the playbook. |
| Full rollout |
Week 4+ |
Migrate remaining repos. Can be done gradually — auto and release-please don't conflict. |
What changes for developers day-to-day
| Before |
After |
Push/merge to main |
Push to feature branch, PR to develop |
| Release happens automatically on merge |
Release PR appears, team reviews, then merges |
| No prerelease testing |
Install @next to test before stable release |
npx auto shipit in CI |
No release command — release-please handles it |
| Commit conventions: same |
Commit conventions: same (conventional commits) |
@bepower/auto-config deprecation
Once all repos are migrated:
- Publish a final version of
@bepower/auto-config with npm deprecate message pointing to this RFC
- Archive the package in
dev-configs repo
Open questions
References
Summary
intuit/autoand@bepower/auto-configwithrelease-pleaseas the standard release tool for all ~30 library repositories publishing to GitHub Packages.develop/mainlocked-branch model (already our standard for AWS project repos) for library repos as well.developfor prerelease publishes (@nextdist-tag) andmainfor stable releases (@latestdist-tag).@bepower/auto-config.Motivation
intuit/autois effectively abandoned@auto-it/*dependencies (^11.0.5) will never receive security patches or compatibility fixesautoacross ~30 repos means accumulating risk with every Node.js and npm updateInconsistent branching model
Our AWS project repos already use a locked
main+developbranch model. Our library repos don't. This creates cognitive overhead when switching between project types. Aligning the two means one workflow to learn, one model to enforce.No prerelease channel
With
auto, we have no way to publish a prerelease version for testing before promoting to stable. Teams that want to test a library change in a downstream project have to either publish a full release or usenpm link/ local paths.Why
release-pleaseActive maintenance
Fit for our workflow
npm publishourselvesWhy not the alternatives?
Proposed branching model (all library repos)
Flow
Branch rules
main@latest)develop@next)feature/*,fix/*, etc.Merge strategy
When merging
develop→main, use merge commit (no squash, no rebase). release-please traverses merge commits and reads the individual conventional commits inside. Squash merging would collapse all commits into one, losing changelog granularity.Default branch
Keep
mainas the default branch in GitHub. This is important because release-please treats the default branch as the stable release branch. Ifdevelopwere the default, release-please would generate stable versions there instead of prereleases.Developers target
developfor feature PRs by convention, enforced by branch protection rules.How release-please works
Configuration
Each repo needs exactly 2 config files + 1 workflow.
release-please-config.json(repo root){ "release-type": "node", "prerelease": true, "packages": { ".": {} } }"release-type": "node"— updatespackage.jsonversion fields"prerelease": true— on non-default branches (develop), generates versions like2.1.0-beta.1; onmain, this flag is ignored and stable versions are generated"packages"— for single-package repos use".", for monorepos list each package path.release-please-manifest.json(repo root){ ".": "1.5.3" }Set this once to match the current published version. After the first release, release-please maintains it automatically.
Where is what configured
release-please-config.json.release-please-manifest.json"prerelease": truein config JSONon.push.branches)No CLI commands to run manually after setup. Everything is file-driven.
Pilot:
bep-cdkWe'll use
bep-cdkas the pilot repo. It's a good candidate because:@bepower/bep-cdkat v7.124.4,@bepower/bep-cdk-libat v10.99.4)@bepower/auto-config,lerna, conventional commits, and publishes to GitHub PackagesCurrent setup (before)
auto.config.ts:npm.yaml(release workflow): runsauto shipiton push tomain.ci.yaml: tests on Node 20, 22, 24.Dependencies:
@bepower/auto-config,auto,@auto-it/*(5+ packages),lerna.Proposed setup (after)
release-please-config.json:{ "release-type": "node", "prerelease": true, "packages": { "packages/bep-cdk": {}, "packages/bep-cdk-lib": {} } }.release-please-manifest.json:{ "packages/bep-cdk": "7.124.4", "packages/bep-cdk-lib": "10.99.4" }ci.yaml(replaces bothci.yamlandnpm.yaml):What gets removed from
bep-cdkauto.config.tslerna.json@bepower/auto-confignpm uninstall"release"script inpackage.json.github/workflows/npm.yamlci.yaml)What gets added
release-please-config.json.release-please-manifest.json.github/workflows/ci.yamlMigration playbook (per repo)
After the pilot is validated, each repo follows these steps:
1. Create
developbranchgit checkout main && git pull git checkout -b develop git push -u origin develop2. Add release-please config files
release-please-config.json— adaptpackagesto your repo:{ "release-type": "node", "prerelease": true, "packages": { ".": {} } }.release-please-manifest.json— set current published version:{ ".": "1.2.3" }3. Replace the GitHub Actions workflow
Use the template from the pilot section above. Adapt test/lint jobs to match your repo.
4. Remove
autoconfiguration and dependenciesRemove the
"release"script frompackage.json.5. Lock branches in GitHub repo settings
main: require PR, require status checks, no direct pushdevelop: require PR, require status checks, no direct push6. Commit and push
git add release-please-config.json .release-please-manifest.json .github/workflows/ git commit -m "feat: migrate from auto to release-please" git pushChecklist
Rollout plan
bep-cdk. Validate end-to-end: Release PR creation, changelog, tag, GitHub Release, publish to GitHub Packages.autoandrelease-pleasedon't conflict.What changes for developers day-to-day
maindevelop@nextto test before stable releasenpx auto shipitin CI@bepower/auto-configdeprecationOnce all repos are migrated:
@bepower/auto-configwithnpm deprecatemessage pointing to this RFCdev-configsrepoOpen questions
@nextfrom day one, or add it later? (Easy to add — just adddevelopto workflow triggers and set"prerelease": true.)develop→main(recommended) or another preference?References