Skip to content

Commit ce427f4

Browse files
committed
feat: add pre-release prefix option for versioning
1 parent 65eaaff commit ce427f4

File tree

7 files changed

+74
-11
lines changed

7 files changed

+74
-11
lines changed

.github/workflows/pr_workflow.yaml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ on:
66
type: boolean
77
description: "Whether to run the version command with the pre-release flag"
88
default: false
9+
pre_release_prefix:
10+
type: string
11+
description: "Prefix for pre-release versions (e.g. 'dev' => 3.0.0-dev.1, empty => 3.0.0-1)"
12+
default: ""
913
use_local_version:
1014
type: boolean
1115
description: "Whether to use the local version of mtrust_api_guard"
@@ -36,7 +40,7 @@ jobs:
3640
run: dart pub global activate --source path .
3741
- name: Compare API changes
3842
id: version
39-
run: mtrust_api_guard version --badge --no-commit --tag --generate-changelog --json version_output.json ${{ inputs.pre_release && '--pre-release' || '' }}
43+
run: mtrust_api_guard version --badge --no-commit --tag --generate-changelog --json version_output.json ${{ inputs.pre_release && '--pre-release' || '' }} ${{ inputs.pre_release_prefix != '' && format('--pre-release-prefix "{0}"', inputs.pre_release_prefix) || '' }}
4044

4145
- name: Generate version summary and comment on PR
4246
if: github.event_name == 'pull_request'

lib/version/calculate_next_version.dart

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Future<String> calculateNextVersion(
1111
bool isPreRelease,
1212
Directory gitRoot,
1313
String tagPrefix,
14+
String preReleasePrefix,
1415
) async {
1516
logger.info('Current version: $version');
1617

@@ -37,12 +38,22 @@ Future<String> calculateNextVersion(
3738
logger.info('New version: $newVersion');
3839

3940
if (isPreRelease) {
41+
final normalizedPrefix = preReleasePrefix.trim();
42+
final separator = normalizedPrefix.isEmpty || normalizedPrefix.endsWith('.') ? '' : '.';
43+
String buildPreReleaseSuffix(int number) {
44+
if (normalizedPrefix.isEmpty) {
45+
return '$number';
46+
}
47+
return '$normalizedPrefix$separator$number';
48+
}
49+
4050
var preReleaseNum = 1;
41-
while (await GitUtils.gitTagExists('$tagPrefix$newVersion-dev.$preReleaseNum', gitRoot.path)) {
51+
while (await GitUtils.gitTagExists('$tagPrefix$newVersion-${buildPreReleaseSuffix(preReleaseNum)}', gitRoot.path)) {
4252
preReleaseNum++;
4353
}
44-
logger.info('Pre-release version: $newVersion-dev.$preReleaseNum');
45-
return '$newVersion-dev.$preReleaseNum';
54+
final preReleaseVersion = '$newVersion-${buildPreReleaseSuffix(preReleaseNum)}';
55+
logger.info('Pre-release version: $preReleaseVersion');
56+
return preReleaseVersion;
4657
} else if (await GitUtils.gitTagExists('$tagPrefix$newVersion', gitRoot.path)) {
4758
logger.err('Version tag $tagPrefix$newVersion already exists');
4859
throw Exception('Version tag $tagPrefix$newVersion already exists');

lib/version/version.dart

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ Future<VersionResult> version({
4343
required bool tag,
4444
String? newRef,
4545
required bool isPreRelease,
46+
required String preReleasePrefix,
4647
required bool commit,
4748
required bool badge,
4849
required bool generateChangelog,
@@ -106,8 +107,14 @@ Future<VersionResult> version({
106107

107108
// For workspace packages, extract the 'v' prefix from tagPrefix (which is like 'package/v')
108109
final versionTagPrefix = packageName != null ? 'v' : tagPrefix;
109-
final nextVersion =
110-
await calculateNextVersion(baseVersion, highestMagnitudeChange, isPreRelease, gitRoot, versionTagPrefix);
110+
final nextVersion = await calculateNextVersion(
111+
baseVersion,
112+
highestMagnitudeChange,
113+
isPreRelease,
114+
gitRoot,
115+
versionTagPrefix,
116+
preReleasePrefix,
117+
);
111118

112119
logger.info('Next version: $nextVersion');
113120

lib/version/version_command.dart

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,15 @@ class VersionCommand extends Command
6060
..addFlag(
6161
'pre-release',
6262
abbr: 'p',
63-
help: 'Add pre-release suffix. 3.0.0-dev.1 where dev.1 is the pre-release suffix',
63+
help: 'Add pre-release suffix. Defaults to 3.0.0-1 unless --pre-release-prefix is provided',
6464
defaultsTo: false,
6565
)
66+
..addOption(
67+
'pre-release-prefix',
68+
help: 'Prefix for pre-release versions. Example: --pre-release-prefix dev -> 3.0.0-dev.1',
69+
defaultsTo: '',
70+
valueHelp: 'prefix',
71+
)
6672
..addOption(
6773
'tag-prefix',
6874
help: 'Prefix for version tags useful for mono repos where multiple packages are versioned together',
@@ -88,6 +94,10 @@ class VersionCommand extends Command
8894
return argResults?['pre-release'] as bool;
8995
}
9096

97+
String get preReleasePrefix {
98+
return argResults?['pre-release-prefix'] as String? ?? '';
99+
}
100+
91101
bool get badge {
92102
return argResults?['badge'] as bool;
93103
}
@@ -122,6 +132,7 @@ class VersionCommand extends Command
122132
generateChangelog: generateChangelog,
123133
cache: cache,
124134
isPreRelease: preRelease,
135+
preReleasePrefix: preReleasePrefix,
125136
tagPrefix: tagPrefix,
126137
dartFile: dartFile,
127138
);

lib/version/version_workspace_command.dart

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ class VersionWorkspaceCommand extends Command
1818
factory VersionWorkspaceCommand() => _instance;
1919

2020
@override
21-
String get description => "Calculate and output the next version for all packages in a workspace based on API changes";
21+
String get description =>
22+
"Calculate and output the next version for all packages in a workspace based on API changes";
2223

2324
@override
2425
String get name => "version-workspace";
@@ -64,9 +65,15 @@ class VersionWorkspaceCommand extends Command
6465
..addFlag(
6566
'pre-release',
6667
abbr: 'p',
67-
help: 'Add pre-release suffix. 3.0.0-dev.1 where dev.1 is the pre-release suffix',
68+
help: 'Add pre-release suffix. Defaults to 3.0.0-1 unless --pre-release-prefix is provided',
6869
defaultsTo: false,
6970
)
71+
..addOption(
72+
'pre-release-prefix',
73+
help: 'Prefix for pre-release versions. Example: --pre-release-prefix dev -> 3.0.0-dev.1',
74+
defaultsTo: '',
75+
valueHelp: 'prefix',
76+
)
7077
..addOption(
7178
'dart-file',
7279
help: 'Output the version as a Dart constant to the specified file',
@@ -86,6 +93,10 @@ class VersionWorkspaceCommand extends Command
8693
return argResults?['pre-release'] as bool;
8794
}
8895

96+
String get preReleasePrefix {
97+
return argResults?['pre-release-prefix'] as String? ?? '';
98+
}
99+
89100
bool get badge {
90101
return argResults?['badge'] as bool;
91102
}
@@ -128,6 +139,7 @@ class VersionWorkspaceCommand extends Command
128139
generateChangelog: generateChangelog,
129140
cache: cache,
130141
isPreRelease: preRelease,
142+
preReleasePrefix: preReleasePrefix,
131143
dartFile: dartFile,
132144
);
133145

lib/version/workspace_version.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ Future<WorkspaceVersionResult> versionWorkspace({
3232
required bool tag,
3333
String? newRef,
3434
required bool isPreRelease,
35+
required String preReleasePrefix,
3536
required bool commit,
3637
required bool badge,
3738
required bool generateChangelog,
@@ -83,6 +84,7 @@ Future<WorkspaceVersionResult> versionWorkspace({
8384
tag: tag,
8485
newRef: effectiveNewRef,
8586
isPreRelease: isPreRelease,
87+
preReleasePrefix: preReleasePrefix,
8688
commit: commit,
8789
badge: badge,
8890
generateChangelog: generateChangelog,

test/commands/version_command_test.dart

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -326,21 +326,37 @@ void main() {
326326
await testSetup.commitChanges('API change to v${TestConstants.minorVersion}');
327327

328328
await testSetup.runApiGuard('version', ['--pre-release']);
329-
expect(testSetup.getCurrentVersion(), '0.1.0-dev.1');
329+
expect(testSetup.getCurrentVersion(), '0.1.0-1');
330330

331331
// 3. Apply major changes and create another pre-release
332332
await copyDir(testSetup.fixtures.appV200Dir, testSetup.tempDir);
333333
await testSetup.commitChanges('feat: implement compatibility with v${TestConstants.majorVersion}');
334334

335335
await testSetup.runApiGuard('version', ['--pre-release']);
336-
expect(testSetup.getCurrentVersion(), '1.0.0-dev.1');
336+
expect(testSetup.getCurrentVersion(), '1.0.0-1');
337337

338338
// 4. Finalize the release (removes pre-release suffix)
339339
await testSetup.runApiGuard('version', []);
340340

341341
expect(testSetup.getCurrentVersion(), '1.0.0');
342342
});
343343

344+
test('pre-release prefix option applies custom suffix', () async {
345+
// 1. Set up initial tagged version
346+
await testSetup.setupGitRepo();
347+
await testSetup.setupFlutterPackage();
348+
await copyDir(testSetup.fixtures.appV100Dir, testSetup.tempDir);
349+
await testSetup.commitChanges('chore!: Initial release v${TestConstants.initialVersion}');
350+
await runProcess('git', ['tag', 'v${TestConstants.initialVersion}'], workingDir: testSetup.tempDir.path);
351+
352+
// 2. Apply minor changes and create pre-release with custom prefix
353+
await copyDir(testSetup.fixtures.appV110Dir, testSetup.tempDir);
354+
await testSetup.commitChanges('API change to v${TestConstants.minorVersion}');
355+
356+
await testSetup.runApiGuard('version', ['--pre-release', '--pre-release-prefix', 'dev']);
357+
expect(testSetup.getCurrentVersion(), '0.1.0-dev.1');
358+
});
359+
344360
test('custom tag prefix works correctly', () async {
345361
// 1. Set up initial tagged version with custom prefix
346362
await testSetup.setupGitRepo();

0 commit comments

Comments
 (0)