Skip to content

Commit

Permalink
project.version set when updateProjectVersionAfterRelease flag is ena…
Browse files Browse the repository at this point in the history
…bled | fixes #806
  • Loading branch information
bgalek committed Sep 2, 2024
1 parent ec7fe55 commit 8780574
Show file tree
Hide file tree
Showing 13 changed files with 214 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package pl.allegro.tech.build.axion.release

import org.gradle.testkit.runner.BuildResult
import org.gradle.testkit.runner.GradleRunner
import org.gradle.testkit.runner.internal.DefaultBuildResult

import java.nio.file.Files

Expand Down Expand Up @@ -41,14 +42,20 @@ class BaseIntegrationTest extends RepositoryBasedTest {

BuildResult runGradle(String... arguments) {
def args = []
args.addAll(arguments)
args.add("--stacktrace")
args.add("--configuration-cache")
args.add("--warning-mode=fail")
args.addAll(arguments)
runGradleWithArgs(args)
}

BuildResult runGradleWithArgs(List<String> args) {
try {
return gradle().withArguments(args).build()
}
catch (e) {
throw new RuntimeException("Gradle build failed", e)
}

finally {
def ccDir = new File(temporaryFolder, "build/reports/configuration-cache")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,4 +203,69 @@ class SimpleIntegrationTest extends BaseIntegrationTest {
cleanup:
environmentVariablesRule.clear("GITHUB_ACTIONS", "GITHUB_OUTPUT")
}
def "should not update project.version after release when updateProjectVersionAfterRelease option is not set"() {
given:
buildFile("""
task assemble {
inputs.property("version", project.version)
doLast {
println("Assembling project: " + version)
}
}
""")
def result = runGradleWithArgs(['currentVersion', 'release', 'assemble', '-Prelease.localOnly', '-Prelease.disableChecks'])
expect:
result.output.contains('Project version: 0.1.0-SNAPSHOT')
result.output.contains('Creating tag: v0.1.0')
result.output.contains('Assembling project: 0.1.0-SNAPSHOT')
result.task(":currentVersion").outcome == TaskOutcome.SUCCESS
result.task(":release").outcome == TaskOutcome.SUCCESS
result.task(":assemble").outcome == TaskOutcome.SUCCESS
}
def "should update project.version after release when updateProjectVersionAfterRelease option is set"() {
given:
buildFile("""
scmVersion {
updateProjectVersionAfterRelease = true
}

task assemble {
inputs.property("version", project.version)
doLast {
println("Assembling project: " + version)
}
}
""")
def result = runGradleWithArgs(['currentVersion', 'release', 'assemble', '-Prelease.localOnly', '-Prelease.disableChecks'])
expect:
result.output.contains('Project version: 0.1.0-SNAPSHOT')
result.output.contains('Creating tag: v0.1.0')
result.output.contains('Project version will be updated after release.')
result.output.contains('Assembling project: 0.1.0')
result.task(":currentVersion").outcome == TaskOutcome.SUCCESS
result.task(":release").outcome == TaskOutcome.SUCCESS
result.task(":assemble").outcome == TaskOutcome.SUCCESS
}
def "should throw error when using updateProjectVersionAfterRelease and configuration cache"() {
given:
buildFile("""
scmVersion {
updateProjectVersionAfterRelease = true
}
""")
when:
runGradle('release', '--stacktrace', '-Prelease.localOnly', '-Prelease.disableChecks')
then:
def e = thrown(RuntimeException)
e.getCause().getMessage().contains('Configuration cache is enabled and `scmVersion.updateProjectVersionAfterRelease` is set to `true`. This is not supported. Set `scmVersion.updateProjectVersionAfterRelease` to `false` and remember to run release task separately.')
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package pl.allegro.tech.build.axion.release

class ConfigurationCacheConfiguration {
boolean updateProjectVersionAfterRelease
boolean configurationCacheEnabled
public Closure<String> updateProjectVersion

ConfigurationCacheConfiguration(boolean updateProjectVersionAfterRelease, boolean configurationCacheEnabled, Closure<String> updateProjectVersion) {
this.updateProjectVersionAfterRelease = updateProjectVersionAfterRelease
this.configurationCacheEnabled = configurationCacheEnabled
this.updateProjectVersion = updateProjectVersion
}
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,31 @@
package pl.allegro.tech.build.axion.release

import org.gradle.api.tasks.Input
import org.gradle.api.tasks.TaskAction
import pl.allegro.tech.build.axion.release.domain.Releaser
import pl.allegro.tech.build.axion.release.domain.scm.ScmService
import pl.allegro.tech.build.axion.release.infrastructure.di.VersionResolutionContext

abstract class CreateReleaseTask extends BaseAxionTask {

@Input
boolean configurationCacheEnabled

@TaskAction
void release() {
VersionResolutionContext context = resolutionContext()
Releaser releaser = context.releaser()
ScmService scmService = context.scmService()
ReleaseBranchesConfiguration releaseBranchesConfiguration = new ReleaseBranchesConfiguration(
context.scmService().isReleaseOnlyOnReleaseBranches(),
scmService.isReleaseOnlyOnReleaseBranches(),
context.repository().currentPosition().getBranch(),
context.scmService().getReleaseBranchNames()
scmService.getReleaseBranchNames()
)
ConfigurationCacheConfiguration configurationCacheConfiguration = new ConfigurationCacheConfiguration(
scmService.isUpdateProjectVersionAfterRelease(),
configurationCacheEnabled,
(version) -> project.setVersion(version)
)
releaser.release(context.rules(), releaseBranchesConfiguration)
releaser.release(context.rules(), releaseBranchesConfiguration, configurationCacheConfiguration)
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package pl.allegro.tech.build.axion.release

import com.github.zafarkhaja.semver.Version
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.internal.StartParameterInternal
import pl.allegro.tech.build.axion.release.domain.SnapshotDependenciesChecker
import pl.allegro.tech.build.axion.release.domain.VersionConfig
import pl.allegro.tech.build.axion.release.util.FileLoader
Expand Down Expand Up @@ -41,12 +43,26 @@ abstract class ReleasePlugin implements Plugin<Project> {
group = 'Release'
description = 'Performs release - creates tag and pushes it to remote.'
dependsOn(VERIFY_RELEASE_TASK)
configurationCacheEnabled = Utils.isConfigurationCacheEnabled(project)
if (versionConfig.updateProjectVersionAfterRelease.get() && !project.tasks.matching { it.name == "assemble" }.isEmpty()) {
doLast {
logger.quiet("Project version will be updated after release.")
}
finalizedBy(project.tasks.named("assemble"))
}
}

project.tasks.register(CREATE_RELEASE_TASK, CreateReleaseTask) {
group = 'Release'
description = 'Performs first stage of release - creates tag.'
dependsOn(VERIFY_RELEASE_TASK)
configurationCacheEnabled = Utils.isConfigurationCacheEnabled(project)
if (versionConfig.updateProjectVersionAfterRelease.get() && !project.tasks.matching { it.name == "assemble" }.isEmpty()) {
doLast {
logger.quiet("Project version will be updated after release.")
}
finalizedBy(project.tasks.named("assemble"))
}
}

project.tasks.register(PUSH_RELEASE_TASK, PushReleaseTask) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package pl.allegro.tech.build.axion.release

import org.gradle.api.tasks.Input
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.ScmPushResultOutcome
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 @@ -12,17 +14,32 @@ import java.nio.file.StandardOpenOption

abstract class ReleaseTask extends BaseAxionTask {

@Input
boolean configurationCacheEnabled

@TaskAction
void release() {
VersionResolutionContext context = resolutionContext()
Releaser releaser = context.releaser()
ScmService service = context.scmService()

ReleaseBranchesConfiguration releaseBranchesConfiguration = new ReleaseBranchesConfiguration(
context.scmService().isReleaseOnlyOnReleaseBranches(),
service.isReleaseOnlyOnReleaseBranches(),
context.repository().currentPosition().getBranch(),
context.scmService().getReleaseBranchNames()
service.getReleaseBranchNames()
)

ScmPushResult result = releaser.releaseAndPush(context.rules(), releaseBranchesConfiguration)
ConfigurationCacheConfiguration configurationCacheConfiguration = new ConfigurationCacheConfiguration(
service.isUpdateProjectVersionAfterRelease(),
configurationCacheEnabled,
(version) -> project.setVersion(version)
)

ScmPushResult result = releaser.releaseAndPush(
context.rules(),
releaseBranchesConfiguration,
configurationCacheConfiguration
)

if (result.outcome === ScmPushResultOutcome.FAILED) {
def status = result.failureStatus
Expand Down
33 changes: 33 additions & 0 deletions src/main/groovy/pl/allegro/tech/build/axion/release/Utils.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package pl.allegro.tech.build.axion.release

import com.github.zafarkhaja.semver.Version
import org.gradle.api.Project
import org.gradle.api.internal.StartParameterInternal

class Utils {
static boolean isConfigurationCacheEnabled(Project project) {
try {
def gradleVersion = getGradleVersion(project.gradle.gradleVersion)
if (gradleVersion.greaterThan(Version.valueOf("7.6.0"))) {
return project.gradle.startParameter.isConfigurationCacheRequested()
} else if (gradleVersion.greaterThanOrEqualTo(Version.valueOf("7.0.0"))) {
return (project.gradle.startParameter as StartParameterInternal).isConfigurationCache()
}
} catch (e) {
project.logger.quiet("Cannot determine if configuration cache is enabled. Assuming it is not.", e)
return false
}
return false
}

static Version getGradleVersion(String gradleVersionString) {
def split = gradleVersionString.split("\\.", 3)
if (split.length === 2) {
return Version.forIntegers(split[0].toInteger(), split[1].toInteger())
} else if (split.length === 3) {
return Version.forIntegers(split[0].toInteger(), split[1].toInteger(), split[2].toInteger())
} else {
throw new IllegalStateException("Cannot parse Gradle version: $gradleVersionString")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ abstract class VersionConfig extends BaseExtension {
private static final String IGNORE_UNCOMMITTED_CHANGES_PROPERTY = 'release.ignoreUncommittedChanges'
private static final String FORCE_SNAPSHOT_PROPERTY = 'release.forceSnapshot'
private static final String USE_HIGHEST_VERSION_PROPERTY = 'release.useHighestVersion'
private static final String UPDATE_PROJECT_VERSION_AFTER_RELEASE_PROPERTY = 'release.updateProjectVersionAfterRelease'
private static final String LOCAL_ONLY = "release.localOnly"
private static final String FORCE_VERSION_PROPERTY = 'release.version'
private static final String DEPRECATED_FORCE_VERSION_PROPERTY = 'release.forceVersion'
Expand All @@ -43,6 +44,7 @@ abstract class VersionConfig extends BaseExtension {
getLocalOnly().convention(false)
getIgnoreUncommittedChanges().convention(true)
getUseHighestVersion().convention(false)
getUpdateProjectVersionAfterRelease().convention(false)
getUnshallowRepoOnCI().convention(false)
getIgnoreGlobalGitConfig().convention(false)
getReleaseBranchNames().convention(gradlePropertyAsSet(RELEASE_BRANCH_NAMES_PROPERTY).orElse(['master', 'main'] as Set))
Expand Down Expand Up @@ -127,6 +129,9 @@ abstract class VersionConfig extends BaseExtension {
@Internal
abstract Property<Boolean> getUseHighestVersion();

@Internal
abstract Property<Boolean> getUpdateProjectVersionAfterRelease();

Provider<Boolean> ignoreUncommittedChanges() {
gradlePropertyPresent(IGNORE_UNCOMMITTED_CHANGES_PROPERTY)
.orElse(ignoreUncommittedChanges)
Expand All @@ -140,6 +145,10 @@ abstract class VersionConfig extends BaseExtension {
gradlePropertyPresent(USE_HIGHEST_VERSION_PROPERTY).orElse(useHighestVersion)
}

Provider<Boolean> updateProjectVersionAfterRelease() {
gradlePropertyPresent(UPDATE_PROJECT_VERSION_AFTER_RELEASE_PROPERTY).orElse(updateProjectVersionAfterRelease)
}

Provider<Boolean> localOnly() {
gradlePropertyPresent(LOCAL_ONLY).orElse(localOnly)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ class ScmPropertiesFactory {
config.getUnshallowRepoOnCI().get(),
config.getReleaseBranchNames().get(),
config.getReleaseOnlyOnReleaseBranches().get(),
config.getIgnoreGlobalGitConfig().get()
config.getIgnoreGlobalGitConfig().get(),
config.getUpdateProjectVersionAfterRelease().get(),
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.github.zafarkhaja.semver.Version;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
import pl.allegro.tech.build.axion.release.ConfigurationCacheConfiguration;
import pl.allegro.tech.build.axion.release.ReleaseBranchesConfiguration;
import pl.allegro.tech.build.axion.release.domain.hooks.ReleaseHooksRunner;
import pl.allegro.tech.build.axion.release.domain.properties.Properties;
Expand All @@ -25,7 +26,11 @@ public Releaser(VersionService versionService, ScmService repository, ReleaseHoo
this.hooksRunner = hooksRunner;
}

public Optional<String> release(Properties properties, ReleaseBranchesConfiguration releaseBranchesConfiguration) {
public Optional<String> release(
Properties properties,
ReleaseBranchesConfiguration releaseBranchesConfiguration,
ConfigurationCacheConfiguration configurationCacheConfiguration
) {
if (releaseBranchesConfiguration.shouldRelease()) {
String message = String.format(
"Release step skipped since 'releaseOnlyOnReleaseBranches' option is set, and '%s' was not in 'releaseBranchNames' list [%s]",
Expand All @@ -42,6 +47,14 @@ public Optional<String> release(Properties properties, ReleaseBranchesConfigurat

Version version = versionContext.getVersion();

if (configurationCacheConfiguration.isUpdateProjectVersionAfterRelease()) {
if (configurationCacheConfiguration.isConfigurationCacheEnabled()) {
throw new IllegalStateException("Configuration cache is enabled and `scmVersion.updateProjectVersionAfterRelease` is set to `true`. " +
"This is not supported. Set `scmVersion.updateProjectVersionAfterRelease` to `false` and remember to run release task separately.");
}
configurationCacheConfiguration.updateProjectVersion.call(version.toString());
}

if (versionContext.isSnapshot()) {
String tagName = properties.getTag().getSerialize().apply(properties.getTag(), version.toString());

Expand All @@ -58,8 +71,12 @@ public Optional<String> release(Properties properties, ReleaseBranchesConfigurat
}
}

public ScmPushResult releaseAndPush(Properties rules, ReleaseBranchesConfiguration releaseBranchesConfiguration) {
Optional<String> releasedTagName = release(rules, releaseBranchesConfiguration);
public ScmPushResult releaseAndPush(
Properties rules,
ReleaseBranchesConfiguration releaseBranchesConfiguration,
ConfigurationCacheConfiguration configurationCacheEnabled
) {
Optional<String> releasedTagName = release(rules, releaseBranchesConfiguration, configurationCacheEnabled);

if (releasedTagName.isEmpty()) {
return new ScmPushResult(ScmPushResultOutcome.SKIPPED, Optional.empty(), Optional.empty());
Expand Down
Loading

0 comments on commit 8780574

Please sign in to comment.