feat: Automatic version bumping from configured targets#707
Conversation
When minVersion >= 2.19.0 and no preReleaseCommand is defined, Craft automatically bumps version numbers based on configured publish targets. Supported targets: - npm: npm version --no-git-tag-version - pypi: hatch, poetry, setuptools-scm, or direct pyproject.toml edit - crates: cargo set-version (cargo-edit) - gem: Direct edit of gemspec and lib/**/version.rb - pub-dev: Direct edit of pubspec.yaml - hex: Direct edit of mix.exs - nuget: dotnet-setversion or direct XML edit Fixes #76
Semver Impact of This PR🟡 Minor (new features) 📋 Changelog PreviewThis is how your changes will appear in the changelog. New Features ✨
🤖 This preview updates automatically when you update the PR. |
For npm/yarn/pnpm monorepos, automatically detect and bump versions in all workspace packages: - npm 7+: Uses npm version --workspaces - yarn/pnpm or npm < 7: Falls back to individual package bumping Private packages are skipped during workspace version bumping.
Tests cover: - runAutomaticVersionBumps utility function - NpmTarget.bumpVersion (including workspace detection) - PypiTarget.bumpVersion (hatch, poetry, setuptools-scm, direct edit) - CratesTarget.bumpVersion - GemTarget.bumpVersion - PubDevTarget.bumpVersion - HexTarget.bumpVersion - NugetTarget.bumpVersion
- Remove obvious comments (// Check if X exists) - Simplify verbose multi-line comments to single lines - Remove redundant JSDoc field descriptions - Clean up try/catch blocks with explicit early returns - Shorten verbose error messages
| For npm/yarn/pnpm monorepos, Craft automatically detects and bumps versions in all workspace packages: | ||
|
|
||
| - **npm 7+**: Uses `npm version --workspaces` to bump all packages at once | ||
| - **yarn/pnpm or npm < 7**: Falls back to bumping each non-private package individually |
There was a problem hiding this comment.
where's my dear Bun? we can add it later, i think we could just look for Bun lockfiles bun.lockb / bun.lock, add BUN_BIN, USE_BUN env vars, and bun publishsupport.
There was a problem hiding this comment.
it supports workspaces too https://bun.com/docs/pm/workspaces
|
Re: Gem monorepo support Updated! The gem target now searches for
The implementation uses the Re: Bun support Great suggestion! Bun support (lockfile detection via |
- Add 'ignore' package for gitignore-aware file traversal - Add findFiles() utility that respects .gitignore patterns - Update GemTarget.bumpVersion() to search up to 2 levels deep - Convert gem target methods to async fs/promises APIs - Add tests for monorepo support (sentry-ruby style)
|
Addresses PR review comments to update the minimum version required for automatic version bumping from targets to 2.21.0, which will be the release version for this feature.
Replace readdir with opendir and async for...of loop for more memory-efficient directory traversal. The async iterator processes entries one at a time rather than loading all entries into memory. Addresses PR review feedback.
Add helper functions to centralize the common pattern of: 1. Resolving executable path (with optional env var override) 2. Checking if executable exists 3. Throwing helpful error if not found 4. Running the command with debug logging New exports in system.ts: - ExecutableConfig: interface for configuring executable resolution - resolveExecutable(): resolve binary path from config - runWithExecutable(): check and run executable in one call Updated targets to use the new helper: - pypi.ts: bumpWithHatch, bumpWithPoetry - crates.ts: bumpVersion Closes #738
Add support for trying multiple executables in order: - findFirstExecutable(): finds first available from array of configs - requireFirstExecutable(): same but throws if none found - runWithExecutable(): now accepts single config or array Updated npm.ts to use the new abstraction: - Uses requireFirstExecutable([NPM_CONFIG, YARN_CONFIG]) - Returns index to determine which executable was found - Replaces manual hasExecutable checks with cleaner pattern
…ling - Mock runWithExecutable in tests since it calls hasExecutable internally - Use module-scope mock functions for proper test configuration - Remove explicit dir.close() since for-await-of handles cleanup automatically
vi.mock is hoisted to top of file, so mock functions must be created with vi.hoisted() to be available during the mock factory execution.
|
@sentry review |
|
@cursoragent review |
|
Perfect! I've completed a comprehensive review of this PR. Let me provide you with my findings. Code Review SummaryOverall Assessment ✅This is a well-designed and thoroughly implemented feature that adds automatic version bumping for multiple package ecosystems. The code quality is excellent, with comprehensive tests and good documentation. Strengths
Key Implementation DetailsVersion Bump Flow:
Target Implementations:
Minor Issues Found (Non-blocking)
import { logger } from '../logger'; // Only used in bumpVersion, not in main class
catch (e) { // 'e' defined but never used
Addressed PR CommentsAll previous PR feedback has been addressed:
Recommendations
Testing
Final VerdictAPPROVED ✅ This PR is ready to merge. The implementation is solid, well-tested, and follows the project's coding standards. The automatic version bumping feature will significantly improve the developer experience by eliminating the need for custom bump-version scripts in most cases. The feature is properly gated behind |
- Return detailed VersionBumpResult from runAutomaticVersionBumps - Provide specific warnings for: - No targets support version bumping - Targets support it but didn't find applicable files - Add recovery documentation for failed prepare after version bump - Update tests for new return type


Summary
When
minVersion >= 2.21.0and no custompreReleaseCommandis defined, Craft automatically bumps version numbers based on configured publish targets. This eliminates the need for ascripts/bump-version.shscript in most cases.How It Works
targetsin.craft.ymlSupported Targets
npmpackage.jsonnpm version --no-git-tag-versionpypipyproject.tomlcratesCargo.tomlcargo set-version(cargo-edit)gem*.gemspeclib/**/version.rbpub-devpubspec.yamlhexmix.exsnuget*.csprojPython (pypi) Detection Priority
[tool.hatch]→hatch version <version>[tool.poetry]→poetry version <version>[tool.setuptools_scm]→ No-op (version from git tags)[project]with version → Direct TOML editBreaking Changes
None. Existing projects continue to work unchanged. The feature is gated behind
minVersion: "2.21.0".Fixes #76