Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/src/content/docs/versioning.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ Craft reads it from the files of the first configured target that
[supports version bumping](#supported-targets) and declares a semver version
above `0.0.0`. Without one, they increment `0.0.0`.

Before `1.0.0`, `auto` and `pre` treat breaking changes as a minor bump, so
`0.5.0` becomes `0.6.0`. Pass `1.0.0` or `major` to release `1.0.0`.

After a prerelease, bump types and `auto` promote it to a stable release:
`2.1.0-alpha.3` becomes `2.1.0`, or a higher version when the bump needs one.
To be safe, `auto` doesn't promote a prerelease to a major release: after
Expand Down
41 changes: 41 additions & 0 deletions src/__tests__/prepare-dry-run.e2e.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -778,6 +778,47 @@ targets: []
expect(output).not.toContain('Add foo feature in');
}, 60000);

test.each([
['auto', '0.6.0'],
['pre', '0.6.0-alpha.0'],
['major', '1.0.0'],
])(
'a breaking change before 1.0.0 with %s releases %s',
async (versionArg, expected) => {
tempDir = await createTestRepo();
// eslint-disable-next-line no-restricted-syntax -- Test setup needs direct git access
const git = simpleGit(tempDir);
await writeFile(
join(tempDir, '.craft.yml'),
`minVersion: "3.9.0"
github:
owner: test-owner
repo: test-repo
changelog:
policy: auto
preReleaseCommand: ""
targets: []
`,
);
await git.add('.');
await git.commit('chore: Enable automatic versioning');
await git.addTag('0.5.0');
await writeFile(join(tempDir, 'baz.ts'), 'export const baz = 3;');
await git.add('.');
await git.commit('feat!: Remove the old baz API');
await git.push('origin', (await git.status()).current!);

const { stdout, stderr } = await execFileAsync(
CLI_BIN,
['prepare', versionArg, '--dry-run', '--no-input'],
{ cwd: tempDir, env: { ...CLI_ENV, GITHUB_TOKEN: '' } },
);

expect(stdout + stderr).toContain(`Version bump: 0.5.0 -> ${expected}`);
},
60000,
);

test('prepares a workspace changelog without changing the root changelog', async () => {
tempDir = await createTestRepo();
// eslint-disable-next-line no-restricted-syntax -- Test setup needs direct git access
Expand Down
27 changes: 18 additions & 9 deletions src/commands/prepare.ts
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,15 @@ async function resolveVersion(

const latestTag = await getLatestTag(git, getGitTagPrefix());

// Calculate new version from the latest tag. Before the first tag, start
// from the version in the release unit's project files, so a workspace at
// `1.0.0-dev.0` releases `1.0.0` instead of a bump of `0.0.0`. Bumping a
// prerelease promotes it, so `2.0.0-alpha.3` releases `2.0.0`.
const currentVersion =
(latestTag && getVersion(latestTag)) ||
(await readProjectVersion(config.targets || [], getReleaseUnitDir())) ||
'0.0.0';

// Determine bump type - either from arg or from commit analysis
let bumpType: BumpType;
if (version === 'auto' || version === 'pre') {
Expand All @@ -726,19 +735,19 @@ async function resolveVersion(
);
validateBumpType(changelogResult);
bumpType = changelogResult.bumpType;
if (bumpType === 'major' && semver.major(currentVersion) === 0) {
// Before 1.0.0, breaking changes bump the minor version. Releasing
// 1.0.0 is a decision, so it takes an explicit `major` or version.
logger.info(
`${currentVersion} is below 1.0.0, so the breaking changes bump ` +
'the minor version. Pass "major" to release 1.0.0.',
);
bumpType = 'minor';
}
} else {
bumpType = version as BumpType;
}

// Calculate new version from the latest tag. Before the first tag, start
// from the version in the release unit's project files, so a workspace at
// `1.0.0-dev.0` releases `1.0.0` instead of a bump of `0.0.0`. Bumping a
// prerelease promotes it, so `2.0.0-alpha.3` releases `2.0.0`.
const currentVersion =
(latestTag && getVersion(latestTag)) ||
(await readProjectVersion(config.targets || [], getReleaseUnitDir())) ||
'0.0.0';

let newVersion = calculateNextVersion(currentVersion, bumpType);
if (version === 'pre') {
// `pre` cuts a prerelease of the version `auto` would release.
Expand Down
Loading