diff --git a/src/integTest/groovy/org/shipkit/changelog/ChangelogPluginIntegTest.groovy b/src/integTest/groovy/org/shipkit/changelog/ChangelogPluginIntegTest.groovy index 8250907..5a403f5 100644 --- a/src/integTest/groovy/org/shipkit/changelog/ChangelogPluginIntegTest.groovy +++ b/src/integTest/groovy/org/shipkit/changelog/ChangelogPluginIntegTest.groovy @@ -1,32 +1,23 @@ package org.shipkit.changelog - import org.junit.Rule import org.junit.rules.TemporaryFolder import org.shipkit.BaseSpecification /** * Only smoke test, forever! Don't add more tests here, instead cover the complexity in lower level unit tests. - * - * Once we have a couple of releases (tags) we should unignore this test - * and let it run against "this" repo. */ class ChangelogPluginIntegTest extends BaseSpecification { @Rule TemporaryFolder tmp = new TemporaryFolder() - def setup() { - file("settings.gradle") - } - - def "basic task configuration"() { + def "basic task configuration with no previous version"() { file("build.gradle") << """ plugins { id 'org.shipkit.shipkit-changelog' } tasks.named("generateChangelog") { - previousRevision = "v3.3.10" githubToken = "secret" repository = "mockito/mockito" } @@ -67,8 +58,8 @@ class ChangelogPluginIntegTest extends BaseSpecification { //The release version, default as below version = project.version - //Token used for fetching tickets; same token is used for posting - should remain unexposed, *no default* - githubToken = "secret" + //Token that enables querying GitHub, safe to check-in because it is read-only, *no default* + githubToken = "a0a4c0f41c200f7c653323014d6a72a127764e17" //Repository to look for tickets, *no default* repository = "mockito/mockito" diff --git a/src/main/java/org/shipkit/changelog/GenerateChangelogTask.java b/src/main/java/org/shipkit/changelog/GenerateChangelogTask.java index 363ab86..bbf60f6 100644 --- a/src/main/java/org/shipkit/changelog/GenerateChangelogTask.java +++ b/src/main/java/org/shipkit/changelog/GenerateChangelogTask.java @@ -3,11 +3,8 @@ import org.gradle.api.DefaultTask; import org.gradle.api.logging.Logger; import org.gradle.api.logging.Logging; -import org.gradle.api.tasks.Input; -import org.gradle.api.tasks.InputDirectory; import org.gradle.api.tasks.Optional; -import org.gradle.api.tasks.OutputFile; -import org.gradle.api.tasks.TaskAction; +import org.gradle.api.tasks.*; import java.io.File; import java.util.*; @@ -51,11 +48,23 @@ public void setGhUrl(String ghUrl) { this.ghUrl = ghUrl; } + /** + * Previous revision for changelog generation. + * The changelog is generated between {@code #getPreviousRevision()} and {@link #getRevision()}. + * + * This property is marked as {@code Optional} because the {@code null} value is permitted. + * In this case the task will use "HEAD" as previous revision. + * This way, the task behaves gracefully when generating changelog for the first time (very first version). + */ @Input + @Optional public String getPreviousRevision() { return previousRevision; } + /** + * See {@link #getPreviousRevision()} + */ public void setPreviousRevision(String previousRevision) { this.previousRevision = previousRevision; } @@ -69,11 +78,18 @@ public void setVersion(String version) { this.version = version; } + /** + * Target revision for changelog generation. + * The changelog is generated between {@link #getPreviousRevision()} and {@code #getRevision()}. + */ @Input public String getRevision() { return revision; } + /** + * See {@link #getRevision()} + */ public void setRevision(String revision) { this.revision = revision; } @@ -153,6 +169,7 @@ public void setGithubToken(String githubToken) { ProcessRunner runner = new ProcessRunner(workingDir); GitLogProvider logProvider = new GitLogProvider(runner); + String previousRevision = this.previousRevision != null? this.previousRevision : "master"; LOG.lifecycle("Finding commits between {}..{} in dir: {}", previousRevision, revision, workingDir); Collection commits = new GitCommitProvider(logProvider).getCommits(previousRevision, revision); diff --git a/src/main/java/org/shipkit/changelog/GitLogProvider.java b/src/main/java/org/shipkit/changelog/GitLogProvider.java index 3d131bb..a8d30b8 100644 --- a/src/main/java/org/shipkit/changelog/GitLogProvider.java +++ b/src/main/java/org/shipkit/changelog/GitLogProvider.java @@ -1,18 +1,31 @@ package org.shipkit.changelog; +import org.gradle.api.logging.Logger; +import org.gradle.api.logging.Logging; + class GitLogProvider { + private final static Logger LOG = Logging.getLogger(GitLogProvider.class); + private final ProcessRunner runner; GitLogProvider(ProcessRunner runner) { this.runner = runner; } - public String getLog(String fromRev, String toRev, String format) { + + String getLog(String fromRev, String toRev, String format) { String fetch = "+refs/tags/" + fromRev + ":refs/tags/" + fromRev; String log = fromRev + ".." + toRev; - runner.run("git", "fetch", "origin", fetch); + try { + runner.run("git", "fetch", "origin", fetch); + } catch (Exception e) { + //This is a non blocking problem because we still are able to run git log locally + LOG.info("'git fetch' did not work, continuing running 'git log' locally."); + //To avoid confusion, no stack trace in debug log, just the message: + LOG.debug("'git fetch' problem: {}", e.getMessage()); + } return runner.run("git", "log", format, log); } } diff --git a/src/test/groovy/org/shipkit/changelog/GitLogProviderTest.groovy b/src/test/groovy/org/shipkit/changelog/GitLogProviderTest.groovy index d7affe9..6ddd90b 100644 --- a/src/test/groovy/org/shipkit/changelog/GitLogProviderTest.groovy +++ b/src/test/groovy/org/shipkit/changelog/GitLogProviderTest.groovy @@ -1,27 +1,45 @@ package org.shipkit.changelog - +import org.junit.Rule +import org.junit.rules.TemporaryFolder import spock.lang.Specification class GitLogProviderTest extends Specification { - def "smoke test"() { - File rootDir = findRootDir() - def provider = new GitLogProvider(new ProcessRunner(rootDir)) + @Rule TemporaryFolder tmp = new TemporaryFolder() + ProcessRunner runner + GitLogProvider provider + + def setup() { + runner = new ProcessRunner(tmp.root) + runner.run("git", "init") + runner.run("git", "config", "user.email", "dummy@testing.com") + runner.run("git", "config", "user.name", "Dummy For Testing") + + runner.run("git", "commit", "--allow-empty", "-m", "the initial commit") + runner.run("git", "tag", "v0.0.0") + runner.run("git", "commit", "--allow-empty", "-m", "the second test commit") + runner.run("git", "tag", "v0.0.1") + + provider = new GitLogProvider(runner) + } + + def "smoke test"() { when: def log = provider.getLog("v0.0.0", "v0.0.1", "--pretty=short") then: - log //TODO add assertions when we have more releases with small amount of commits + !log.contains("the initial commit") + log.contains("the second test commit") } - private File findRootDir() { - def testDir = new File(".") - while (!new File(testDir, ".git").directory && testDir != null) { - testDir = testDir.parentFile - } - assert testDir != null - testDir + def "no previous revision"() { + //this is the "first release" use case + when: + def log = provider.getLog("HEAD", "v0.0.1", "--pretty=short") + + then: + log == "" } }