Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

releaseOnlyOnReleaseBranches & releaseBranchNames options #797

Merged
merged 10 commits into from
Aug 27, 2024
10 changes: 10 additions & 0 deletions docs/configuration/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ All `axion-release-plugin` configuration options:
uncommittedChanges.set(false) // permanently disable uncommitted changes check
aheadOfRemote.set(false) // permanently disable ahead of remote check
}

// doc: Version / releaseOnlyOnReleaseBranches
releaseOnlyOnReleaseBranches = false
releaseBranchNames = ['master', 'main']
}

All `axion-release-plugin` configuration flags:
Expand Down Expand Up @@ -108,3 +112,9 @@ All `axion-release-plugin` configuration flags:
- release.fetchTags
- default: false
- fetch tags from the remote repository
- release.releaseOnlyOnReleaseBranches
- default: false
- only perform a release on branches that match the `releaseBranchNames`
- release.releaseBranchNames
- default: `['master', 'main']`
- a list of branch names that are considered release branches
32 changes: 26 additions & 6 deletions docs/configuration/version.md
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,30 @@ This rule uses additional parameter `initialPreReleaseIfNotOnPrerelease`
versionIncrementer('incrementPrerelease', [initialPreReleaseIfNotOnPrerelease: 'rc1'])
}

### releaseOnlyOnReleaseBranches

You can set this flag to true to prevent releasing on branches that are
not marked as release branches. By default, this flag is set to false.

scmVersion {
releaseOnlyOnReleaseBranches = true
}

This flag can also be set via command line:

./gradlew release -Prelease.releaseOnlyOnReleaseBranches

And works well in combination with `releaseBranchNames` option

scmVersion {
releaseOnlyOnReleaseBranches = true
releaseBranchNames = ['main', 'master']
}

or as command line

./gradlew release -Prelease.releaseOnlyOnReleaseBranches -Prelease.releaseBranchNames=main,release

## Decorating

Decorating phase happens only when version is read (and deserialized).
Expand Down Expand Up @@ -367,9 +391,7 @@ Custom version creators can be implemented by creating closure:
{version, position -> ...}

- version - string version resolved by previous steps
-
position - [ScmPosition](https:/allegro/axion-release-plugin/blob/main/src/main/java/pl/allegro/tech/build/axion/release/domain/scm/ScmPosition.java)
object
- position - [ScmPosition](https:/allegro/axion-release-plugin/blob/main/src/main/java/pl/allegro/tech/build/axion/release/domain/scm/ScmPosition.java) object

### Snapshot

Expand All @@ -386,9 +408,7 @@ Snapshot creator can be implemented by creating closure:
{version, position -> ...}

- version - string version resolved by previous steps
-
position - [ScmPosition](https:/allegro/axion-release-plugin/blob/main/src/main/java/pl/allegro/tech/build/axion/release/domain/scm/ScmPosition.java)
object
- position - [ScmPosition](https:/allegro/axion-release-plugin/blob/main/src/main/java/pl/allegro/tech/build/axion/release/domain/scm/ScmPosition.java) object

## Sanitization

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,4 +140,49 @@ class SimpleIntegrationTest extends BaseIntegrationTest {
result.output.contains('Project version: 0.0.1-SNAPSHOT')
result.task(":currentVersion").outcome == TaskOutcome.SUCCESS
}

def "should skip release when releaseOnlyOnReleaseBranches is true and current branch is not on releaseBranchNames list"() {
given:
buildFile("""
scmVersion {
releaseOnlyOnReleaseBranches = true
releaseBranchNames = ['develop', 'release']
}
""")

when:
def releaseResult = runGradle('release', '-Prelease.version=1.0.0', '-Prelease.localOnly', '-Prelease.disableChecks')

then:
releaseResult.task(':release').outcome == TaskOutcome.SUCCESS
releaseResult.output.contains('Release step skipped since \'releaseOnlyOnDefaultBranches\' option is set, and \'master\' was not in \'releaseBranchNames\' list [develop, release]')
bgalek marked this conversation as resolved.
Show resolved Hide resolved
}

def "should skip release when releaseOnlyOnReleaseBranches is set by gradle task property and current branch is not on releaseBranchNames list"() {
given:
buildFile("")

when:
def releaseResult = runGradle('release', '-Prelease.releaseOnlyOnReleaseBranches', '-Prelease.releaseBranchNames=develop,release', '-Prelease.version=1.0.0', '-Prelease.localOnly', '-Prelease.disableChecks')

then:
releaseResult.task(':release').outcome == TaskOutcome.SUCCESS
releaseResult.output.contains('Release step skipped since \'releaseOnlyOnDefaultBranches\' option is set, and \'master\' was not in \'releaseBranchNames\' list [develop, release]')
}

def "should not skip release when releaseOnlyOnReleaseBranches is true when on master branch (default releaseBranches list)"() {
given:
buildFile("""
scmVersion {
releaseOnlyOnReleaseBranches = true
}
""")

when:
def releaseResult = runGradle('release', '-Prelease.version=1.0.0', '-Prelease.localOnly', '-Prelease.disableChecks')

then:
releaseResult.task(':release').outcome == TaskOutcome.SUCCESS
releaseResult.output.contains('Creating tag: ' + fullPrefix() + '1.0.0')
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package pl.allegro.tech.build.axion.release
import org.gradle.api.tasks.TaskAction
import pl.allegro.tech.build.axion.release.domain.Releaser
import pl.allegro.tech.build.axion.release.domain.scm.ScmPushResult
import pl.allegro.tech.build.axion.release.domain.scm.ScmService
import pl.allegro.tech.build.axion.release.infrastructure.di.VersionResolutionContext

import java.nio.file.Files
Expand All @@ -15,10 +16,21 @@ abstract class ReleaseTask extends BaseAxionTask {
void release() {
VersionResolutionContext context = resolutionContext()
Releaser releaser = context.releaser()
ScmService scmService = context.scmService()

if (scmService.isReleaseOnlyOnDefaultBranches()) {
def releaseBranchNames = scmService.getReleaseBranchNames()
def currentBranch = context.repository().currentPosition().getBranch()
if (!releaseBranchNames.contains(currentBranch)) {
logger.quiet("Release step skipped since 'releaseOnlyOnDefaultBranches' option is set, and '${currentBranch}' was not in 'releaseBranchNames' list [${releaseBranchNames.join(', ')}]")
return
}
}
bgalek marked this conversation as resolved.
Show resolved Hide resolved

ScmPushResult result = releaser.releaseAndPush(context.rules())

if (!result.success) {
def status = result.failureStatus.orElse("Unknown status of push")
def status = result.failureStatus
def message = result.remoteMessage.orElse("Unknown error during push")
logger.error("remote status: ${status}")
logger.error("remote message: ${message}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,15 @@ abstract class BaseExtension {
GradleVersion.current()
}

protected Provider<Set<String>> gradleSetProperty(String name) {
bgalek marked this conversation as resolved.
Show resolved Hide resolved
return gradleProperty(name).map({ it.tokenize(',') as Set })
}

protected Provider<Boolean> gradlePropertyBoolean(String name) {
bgalek marked this conversation as resolved.
Show resolved Hide resolved
return gradleProperty(name).map(Boolean::valueOf)
}

protected Provider<Boolean> gradlePropertyPresent(String name) {
return gradleProperty(name).map({true})
return gradleProperty(name).map({ true })
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import org.gradle.api.file.Directory
import org.gradle.api.provider.MapProperty
import org.gradle.api.provider.Property
import org.gradle.api.provider.Provider
import org.gradle.api.provider.SetProperty
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.Nested
Expand Down Expand Up @@ -33,6 +34,8 @@ abstract class VersionConfig extends BaseExtension {
private static final String DEPRECATED_FORCE_VERSION_PROPERTY = 'release.forceVersion'
private static final String VERSION_INCREMENTER_PROPERTY = 'release.versionIncrementer'
private static final String VERSION_CREATOR_PROPERTY = 'release.versionCreator'
private static final String RELEASE_ONLY_ON_RELEASE_BRANCHES_PROPERTY = 'release.releaseOnlyOnReleaseBranches'
private static final String RELEASE_BRANCH_NAMES_PROPERTY = 'release.releaseBranchNames'

@Inject
VersionConfig(Directory repositoryDirectory) {
Expand All @@ -41,6 +44,8 @@ abstract class VersionConfig extends BaseExtension {
getIgnoreUncommittedChanges().convention(true)
getUseHighestVersion().convention(false)
getUnshallowRepoOnCI().convention(false)
getReleaseBranchNames().convention(gradleSetProperty(RELEASE_BRANCH_NAMES_PROPERTY).orElse(['master', 'main'] as Set))
getReleaseOnlyOnReleaseBranches().convention(gradlePropertyPresent(RELEASE_ONLY_ON_RELEASE_BRANCHES_PROPERTY).orElse(false))
getReleaseBranchPattern().convention(Pattern.compile('^' + defaultPrefix() + '(/.*)?$'))
getSanitizeVersion().convention(true)
getCreateReleaseCommit().convention(false)
Expand Down Expand Up @@ -79,7 +84,10 @@ abstract class VersionConfig extends BaseExtension {
abstract Property<Boolean> getIgnoreUncommittedChanges()

@Internal
abstract Property<Boolean> getUseHighestVersion();
abstract SetProperty<String> getReleaseBranchNames()

@Internal
abstract Property<Boolean> getReleaseOnlyOnReleaseBranches()

@Internal
@Incubating
Expand Down Expand Up @@ -112,6 +120,9 @@ abstract class VersionConfig extends BaseExtension {
@Internal
abstract Property<PredefinedReleaseCommitMessageCreator.CommitMessageCreator> getReleaseCommitMessage()

@Internal
abstract Property<Boolean> getUseHighestVersion();

Provider<Boolean> ignoreUncommittedChanges() {
gradlePropertyPresent(IGNORE_UNCOMMITTED_CHANGES_PROPERTY)
.orElse(ignoreUncommittedChanges)
Expand All @@ -132,8 +143,8 @@ abstract class VersionConfig extends BaseExtension {
Provider<String> forcedVersion() {
gradleProperty(FORCE_VERSION_PROPERTY)
.orElse(gradleProperty(DEPRECATED_FORCE_VERSION_PROPERTY))
.map({it.trim()})
.map({ it.isBlank() ? null : it})
.map({ it.trim() })
.map({ it.isBlank() ? null : it })
}

Provider<String> versionIncrementerType() {
Expand Down Expand Up @@ -216,12 +227,12 @@ abstract class VersionConfig extends BaseExtension {

Provider<VersionService.DecoratedVersion> versionProvider() {
def cachedVersionSupplier = this.cachedVersionSupplier
providers.provider( { cachedVersionSupplier.resolve(this,layout.projectDirectory)})
providers.provider({ cachedVersionSupplier.resolve(this, layout.projectDirectory) })
}

Provider<VersionService.DecoratedVersion> uncachedVersionProvider() {
def versionSupplier = this.versionSupplier
providers.provider( { versionSupplier.resolve(this, layout.projectDirectory)})
providers.provider({ versionSupplier.resolve(this, layout.projectDirectory) })
}

@Nested
Expand All @@ -231,21 +242,21 @@ abstract class VersionConfig extends BaseExtension {

@Input
String getVersion() {
return versionProvider().map({ it.decoratedVersion}).get()
return versionProvider().map({ it.decoratedVersion }).get()
}

@Input
String getPreviousVersion() {
return versionProvider().map({ it.previousVersion}).get()
return versionProvider().map({ it.previousVersion }).get()
}

@Input
String getUndecoratedVersion() {
return versionProvider().map({ it.undecoratedVersion}).get()
return versionProvider().map({ it.undecoratedVersion }).get()
}

@Nested
ScmPosition getScmPosition() {
return versionProvider().map({it.position}).get()
return versionProvider().map({ it.position }).get()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ class ScmPropertiesFactory {
config.repository.overriddenBranch().getOrNull(),
config.repository.overriddenIsClean().getOrNull(),
ScmIdentityFactory.create(config.repository, config.repository.disableSshAgent().get()),
config.getUnshallowRepoOnCI().get()
config.getUnshallowRepoOnCI().get(),
config.getReleaseBranchNames().get(),
config.getReleaseOnlyOnReleaseBranches().get()
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.io.File;
import java.util.Optional;
import java.util.Set;

public class ScmProperties {

Expand All @@ -16,6 +17,8 @@ public class ScmProperties {
private final Boolean overriddenIsClean;
private final ScmIdentity identity;
private final Boolean unshallowRepoOnCI;
private final Set<String> releaseBranchNames;
private final boolean releaseOnlyOnReleaseBranches;

public ScmProperties(
String type,
Expand All @@ -28,7 +31,9 @@ public ScmProperties(
String overriddenBranchName,
Boolean overriddenIsClean,
ScmIdentity identity,
Boolean unshallowRepoOnCI
Boolean unshallowRepoOnCI,
Set<String> releaseBranchNames,
boolean releaseOnlyOnReleaseBranches
) {
this.type = type;
this.directory = directory;
Expand All @@ -41,6 +46,8 @@ public ScmProperties(
this.overriddenIsClean = overriddenIsClean;
this.identity = identity;
this.unshallowRepoOnCI = unshallowRepoOnCI;
this.releaseBranchNames = releaseBranchNames;
this.releaseOnlyOnReleaseBranches = releaseOnlyOnReleaseBranches;
}

public ScmPushOptions pushOptions() {
Expand Down Expand Up @@ -90,4 +97,12 @@ public final ScmIdentity getIdentity() {
public Boolean isUnshallowRepoOnCI() {
return unshallowRepoOnCI;
}

public Set<String> getReleaseBranchNames() {
return releaseBranchNames;
}

public boolean isReleaseOnlyOnReleaseBranches() {
return releaseOnlyOnReleaseBranches;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import java.util.List;
import java.util.Optional;
import java.util.Set;

public class ScmService {
private static final Logger logger = Logging.getLogger(ScmService.class);
Expand Down Expand Up @@ -69,4 +70,12 @@ public List<String> lastLogMessages(int messageCount) {
public boolean isLegacyDefTagnameRepo() {
return repository.isLegacyDefTagnameRepo();
}

public Set<String> getReleaseBranchNames() {
return scmProperties.getReleaseBranchNames();
}

public boolean isReleaseOnlyOnDefaultBranches(){
return scmProperties.isReleaseOnlyOnReleaseBranches();
}
}
Loading
Loading