-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
major: Allow incrementing by higher scope than requested
Our prior parallel version logic allowed reckon to increment by the requested scope a second time in order to avoid a parallel version. However, if that version is also in the parallel branch, it would fail saying the version was already claimed. In the new logic, if we bump the target normal in order to avoid a parallel version and that version is still in the parallel versions list, we increment increment by a higher scope (i.e. by MAJOR if they requested MINOR or by MINOR if they requested PATCH). This may resolve many of the bugs we had with parallel version handling. The two unintuitive parts are that it may still not increment as far as someone wants in some cases. And in others someone could be surprised that we incremented by a higher scope than they asked for. To deal with the latter, we may want to consider making a distinction between "soft" and "hard" scopes (i.e. did they explicitly ask for the scope or did it get inferred). This was clearer in the past, when "inferred" really only meant no input from the scope calc. However, with the new commit message scope calc, that's really more of a "soft" scope request than an explicit one. It's trickier because to the Reckoner there's no difference between commit message scope calcs and explicit user-requested scope calcs. Will run this by the users and see what they think. Fixes #180 Related to #102
- Loading branch information
1 parent
9f53cbf
commit ee8c65f
Showing
5 changed files
with
235 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
198 changes: 198 additions & 0 deletions
198
...core/src/test/groovy/org/ajoberstar/reckon/core/ReckonerMaintenanceBranchIntegTest.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,198 @@ | ||
package org.ajoberstar.reckon.core | ||
|
||
import java.time.Clock; | ||
import java.time.Instant; | ||
import java.time.ZoneId; | ||
|
||
import java.nio.file.Files | ||
import java.security.SecureRandom | ||
import org.ajoberstar.grgit.Grgit | ||
import spock.lang.Shared | ||
import spock.lang.Specification | ||
import spock.lang.Ignore | ||
import spock.lang.Stepwise | ||
|
||
@Stepwise | ||
class ReckonerMaintenanceBranchIntegTest extends Specification { | ||
private static final Clock CLOCK = Clock.fixed(Instant.ofEpochSecond(1530724706), ZoneId.of('UTC')) | ||
private static final String TIMESTAMP = '20180704T171826Z' | ||
|
||
@Shared File repoDir | ||
@Shared Grgit grgit | ||
@Shared String initialBranch | ||
@Shared SecureRandom random = new SecureRandom() | ||
|
||
def 'reckon 1.0.0 version'() { | ||
expect: | ||
commit() | ||
def version = reckonStage('major', 'final') | ||
version == '1.0.0' | ||
tag(version) | ||
} | ||
|
||
def 'reckon 1.1.0 version'() { | ||
expect: | ||
commit() | ||
commit() | ||
def dev1 = reckonStage('minor', 'beta') | ||
dev1 == '1.1.0-beta.1' | ||
tag(dev1) | ||
|
||
commit() | ||
commit() | ||
def dev2 = reckonStage('minor', 'beta') | ||
dev2 == '1.1.0-beta.2' | ||
tag(dev2) | ||
|
||
commit() | ||
def dev3 = reckonStage('minor', 'beta') | ||
dev3 == '1.1.0-beta.3' | ||
tag(dev3) | ||
|
||
def minor1 = reckonStage('minor', 'final') | ||
minor1 == '1.1.0' | ||
tag(minor1) | ||
} | ||
|
||
def 'reckon 1.1.1 version'() { | ||
expect: | ||
branch('maintenance/1.1.x') | ||
checkout('maintenance/1.1.x') | ||
|
||
commit() | ||
def patch1 = reckonStage('patch', 'final') | ||
patch1 == '1.1.1' | ||
tag(patch1) | ||
} | ||
|
||
def 'reckon 1.2.0 version'() { | ||
expect: | ||
checkout(initialBranch) | ||
|
||
commit() | ||
commit() | ||
commit() | ||
def beta1 = reckonStage('minor', 'beta') | ||
beta1 == '1.2.0-beta.1' | ||
tag(beta1) | ||
|
||
commit() | ||
commit() | ||
def beta2 = reckonStage('minor', 'beta') | ||
beta2 == '1.2.0-beta.2' | ||
tag(beta2) | ||
|
||
def minor2 = reckonStage('minor', 'final') | ||
minor2 == '1.2.0' | ||
tag(minor2) | ||
} | ||
|
||
def 'reckon 1.2.x versions'() { | ||
expect: | ||
branch('maintenance/1.2.x') | ||
checkout('maintenance/1.2.x') | ||
|
||
commit() | ||
def patch1 = reckonStage('patch', 'final') | ||
patch1 == '1.2.1' | ||
tag(patch1) | ||
|
||
commit() | ||
def patch2 = reckonStage('patch', 'final') | ||
patch2 == '1.2.2' | ||
tag(patch2) | ||
|
||
commit() | ||
def patch3 = reckonStage('patch', 'final') | ||
patch3 == '1.2.3' | ||
tag(patch3) | ||
} | ||
|
||
def 'reckon 1.3.x versions'() { | ||
expect: | ||
checkout(initialBranch) | ||
|
||
commit() | ||
commit() | ||
commit() | ||
def beta1 = reckonStage('patch', 'beta') | ||
beta1 == '1.3.0-beta.1' | ||
tag(beta1) | ||
} | ||
|
||
def setupSpec() { | ||
repoDir = Files.createTempDirectory('repo').toFile() | ||
grgit = Grgit.init(dir: repoDir) | ||
initialBranch = grgit.branch.current().name | ||
} | ||
|
||
def cleanupSpec() { | ||
grgit.close() | ||
assert !repoDir.exists() || repoDir.deleteDir() | ||
} | ||
|
||
private String reckonStage(scope, stage) { | ||
return Reckoner.builder() | ||
.clock(CLOCK) | ||
.git(grgit.repository.jgit.repository) | ||
.scopeCalc { i -> Optional.ofNullable(scope) } | ||
.stages('beta', 'milestone', 'rc', 'final') | ||
.stageCalc { i, v -> Optional.ofNullable(stage) } | ||
.build() | ||
.reckon(); | ||
} | ||
|
||
private String reckonSnapshot(scope, stage) { | ||
return Reckoner.builder() | ||
.clock(CLOCK) | ||
.git(grgit.repository.jgit.repository) | ||
.scopeCalc { i -> Optional.ofNullable(scope) } | ||
.snapshots() | ||
.stageCalc { i, v -> Optional.ofNullable(stage) } | ||
.build() | ||
.reckon(); | ||
} | ||
|
||
private void commit() { | ||
byte[] bytes = new byte[128] | ||
random.nextBytes(bytes) | ||
int fileName = random.nextInt(); | ||
new File(grgit.repository.rootDir, "${fileName}.txt") << bytes | ||
grgit.add(patterns: ["${fileName}.txt"]) | ||
def commit = grgit.commit(message: 'do') | ||
println "Created commit: ${commit.abbreviatedId}" | ||
} | ||
|
||
private void branch(String name) { | ||
def currentHead = grgit.head() | ||
def currentBranch = grgit.branch.current | ||
def newBranch = grgit.branch.add(name: name) | ||
def atCommit = grgit.resolve.toCommit(newBranch.fullName) | ||
println "Added new branch ${name} at ${atCommit.abbreviatedId}" | ||
assert currentBranch == grgit.branch.current | ||
assert currentHead == atCommit | ||
} | ||
|
||
private void tag(String name, boolean annotate = true) { | ||
def currentHead = grgit.head() | ||
def newTag = grgit.tag.add(name: name, annotate: annotate) | ||
def atCommit = grgit.resolve.toCommit(newTag.fullName) | ||
println "Added new tag ${name} at ${atCommit.abbreviatedId}" | ||
assert currentHead == atCommit | ||
} | ||
|
||
private void checkout(String name) { | ||
def currentHead = grgit.head() | ||
grgit.checkout(branch: name) | ||
def atCommit = grgit.resolve.toCommit(name) | ||
println "Checkout out ${name}, which is at ${atCommit.abbreviatedId}" | ||
assert name == grgit.branch.current.name || grgit.branch.current.name == 'HEAD' | ||
} | ||
|
||
private void merge(String name) { | ||
def currentBranch = grgit.branch.current.name | ||
grgit.merge(head: name) | ||
println "Merged ${name} into ${currentBranch}" | ||
assert currentBranch == grgit.branch.current.name | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters