Skip to content

Commit

Permalink
Merge pull request #35 from nebula-plugins/better-error-reporting
Browse files Browse the repository at this point in the history
Add better error reporting
  • Loading branch information
rspieldenner committed Dec 28, 2015
2 parents 1362d72 + 86acf66 commit a4e9f2d
Show file tree
Hide file tree
Showing 9 changed files with 88 additions and 18 deletions.
5 changes: 5 additions & 0 deletions 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
=================

Expand Down
4 changes: 2 additions & 2 deletions README.md
Expand Up @@ -11,15 +11,15 @@ 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-

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'
Expand Down
@@ -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")
}

}
Expand Up @@ -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)
}

Expand Down Expand Up @@ -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'() {
Expand Down Expand Up @@ -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'() {
Expand Down
Expand Up @@ -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)
}

Expand Down
Expand Up @@ -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)
}
Expand Down
Expand Up @@ -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")
Expand Down
22 changes: 20 additions & 2 deletions src/main/groovy/nebula/plugin/release/ReleasePlugin.groovy
Expand Up @@ -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
Expand All @@ -35,6 +36,7 @@ import org.jfrog.gradle.plugin.artifactory.task.BuildInfoPublicationsTask
class ReleasePlugin implements Plugin<Project> {
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'
Expand All @@ -52,7 +54,7 @@ class ReleasePlugin implements Plugin<Project> {
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.")
Expand All @@ -74,7 +76,7 @@ class ReleasePlugin implements Plugin<Project> {
}

releaseExtension.with {
grgit = Grgit.open(dir: gitRoot)
grgit = git
tagStrategy {
generateMessage = { version ->
StringBuilder builder = new StringBuilder()
Expand Down Expand Up @@ -125,6 +127,7 @@ class ReleasePlugin implements Plugin<Project> {

def cliTasks = project.gradle.startParameter.taskNames
determineStage(cliTasks, releaseCheck)
checkStateForStage()

if (shouldSkipGitChecks()) {
project.tasks.release.deleteAllActions()
Expand Down Expand Up @@ -167,6 +170,21 @@ class ReleasePlugin implements Plugin<Project> {
}
}

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<Tag> 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())
Expand Down
Expand Up @@ -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])
Expand Down

0 comments on commit a4e9f2d

Please sign in to comment.