mirror of
https://github.com/AventurasTeam/Aventuras.git
synced 2026-10-20 20:06:17 +00:00
## Release script - Version arithmetic extracted into `scripts/version.js`, covered by `scripts/version.test.js` (17 cases). `vitest.config.ts` now includes `scripts/**/*.test.js` for it. - **Every precondition is checked before anything is written**: a clean tree, a version that moves forward, and a tag/branch that exists neither locally *nor on the remote*. A failure after that point deletes the branch and tag it created and returns to the original branch. - `--dry-run` runs the checks and stops. `--no-merge-back` skips the fast-forward of the branch the script was run from. - Unknown flags are rejected rather than silently ignored. - The rollback's `reset --hard` is guarded behind a **successful checkout**: it moves the *current* branch, so a failed checkout dragged the release branch onto the start commit. - Everything after the push is explicitly best-effort and is **not** rolled back — the tag is out and the release is building, so a protected branch or a race there is a reason to print two commands, not to unpick a published release. - Only `X.Y.Z` and `X.Y.Z-pre.N` are accepted. Other pre-release spellings are valid semver but match neither workflow trigger, so they would tag and build nothing. - Works on Windows again. Note the `--` in `npm run release -- <bump>`: without it npm consumes the flags before the script sees them. Documented in the README. ## eslint `eslint-plugin-boundaries` v7 renamed `rules` to `policies` and takes the element type inside the `disallow` target rather than in a second outer `to`. The config was still written for the v6 shape — it worked, but on the deprecated path. Verified **warning-for-warning identical** across the repo: 189 warnings, same files, same positions, before and after. `mode: 'folder'` dropped where it is already the default. ## Android `src-tauri/gen/android/app/tauri.build.gradle.kts` is autogenerated by the Tauri CLI and was being regenerated on every build, so it showed up as a dirty file constantly. Untracked and gitignored. --- Base: `upstream/master`. `check`, `lint` and the full Vitest suite pass. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Improved release automation with validation, dry-run support, rollback handling, and optional branch merge-back. * Added support for stable and prerelease version validation, comparison, and version bumping. * **Bug Fixes** * Added safeguards for repository state, remote references, network availability, and Windows npm execution. * **Documentation** * Expanded release instructions with supported version formats, safety checks, rollback behavior, and usage options. * **Tests** * Added comprehensive coverage for version handling and release-related scenarios.
107 lines
4 KiB
JavaScript
107 lines
4 KiB
JavaScript
import { describe, it, expect } from 'vitest'
|
|
import { bumpVersion, isValidVersion, parseVersion, compareVersions } from './version.js'
|
|
|
|
describe('bumpVersion', () => {
|
|
it('bumps a stable version', () => {
|
|
expect(bumpVersion('0.7.6', 'patch')).toBe('0.7.7')
|
|
expect(bumpVersion('0.7.6', 'minor')).toBe('0.8.0')
|
|
expect(bumpVersion('0.7.6', 'major')).toBe('1.0.0')
|
|
})
|
|
|
|
it('promotes a pre-release that already sits at the level being bumped', () => {
|
|
expect(bumpVersion('0.7.6-pre.1', 'patch')).toBe('0.7.6')
|
|
expect(bumpVersion('0.8.0-pre.1', 'minor')).toBe('0.8.0')
|
|
expect(bumpVersion('1.0.0-pre.1', 'major')).toBe('1.0.0')
|
|
})
|
|
|
|
it('never moves backwards from a pre-release', () => {
|
|
expect(bumpVersion('0.7.6-pre.1', 'minor')).toBe('0.8.0')
|
|
expect(bumpVersion('0.7.6-pre.1', 'major')).toBe('1.0.0')
|
|
})
|
|
|
|
it('moves the patch before starting a pre-release from a stable version', () => {
|
|
// The alternative sorts before the version already shipped: an offered downgrade.
|
|
expect(bumpVersion('0.7.6', 'prerelease')).toBe('0.7.7-pre.1')
|
|
expect(compareVersions(bumpVersion('0.7.6', 'prerelease'), '0.7.6')).toBeGreaterThan(0)
|
|
})
|
|
|
|
it('counts up within a pre-release series', () => {
|
|
expect(bumpVersion('0.7.7-pre.1', 'prerelease')).toBe('0.7.7-pre.2')
|
|
expect(bumpVersion('0.7.7-pre.9', 'prerelease')).toBe('0.7.7-pre.10')
|
|
})
|
|
|
|
it('every bump type produces a version strictly greater than its input', () => {
|
|
const inputs = ['0.0.0', '0.7.6', '1.0.0', '0.7.6-pre.1', '0.8.0-pre.2', '1.0.0-pre.1']
|
|
for (const from of inputs) {
|
|
for (const type of ['major', 'minor', 'patch', 'prerelease']) {
|
|
const to = bumpVersion(from, type)
|
|
expect(
|
|
compareVersions(to, from),
|
|
`${from} + ${type} produced ${to}, which does not follow it`,
|
|
).toBeGreaterThan(0)
|
|
}
|
|
}
|
|
})
|
|
|
|
it('passes a literal version straight through', () => {
|
|
expect(bumpVersion('0.7.6', '1.2.3')).toBe('1.2.3')
|
|
})
|
|
|
|
it('returns undefined when no type was given, which the caller reports as usage', () => {
|
|
expect(bumpVersion('0.7.6', undefined)).toBeUndefined()
|
|
})
|
|
})
|
|
|
|
describe('isValidVersion', () => {
|
|
it('accepts the two shapes the release workflows build', () => {
|
|
expect(isValidVersion('0.7.6')).toBe(true)
|
|
expect(isValidVersion('0.7.6-pre.1')).toBe(true)
|
|
expect(isValidVersion('10.20.30')).toBe(true)
|
|
})
|
|
|
|
it('rejects a pre-release shape no workflow would build', () => {
|
|
expect(isValidVersion('1.2.3-beta.1')).toBe(false)
|
|
expect(isValidVersion('1.2.3-pre')).toBe(false)
|
|
})
|
|
|
|
it('rejects anything that is not a version', () => {
|
|
expect(isValidVersion('banana')).toBe(false)
|
|
expect(isValidVersion('; rm -rf /')).toBe(false)
|
|
expect(isValidVersion('1.2')).toBe(false)
|
|
expect(isValidVersion('v1.2.3')).toBe(false)
|
|
expect(isValidVersion('')).toBe(false)
|
|
expect(isValidVersion(undefined)).toBe(false)
|
|
})
|
|
})
|
|
|
|
describe('compareVersions', () => {
|
|
it('orders a pre-release before the version it leads to', () => {
|
|
expect(compareVersions('0.7.6-pre.1', '0.7.6')).toBeLessThan(0)
|
|
expect(compareVersions('0.7.6', '0.7.6-pre.1')).toBeGreaterThan(0)
|
|
})
|
|
|
|
it('orders a pre-release series numerically, not as text', () => {
|
|
expect(compareVersions('0.7.6-pre.9', '0.7.6-pre.10')).toBeLessThan(0)
|
|
})
|
|
|
|
it('orders by major, then minor, then patch', () => {
|
|
expect(compareVersions('0.8.0', '0.7.9')).toBeGreaterThan(0)
|
|
expect(compareVersions('1.0.0', '0.99.99')).toBeGreaterThan(0)
|
|
expect(compareVersions('0.7.6', '0.7.6')).toBe(0)
|
|
})
|
|
|
|
it('refuses to compare something it cannot parse', () => {
|
|
expect(() => compareVersions('banana', '0.7.6')).toThrow()
|
|
})
|
|
})
|
|
|
|
describe('parseVersion', () => {
|
|
it('returns null rather than a half-parsed object', () => {
|
|
expect(parseVersion('banana')).toBeNull()
|
|
})
|
|
|
|
it('distinguishes no pre-release from pre-release zero', () => {
|
|
expect(parseVersion('0.7.6').pre).toBeNull()
|
|
expect(parseVersion('0.7.6-pre.0').pre).toBe(0)
|
|
})
|
|
})
|