From 86acf66ade8bad9f8b2adcaa0f7d258e34d2bcfd Mon Sep 17 00:00:00 2001 From: Nadav Cohen Date: Tue, 8 Dec 2015 23:07:05 -0800 Subject: [PATCH] Add better error reporting --- CHANGELOG.md | 5 ++ README.md | 4 +- ...eleasePluginGitStateIntegrationSpec.groovy | 53 +++++++++++++++++++ .../ReleasePluginIntegrationSpec.groovy | 6 ++- ...leasePluginIvyStatusIntegrationSpec.groovy | 1 + ...sePluginMultiprojectIntegrationSpec.groovy | 2 + ...easePluginNewProjectIntegrationSpec.groovy | 12 ----- .../plugin/release/ReleasePlugin.groovy | 22 +++++++- .../ReleasePluginOptionalDepsSpec.groovy | 1 + 9 files changed, 88 insertions(+), 18 deletions(-) create mode 100644 src/integTest/groovy/nebula/plugin/release/ReleasePluginGitStateIntegrationSpec.groovy diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f2cc8f..0b0b87d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +3.1.2 / 2015-12-9 +================= + +* Better error reporting for missing init tag and uncommitted changes + 3.1.1 / 2015-12-8 ================= diff --git a/README.md b/README.md index 4898c77..c2ae989 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ This plugin provides opinions and tasks for the release process provided by [gra # Applying the plugin plugins { - id 'nebula.nebula-release' version '3.1.1' + id 'nebula.nebula-release' version '3.1.2' } -or- @@ -19,7 +19,7 @@ This plugin provides opinions and tasks for the release process provided by [gra buildscript { repositories { jcenter() } dependencies { - classpath 'com.netflix.nebula:nebula-release-plugin:3.1.1' + classpath 'com.netflix.nebula:nebula-release-plugin:3.1.2' } } apply plugin: 'nebula.nebula-release' diff --git a/src/integTest/groovy/nebula/plugin/release/ReleasePluginGitStateIntegrationSpec.groovy b/src/integTest/groovy/nebula/plugin/release/ReleasePluginGitStateIntegrationSpec.groovy new file mode 100644 index 0000000..77c2598 --- /dev/null +++ b/src/integTest/groovy/nebula/plugin/release/ReleasePluginGitStateIntegrationSpec.groovy @@ -0,0 +1,53 @@ +package nebula.plugin.release + +import org.gradle.api.plugins.JavaPlugin + +import static org.codehaus.groovy.runtime.StackTraceUtils.extractRootCause + +class ReleasePluginGitStateIntegrationSpec extends GitVersioningIntegrationSpec { + + @Override + def setupBuild() { + buildFile << """ + ${applyPlugin(ReleasePlugin)} + ${applyPlugin(JavaPlugin)} + """ + } + + def 'test that final and candidate do not work with uncommitted changes'() { + setup: + buildFile << "// force an uncommitted change to file" + + when: + def finalFail = runTasksWithFailure("final") + + then: + extractRootCause(finalFail.failure).message.contains('require all changes to be committed into Git') + + when: + def candidateFail = runTasksWithFailure("candidate") + + then: + extractRootCause(candidateFail.failure).message.contains('require all changes to be committed into Git') + } + + def 'ensure plugin throws error regarding missing tag'() { + setup: + ['v1', '1.0.0', 'v0.0'].each { git.tag.add(name: it) } + + when: + def failure = runTasksWithFailure("devSnapshot") + + then: + extractRootCause(failure.failure).message.contains('requires a Git tag to indicate initial version') + } + + def 'ensure plugin does NOT throw an error when a good init tag is present'() { + setup: + ['my-feature-branch', 'super-duper', 'v1.0', 'v0.1.0'].each { git.tag.add(name: it) } + + expect: + runTasksSuccessfully("devSnapshot") + } + +} diff --git a/src/integTest/groovy/nebula/plugin/release/ReleasePluginIntegrationSpec.groovy b/src/integTest/groovy/nebula/plugin/release/ReleasePluginIntegrationSpec.groovy index 4f16c61..875be00 100644 --- a/src/integTest/groovy/nebula/plugin/release/ReleasePluginIntegrationSpec.groovy +++ b/src/integTest/groovy/nebula/plugin/release/ReleasePluginIntegrationSpec.groovy @@ -31,6 +31,8 @@ class ReleasePluginIntegrationSpec extends GitVersioningIntegrationSpec { } """.stripIndent() + git.tag.add(name: 'v0.0.1') + git.commit(message: 'Another commit') git.add(patterns: ['build.gradle', '.gitignore'] as Set) } @@ -128,7 +130,7 @@ class ReleasePluginIntegrationSpec extends GitVersioningIntegrationSpec { def version = inferredVersionForTask('final', '-Prelease.scope=patch') then: - version == normal('0.0.1') + version == normal('0.0.2') } def 'choose release version, update major'() { @@ -188,7 +190,7 @@ class ReleasePluginIntegrationSpec extends GitVersioningIntegrationSpec { String message = originGit.tag.list().find { it.name == 'v0.1.0' }.fullMessage message.contains 'Release of 0.1.0' message.find(/- [a-f0-9]{40}: Setup/) - message.find(/- [a-f0-9]{40}: Initial checkout/) + message.find(/- [a-f0-9]{40}: Another commit/) } def 'create new major release branch have branch name respected on version'() { diff --git a/src/integTest/groovy/nebula/plugin/release/ReleasePluginIvyStatusIntegrationSpec.groovy b/src/integTest/groovy/nebula/plugin/release/ReleasePluginIvyStatusIntegrationSpec.groovy index 4468d04..2ffcfa2 100644 --- a/src/integTest/groovy/nebula/plugin/release/ReleasePluginIvyStatusIntegrationSpec.groovy +++ b/src/integTest/groovy/nebula/plugin/release/ReleasePluginIvyStatusIntegrationSpec.groovy @@ -58,6 +58,7 @@ class ReleasePluginIvyStatusIntegrationSpec extends GitVersioningIntegrationSpec rootProject.name='statuscheck' '''.stripIndent() + git.tag.add(name: 'v0.0.1') git.add(patterns: ['build.gradle', '.gitignore', 'settings.gradle'] as Set) } diff --git a/src/integTest/groovy/nebula/plugin/release/ReleasePluginMultiprojectIntegrationSpec.groovy b/src/integTest/groovy/nebula/plugin/release/ReleasePluginMultiprojectIntegrationSpec.groovy index 302cba4..8251dbd 100644 --- a/src/integTest/groovy/nebula/plugin/release/ReleasePluginMultiprojectIntegrationSpec.groovy +++ b/src/integTest/groovy/nebula/plugin/release/ReleasePluginMultiprojectIntegrationSpec.groovy @@ -41,6 +41,8 @@ class ReleasePluginMultiprojectIntegrationSpec extends GitVersioningIntegrationS } '''.stripIndent()) + git.tag.add(name: 'v0.0.1') + git.commit(message: 'Another commit') git.add(patterns: ['build.gradle', '.gitignore', 'settings.gradle', 'test-release-common/build.gradle', 'test-release-client/build.gradle'] as Set) } diff --git a/src/integTest/groovy/nebula/plugin/release/ReleasePluginNewProjectIntegrationSpec.groovy b/src/integTest/groovy/nebula/plugin/release/ReleasePluginNewProjectIntegrationSpec.groovy index 9d66285..61c53be 100644 --- a/src/integTest/groovy/nebula/plugin/release/ReleasePluginNewProjectIntegrationSpec.groovy +++ b/src/integTest/groovy/nebula/plugin/release/ReleasePluginNewProjectIntegrationSpec.groovy @@ -7,18 +7,6 @@ import org.gradle.api.plugins.JavaPlugin * initial commit) */ class ReleasePluginNewProjectIntegrationSpec extends IntegrationSpec { - def 'release tasks unavailable when no git repository has been initialized'() { - when: - buildFile << """ - ${applyPlugin(ReleasePlugin)} - ${applyPlugin(JavaPlugin)} - """ - - then: - runTasksSuccessfully('build') - runTasksWithFailure('snapshot') - } - def 'release tasks unavailable when git repository has no commits'() { setup: // equivalent of having completed `git init` but no initial commit def origin = new File(projectDir.parent, "${projectDir.name}.git") diff --git a/src/main/groovy/nebula/plugin/release/ReleasePlugin.groovy b/src/main/groovy/nebula/plugin/release/ReleasePlugin.groovy index 25efa67..660f2b8 100644 --- a/src/main/groovy/nebula/plugin/release/ReleasePlugin.groovy +++ b/src/main/groovy/nebula/plugin/release/ReleasePlugin.groovy @@ -19,6 +19,7 @@ import nebula.core.ProjectType import org.ajoberstar.gradle.git.release.base.BaseReleasePlugin import org.ajoberstar.gradle.git.release.base.ReleasePluginExtension import org.ajoberstar.grgit.Grgit +import org.ajoberstar.grgit.Tag import org.eclipse.jgit.errors.RepositoryNotFoundException import org.gradle.api.GradleException import org.gradle.api.Plugin @@ -35,6 +36,7 @@ import org.jfrog.gradle.plugin.artifactory.task.BuildInfoPublicationsTask class ReleasePlugin implements Plugin { public static final String DISABLE_GIT_CHECKS = 'release.disableGitChecks' Project project + Grgit git static Logger logger = Logging.getLogger(ReleasePlugin) static final String SNAPSHOT_TASK_NAME = 'snapshot' @@ -52,7 +54,7 @@ class ReleasePlugin implements Plugin { def gitRoot = project.hasProperty('git.root') ? project.property('git.root') : project.rootProject.projectDir try { - Grgit.open(dir: gitRoot) + git = Grgit.open(dir: gitRoot) } catch(RepositoryNotFoundException e) { logger.warn("Git repository not found at $gitRoot -- nebula-release tasks will not be available. Use the git.root Gradle property to specify a different directory.") @@ -74,7 +76,7 @@ class ReleasePlugin implements Plugin { } releaseExtension.with { - grgit = Grgit.open(dir: gitRoot) + grgit = git tagStrategy { generateMessage = { version -> StringBuilder builder = new StringBuilder() @@ -125,6 +127,7 @@ class ReleasePlugin implements Plugin { def cliTasks = project.gradle.startParameter.taskNames determineStage(cliTasks, releaseCheck) + checkStateForStage() if (shouldSkipGitChecks()) { project.tasks.release.deleteAllActions() @@ -167,6 +170,21 @@ class ReleasePlugin implements Plugin { } } + private void checkStateForStage() { + if (!project.tasks.releaseCheck.isSnapshotRelease) { + def status = git.status() + def uncommittedChangesFound = [status.staged, status.unstaged].any { it.getAllChanges().size() > 0 } + if (uncommittedChangesFound) { + throw new GradleException('Final and candidate builds require all changes to be committed into Git.') + } + } + + List tags = git.tag.list() + if (!tags.any { it.fullName.split('/')[-1] ==~ /v[\d]+.[\d+].[\d]+/ }) { + throw new GradleException('The nebula-release-plugin requires a Git tag to indicate initial version. Use "git tag v1.0.0" to start from version 1.0.0.') + } + } + private boolean shouldSkipGitChecks() { (project.hasProperty(DISABLE_GIT_CHECKS) && project.property(DISABLE_GIT_CHECKS) as Boolean) || (project.hasProperty('release.travisci') && project.property('release.travisci').toBoolean()) diff --git a/src/test/groovy/nebula/plugin/release/ReleasePluginOptionalDepsSpec.groovy b/src/test/groovy/nebula/plugin/release/ReleasePluginOptionalDepsSpec.groovy index f4ea5e6..8468743 100644 --- a/src/test/groovy/nebula/plugin/release/ReleasePluginOptionalDepsSpec.groovy +++ b/src/test/groovy/nebula/plugin/release/ReleasePluginOptionalDepsSpec.groovy @@ -27,6 +27,7 @@ class ReleasePluginOptionalDepsSpec extends ProjectSpec { def setup() { git = Grgit.init(dir: projectDir) git.commit(message: 'initial commit') + git.tag.add(name: 'v0.0.1') } @ConfineMetaClassChanges(value = [ReleasePlugin])