diff --git a/docs/faq.md b/docs/faq.md index 938b2448..834e1621 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -16,13 +16,28 @@ Using Gradle vocabulary: all archives produced by all subprojects in your build Say that one of your subprojects is a "test" or "sample" project that you don't want to publish. To prevent publication, disable ```bintrayUpload``` task: -```java +```groovy //build.gradle of a subproject that you don't want to publish apply plugin: 'java' ... bintrayUpload.enabled = false ``` -See [docs/getting-started.md](/docs/getting-started.md) document. +### How to build my library against different JDK versions? +Sometimes projects are build against different Java versions, but you can't release the same +artifact version twice. To avoid failed builds on Travis, you can configure it like that: +```yaml +matrix: + include: + - jdk: oraclejdk8 + - jdk: oraclejdk9 + env: SKIP_RELEASE=true + - jdk: openjdk10 + env: SKIP_RELEASE=true + - jdk: openjdk11 + env: SKIP_RELEASE=true +``` + +Now only artifacts produced by JDK8 build will be published. diff --git a/subprojects/shipkit/src/main/groovy/org/shipkit/gradle/configuration/ShipkitConfiguration.java b/subprojects/shipkit/src/main/groovy/org/shipkit/gradle/configuration/ShipkitConfiguration.java index 9be50e95..941e845b 100644 --- a/subprojects/shipkit/src/main/groovy/org/shipkit/gradle/configuration/ShipkitConfiguration.java +++ b/subprojects/shipkit/src/main/groovy/org/shipkit/gradle/configuration/ShipkitConfiguration.java @@ -25,6 +25,7 @@ public class ShipkitConfiguration { private final ShipkitConfigurationStore store; private final GitHub gitHub = new GitHub(); + private final Javadoc javadoc = new Javadoc(); private final ReleaseNotes releaseNotes = new ReleaseNotes(); private final Git git = new Git(); private final Team team = new Team(); @@ -86,6 +87,10 @@ public GitHub getGitHub() { return gitHub; } + public Javadoc getJavadoc() { + return javadoc; + } + public ReleaseNotes getReleaseNotes() { return releaseNotes; } @@ -218,11 +223,84 @@ public String getWriteAuthToken() { " shipkit.gitHub.writeAuthToken = 'secret'"); } + /** + * @see {@link #getWriteAuthToken()} + */ public void setWriteAuthToken(String writeAuthToken) { store.put("gitHub.writeAuthToken", writeAuthToken); } } + public class Javadoc { + /** + * GitHub Javadoc repository name, for example: "mockito/shipkit-javadoc". + * The default value is repository with "-javadoc" suffix. + * @since 2.2.0 + */ + public String getRepository() { + return store.getString("javadoc.repository"); + } + + /** + * @see {@link #getRepository()} + * @since 2.2.0 + */ + public void setRepository(String javadocRepository) { + store.put("javadoc.repository", javadocRepository); + } + + /** + * GitHub Javadoc repository branch name. The branch needs to exist. + * By default it's using the branch set as main in GitHub repo, usually master. + * @since 2.2.0 + */ + public String getRepositoryBranch() { + return store.getString("javadoc.repositoryBranch"); + } + + /** + * @see {@link #getRepositoryBranch()} + * @since 2.2.0 + */ + public void setRepositoryBranch(String javadocRepositoryBranch) { + store.put("javadoc.repositoryBranch", javadocRepositoryBranch); + } + + /** + * GitHub Javadoc repository directory where put javadoc files. By default it's root directory. + * @since 2.2.0 + */ + public String getRepositoryDirectory() { + return store.getString("javadoc.repositoryDirectory"); + } + + /** + * @see {@link #getRepositoryDirectory()} + * @since 2.2.0 + */ + public void setRepositoryDirectory(String javadocRepositoryDirectory) { + store.put("javadoc.repositoryDirectory", javadocRepositoryDirectory); + } + + /** + * Commit message used to commit Javadocs. Default: "Update current and ${version} Javadocs. [ci skip]" + * You can override this message and ${version} will be replaced by currently build version. + * You don't need to specify "[ci skip]" in your message - it will be added automatically. + * @since 2.2.0 + */ + public String getCommitMessage() { + return store.getString("javadoc.commitMessage"); + } + + /** + * @see {@link #getCommitMessage()} + * @since 2.2.0 + */ + public void setCommitMessage(String commitMessage) { + store.put("javadoc.commitMessage", commitMessage); + } + } + public class ReleaseNotes { /** @@ -303,7 +381,7 @@ public void setPublicationRepository(String publicationRepository) { * Get the Publication Plugin Name * * @see @setPublicationPluginName(String) - * + * @since 2.0.32 * @deprecated since 2.1.6 because we no longer are using this one. It is scheduled to be removed in 3.0.0. */ @Deprecated @@ -328,6 +406,8 @@ public String getPublicationPluginName() { * * This will show nice badge with actual plugin version in Gradle Plugin Portal. * + * @since 2.0.32 + * * @deprecated since 2.1.6 because we no longer are using this one. It is scheduled to be removed in 3.0.0. */ @Deprecated diff --git a/subprojects/shipkit/src/main/groovy/org/shipkit/gradle/exec/ShipkitExecTask.java b/subprojects/shipkit/src/main/groovy/org/shipkit/gradle/exec/ShipkitExecTask.java index e477437f..e338937d 100644 --- a/subprojects/shipkit/src/main/groovy/org/shipkit/gradle/exec/ShipkitExecTask.java +++ b/subprojects/shipkit/src/main/groovy/org/shipkit/gradle/exec/ShipkitExecTask.java @@ -20,7 +20,7 @@ public class ShipkitExecTask extends DefaultTask { * Executes all commands */ @TaskAction public void execCommands() { - new ShipkitExec().execCommands(this.getExecCommands(), this.getProject()); + new ShipkitExec().execCommands(this.getExecCommands(), this.getProject(), null); } /** diff --git a/subprojects/shipkit/src/main/groovy/org/shipkit/gradle/git/GitCommitTask.java b/subprojects/shipkit/src/main/groovy/org/shipkit/gradle/git/GitCommitTask.java index e637db20..b3dbf111 100644 --- a/subprojects/shipkit/src/main/groovy/org/shipkit/gradle/git/GitCommitTask.java +++ b/subprojects/shipkit/src/main/groovy/org/shipkit/gradle/git/GitCommitTask.java @@ -3,6 +3,7 @@ import org.gradle.api.DefaultTask; import org.gradle.api.Task; import org.gradle.api.tasks.Input; +import org.gradle.api.tasks.Optional; import org.gradle.api.tasks.SkipWhenEmpty; import org.gradle.api.tasks.TaskAction; import org.shipkit.internal.gradle.git.tasks.GitCommitImpl; @@ -23,6 +24,7 @@ public class GitCommitTask extends DefaultTask { @Input String gitUserName; @Input String gitUserEmail; @Input String commitMessagePostfix; + @Input @Optional File workingDir; @TaskAction public void commit() { new GitCommitImpl().commit(this); @@ -37,7 +39,9 @@ public class GitCommitTask extends DefaultTask { * @param taskMakingChange task that makes the change, we will automatically set 'dependsOn' this task */ public void addChange(List files, String changeDescription, Task taskMakingChange) { - dependsOn(taskMakingChange); + if (taskMakingChange != null) { + dependsOn(taskMakingChange); + } filesToCommit.addAll(files); descriptions.add(changeDescription); } @@ -92,10 +96,26 @@ public List getFilesToCommit() { } /** - * Change descriptions to be included in the commit message. + * Get descriptions to be included in the commit message. * Descriptions are registered using {@link #addChange(List, String, Task)} */ public List getDescriptions() { return descriptions; } + + /** + * Gets working directory where commands are executed. By default it is project root directory. + * @since 2.2.0 + */ + public File getWorkingDir() { + return workingDir; + } + + /** + * @see {@link #getWorkingDir()} + * @since 2.2.0 + */ + public void setWorkingDir(File workingDir) { + this.workingDir = workingDir; + } } diff --git a/subprojects/shipkit/src/main/groovy/org/shipkit/gradle/git/GitPushTask.java b/subprojects/shipkit/src/main/groovy/org/shipkit/gradle/git/GitPushTask.java index 62c8d824..fe8b4c63 100644 --- a/subprojects/shipkit/src/main/groovy/org/shipkit/gradle/git/GitPushTask.java +++ b/subprojects/shipkit/src/main/groovy/org/shipkit/gradle/git/GitPushTask.java @@ -2,6 +2,7 @@ import org.gradle.api.DefaultTask; import org.gradle.api.tasks.Input; +import org.gradle.api.tasks.Optional; import org.gradle.api.tasks.TaskAction; import org.shipkit.internal.gradle.git.tasks.GitPush; @@ -20,6 +21,7 @@ public class GitPushTask extends DefaultTask { @Input private List targets = new LinkedList<>(); @Input private String url; @Input private boolean dryRun; + @Input @Optional private String workingDir; private String secretValue; @TaskAction public void gitPush() { @@ -82,4 +84,20 @@ public String getSecretValue() { public void setSecretValue(String secretValue) { this.secretValue = secretValue; } + + /** + * Gets working directory where commands are executed. By default it is project root directory. + * @since 2.2.0 + */ + public String getWorkingDir() { + return workingDir; + } + + /** + * @see {@link #getWorkingDir()} + * @since 2.2.0 + */ + public void setWorkingDir(String workingDir) { + this.workingDir = workingDir; + } } diff --git a/subprojects/shipkit/src/main/groovy/org/shipkit/internal/gradle/exec/ShipkitExec.java b/subprojects/shipkit/src/main/groovy/org/shipkit/internal/gradle/exec/ShipkitExec.java index cf4110ee..84c223dd 100644 --- a/subprojects/shipkit/src/main/groovy/org/shipkit/internal/gradle/exec/ShipkitExec.java +++ b/subprojects/shipkit/src/main/groovy/org/shipkit/internal/gradle/exec/ShipkitExec.java @@ -10,13 +10,20 @@ import org.shipkit.internal.exec.ExternalProcessStream; import org.shipkit.internal.gradle.util.StringUtil; +import java.io.File; import java.util.Collection; public class ShipkitExec { private final static Logger LOG = Logging.getLogger(ShipkitExec.class); - public void execCommands(Collection execCommands, Project project) { + /** + * Execute commands and print execution summary. + * @param execCommands Commands to execute + * @param project Gradle Project instance + * @param workingDir Working directory where command will be executed, it may be null + */ + public void execCommands(Collection execCommands, Project project, File workingDir) { for (final ExecCommand execCommand : execCommands) { ExecResult result = project.exec(new Action() { @Override @@ -25,6 +32,9 @@ public void execute(ExecSpec spec) { spec.commandLine(execCommand.getCommandLine()); spec.setStandardOutput(new ExternalProcessStream(execCommand.getLoggingPrefix(), System.out)); spec.setErrorOutput(new ExternalProcessStream(execCommand.getLoggingPrefix(), System.err)); + if (workingDir != null) { + spec.setWorkingDir(workingDir); + } execCommand.getSetupAction().execute(spec); diff --git a/subprojects/shipkit/src/main/groovy/org/shipkit/internal/gradle/git/GitCommitTaskFactory.java b/subprojects/shipkit/src/main/groovy/org/shipkit/internal/gradle/git/GitCommitTaskFactory.java new file mode 100644 index 00000000..98e0d2ed --- /dev/null +++ b/subprojects/shipkit/src/main/groovy/org/shipkit/internal/gradle/git/GitCommitTaskFactory.java @@ -0,0 +1,21 @@ +package org.shipkit.internal.gradle.git; + +import org.gradle.api.Project; +import org.shipkit.gradle.configuration.ShipkitConfiguration; +import org.shipkit.gradle.git.GitCommitTask; +import org.shipkit.internal.gradle.configuration.ShipkitConfigurationPlugin; +import org.shipkit.internal.gradle.util.TaskMaker; + +public class GitCommitTaskFactory { + + public static GitCommitTask createGitCommitTask(Project project, String taskName, String description) { + ShipkitConfiguration conf = project.getPlugins().apply(ShipkitConfigurationPlugin.class).getConfiguration(); + + return TaskMaker.task(project, taskName, GitCommitTask.class, task -> { + task.setDescription(description); + task.setGitUserName(conf.getGit().getUser()); + task.setGitUserEmail(conf.getGit().getEmail()); + task.setCommitMessagePostfix(conf.getGit().getCommitMessagePostfix()); + }); + } +} diff --git a/subprojects/shipkit/src/main/groovy/org/shipkit/internal/gradle/git/GitPlugin.java b/subprojects/shipkit/src/main/groovy/org/shipkit/internal/gradle/git/GitPlugin.java index 18b94b24..e429dfa3 100644 --- a/subprojects/shipkit/src/main/groovy/org/shipkit/internal/gradle/git/GitPlugin.java +++ b/subprojects/shipkit/src/main/groovy/org/shipkit/internal/gradle/git/GitPlugin.java @@ -54,14 +54,8 @@ public class GitPlugin implements Plugin { public void apply(final Project project) { final ShipkitConfiguration conf = project.getPlugins().apply(ShipkitConfigurationPlugin.class).getConfiguration(); - TaskMaker.task(project, GIT_COMMIT_TASK, GitCommitTask.class, new Action() { - public void execute(final GitCommitTask t) { - t.setDescription("Commits all changed files using generic --author and aggregated commit message"); - t.setGitUserName(conf.getGit().getUser()); - t.setGitUserEmail(conf.getGit().getEmail()); - t.setCommitMessagePostfix(conf.getGit().getCommitMessagePostfix()); - } - }); + GitCommitTaskFactory.createGitCommitTask(project, GIT_COMMIT_TASK, + "Commits all changed files using generic --author and aggregated commit message"); TaskMaker.task(project, GIT_TAG_TASK, ShipkitExecTask.class, new Action() { public void execute(final ShipkitExecTask t) { @@ -82,7 +76,7 @@ public void execute(final GitPushTask t) { t.getTargets().add(GitUtil.getTag(conf, project)); t.setDryRun(conf.isDryRun()); - GitUrlInfo info = new GitUrlInfo(conf); + GitUrlInfo info = new GitUrlInfo(conf, conf.getGitHub().getRepository()); t.setUrl(info.getGitUrl()); t.setSecretValue(info.getWriteToken()); diff --git a/subprojects/shipkit/src/main/groovy/org/shipkit/internal/gradle/git/GitUrlInfo.java b/subprojects/shipkit/src/main/groovy/org/shipkit/internal/gradle/git/GitUrlInfo.java index 9c3b5ac2..24968a3d 100644 --- a/subprojects/shipkit/src/main/groovy/org/shipkit/internal/gradle/git/GitUrlInfo.java +++ b/subprojects/shipkit/src/main/groovy/org/shipkit/internal/gradle/git/GitUrlInfo.java @@ -9,8 +9,8 @@ public class GitUrlInfo { private final String gitUrl; private final String writeToken; - public GitUrlInfo(ShipkitConfiguration conf) { - gitUrl = getGitHubUrl(conf.getGitHub().getRepository(), conf); + public GitUrlInfo(ShipkitConfiguration conf, String repository) { + gitUrl = getGitHubUrl(repository, conf); writeToken = conf.getLenient().getGitHub().getWriteAuthToken(); } diff --git a/subprojects/shipkit/src/main/groovy/org/shipkit/internal/gradle/git/tasks/GitCheckOutTask.java b/subprojects/shipkit/src/main/groovy/org/shipkit/internal/gradle/git/tasks/GitCheckOutTask.java index 5e40541e..4f9fd946 100644 --- a/subprojects/shipkit/src/main/groovy/org/shipkit/internal/gradle/git/tasks/GitCheckOutTask.java +++ b/subprojects/shipkit/src/main/groovy/org/shipkit/internal/gradle/git/tasks/GitCheckOutTask.java @@ -1,15 +1,17 @@ package org.shipkit.internal.gradle.git.tasks; +import java.io.File; +import java.util.ArrayList; +import java.util.List; + import org.gradle.api.DefaultTask; import org.gradle.api.tasks.Input; +import org.gradle.api.tasks.Optional; import org.gradle.api.tasks.TaskAction; import org.shipkit.internal.exec.DefaultProcessRunner; import org.shipkit.internal.exec.ProcessRunner; import org.shipkit.internal.util.ExposedForTesting; -import java.util.ArrayList; -import java.util.List; - /** * This task will checkout a certain revision. */ @@ -19,6 +21,8 @@ public class GitCheckOutTask extends DefaultTask { private String rev; @Input private boolean newBranch; + @Input @Optional + private File directory; private ProcessRunner processRunner; @@ -50,6 +54,20 @@ public boolean isNewBranch() { return newBranch; } + /** + * A directory where execute git command + */ + public File getDirectory() { + return directory; + } + + /** + * See {@link #getDirectory()} + */ + public void setDirectory(File directory) { + this.directory = directory; + } + @TaskAction public void checkOut() { getProcessRunner().run(getCommandLine()); @@ -68,7 +86,11 @@ private List getCommandLine() { private ProcessRunner getProcessRunner() { if (processRunner == null) { - return new DefaultProcessRunner(getProject().getProjectDir()); + if (directory == null) { + return new DefaultProcessRunner(getProject().getProjectDir()); + } else { + return new DefaultProcessRunner(directory); + } } return processRunner; } diff --git a/subprojects/shipkit/src/main/groovy/org/shipkit/internal/gradle/git/tasks/GitCommitImpl.java b/subprojects/shipkit/src/main/groovy/org/shipkit/internal/gradle/git/tasks/GitCommitImpl.java index 15ca4904..47b1bb8f 100644 --- a/subprojects/shipkit/src/main/groovy/org/shipkit/internal/gradle/git/tasks/GitCommitImpl.java +++ b/subprojects/shipkit/src/main/groovy/org/shipkit/internal/gradle/git/tasks/GitCommitImpl.java @@ -21,7 +21,7 @@ public void commit(GitCommitTask task) { getAddCommand(task.getFilesToCommit()))); commands.add(execCommand("Performing git commit", getCommitCommand(task.getGitUserName(), task.getGitUserEmail(), task.getDescriptions(), task.getCommitMessagePostfix()))); - new ShipkitExec().execCommands(commands, task.getProject()); + new ShipkitExec().execCommands(commands, task.getProject(), task.getWorkingDir()); } static String getAggregatedCommitMessage(List descriptions) { diff --git a/subprojects/shipkit/src/main/groovy/org/shipkit/internal/gradle/git/tasks/GitPush.java b/subprojects/shipkit/src/main/groovy/org/shipkit/internal/gradle/git/tasks/GitPush.java index afee54bd..9de172a0 100644 --- a/subprojects/shipkit/src/main/groovy/org/shipkit/internal/gradle/git/tasks/GitPush.java +++ b/subprojects/shipkit/src/main/groovy/org/shipkit/internal/gradle/git/tasks/GitPush.java @@ -4,6 +4,7 @@ import org.shipkit.internal.exec.DefaultProcessRunner; import org.shipkit.internal.gradle.util.handler.GitPushExceptionHandler; +import java.io.File; import java.util.LinkedList; import java.util.List; @@ -33,7 +34,7 @@ public void gitPush(final GitPushTask task) { Runnable gitPush = new Runnable() { public void run() { - new DefaultProcessRunner(task.getProject().getProjectDir()) + new DefaultProcessRunner(getWorkDir(task)) .setSecretValue(task.getSecretValue()) .run(GitPush.gitPushArgs(task.getUrl(), task.getTargets(), task.isDryRun())); } @@ -41,4 +42,11 @@ public void run() { withExceptionHandling(gitPush, new GitPushExceptionHandler(task.getSecretValue())); } + + private File getWorkDir(GitPushTask task) { + if (task.getWorkingDir() != null) { + return new File(task.getWorkingDir()); + } + return task.getProject().getProjectDir(); + } } diff --git a/subprojects/shipkit/src/main/groovy/org/shipkit/internal/gradle/javadoc/JavadocPlugin.java b/subprojects/shipkit/src/main/groovy/org/shipkit/internal/gradle/javadoc/JavadocPlugin.java new file mode 100644 index 00000000..c2dcaa07 --- /dev/null +++ b/subprojects/shipkit/src/main/groovy/org/shipkit/internal/gradle/javadoc/JavadocPlugin.java @@ -0,0 +1,273 @@ +package org.shipkit.internal.gradle.javadoc; + +import org.gradle.api.Plugin; +import org.gradle.api.Project; +import org.gradle.api.Task; +import org.gradle.api.tasks.Copy; +import org.gradle.jvm.tasks.Jar; +import org.shipkit.gradle.configuration.ShipkitConfiguration; +import org.shipkit.gradle.git.GitCommitTask; +import org.shipkit.gradle.git.GitPushTask; +import org.shipkit.internal.gradle.configuration.ShipkitConfigurationPlugin; +import org.shipkit.internal.gradle.git.GitCommitTaskFactory; +import org.shipkit.internal.gradle.git.GitPlugin; +import org.shipkit.internal.gradle.git.GitUrlInfo; +import org.shipkit.internal.gradle.git.tasks.CloneGitRepositoryTask; +import org.shipkit.internal.gradle.git.tasks.GitCheckOutTask; +import org.shipkit.internal.gradle.util.TaskMaker; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.HashSet; +import java.util.Set; + +import static java.util.Collections.singletonList; +import static java.util.Objects.isNull; + +/** + * Release Javadoc to git repository. + *

+ * Applies: + * + *

    + *
  • {@link GitPlugin}
  • + *
  • {@link ShipkitConfigurationPlugin}
  • + *
+ * + *

+ * Adds tasks: + * + *

    + *
  • cloneJavadocRepo - clones Javadoc repository into a temporary directory. Javadoc will be published in this + * repository.
  • + *
  • checkoutJavadocRepoBranch - checkouts a branch in Javadoc repository, where Javadoc will be published.
  • + *
  • copyJavadocToStageVersionDir - extracts and copies Javadoc from Javadoc jar to stage directory to version + * (eg.: "/1.2.3") subdirectory. This task is added to each subproject.
  • + *
  • copyJavadocToStageCurrentDir - extracts and copies Javadoc from Javadoc jar to stage directory to /current + * current directory. This task is added to each subproject.
  • + *
  • refreshVersionJavadoc - aggregates all copyJavadocToStageVersionDir tasks.
  • + *
  • refreshCurrentJavadoc - aggregates all copyJavadocToStageCurrentDir tasks.
  • + *
  • copyJavadocStageToRepoDir - copies all Javadocs from stage directory to Javadoc repository directory.
  • + *
  • commitJavadoc - commits all changes in Javadoc repository.
  • + *
  • pushJavadoc - pushes Javadocs to remote Javadoc repository.
  • + *
  • releaseJavadoc - aggregate all tasks needed to release Javadocs: clone, checkout, copy, commit, push.
  • + *
  • clean - additionally removes build directory in project root
  • + *
+ */ +public class JavadocPlugin implements Plugin { + + private static final String CHECKOUT_JAVADOC_REPO_BRANCH = "checkoutJavadocRepoBranch"; + private static final String CLONE_JAVADOC_REPO = "cloneJavadocRepo"; + private static final String COMMIT_JAVADOC_TASK = "commitJavadoc"; + private static final String COPY_JAVADOC_STAGE_TO_REPO_DIR_TASK = "copyJavadocStageToRepoDir"; + private static final String COPY_JAVADOC_TO_STAGE_VERSION_DIR_TASK = "copyJavadocToStageVersionDir"; + private static final String COPY_JAVADOC_TO_STAGE_CURRENT_DIR_TASK = "copyJavadocToStageCurrentDir"; + private static final String PUSH_JAVADOC_TASK = "pushJavadoc"; + private static final String RELEASE_JAVADOC_TASK = "releaseJavadoc"; + private static final String REFRESH_CURRENT_JAVADOC_TASK = "refreshCurrentJavadoc"; + private static final String REFRESH_VERSION_JAVADOC_TASK = "refreshVersionJavadoc"; + + @Override + public void apply(Project project) { + project.getPlugins().apply(GitPlugin.class); + ShipkitConfiguration conf = project.getPlugins().apply(ShipkitConfigurationPlugin.class).getConfiguration(); + + CloneGitRepositoryTask cloneJavadocTask = createCloneJavadocTask(project, conf); + + GitCheckOutTask checkoutJavadocRepoBranch = createCheckoutJavadocReposBranch(project, conf); + checkoutJavadocRepoBranch.dependsOn(cloneJavadocTask); + + CopyTasks copyTasks = createCopyJavadocToStageTasks(project); + Task refreshVersionJavadocTask = createRefreshVersionJavadocTask(project, copyTasks.copyToVersionTasks); + Task refreshCurrentJavadocTask = createRefreshCurrentJavadocTask(project, copyTasks.copyToCurrentTasks); + + //refresh javadoc first so that if there is no javadoc we will avoid cloning + cloneJavadocTask.mustRunAfter(refreshVersionJavadocTask); + + Copy copyStageToRepoDir = createCopyStageToRepoDirTask(project, conf); + copyStageToRepoDir.dependsOn(checkoutJavadocRepoBranch, refreshVersionJavadocTask, refreshCurrentJavadocTask); + + GitCommitTask commitJavadocTask = createGitCommitTask(project, conf); + commitJavadocTask.dependsOn(copyStageToRepoDir); + + GitPushTask pushJavadoc = createPushJavadocTask(project, conf); + pushJavadoc.dependsOn(commitJavadocTask); + + Task releaseJavadocTask = createReleaseJavadocTask(project, cloneJavadocTask, commitJavadocTask, pushJavadoc); + releaseJavadocTask.dependsOn(cloneJavadocTask, commitJavadocTask, pushJavadoc); + + deleteBuildDIrInRootProjectWhenCleanTask(project); + } + + private CloneGitRepositoryTask createCloneJavadocTask(Project project, ShipkitConfiguration conf) { + String javadocRepository = getJavadocRepository(conf); + String gitHubUrl = conf.getGitHub().getUrl(); + return TaskMaker.task(project, CLONE_JAVADOC_REPO, CloneGitRepositoryTask.class, + task -> { + task.setDescription("Clones Javadoc repo " + javadocRepository + " into a temporary directory."); + task.setRepositoryUrl(gitHubUrl + "/" + javadocRepository); + task.setTargetDir(new File(getJavadocRepoCloneDir(project))); + // onlyIf { stagingDir not empty } + task.onlyIf(t -> containsFileInDir(getJavadocStageDir(project))); + }); + } + + private GitCheckOutTask createCheckoutJavadocReposBranch(Project project, ShipkitConfiguration conf) { + String branch = conf.getLenient().getJavadoc().getRepositoryBranch(); + return TaskMaker.task(project, CHECKOUT_JAVADOC_REPO_BRANCH, GitCheckOutTask.class, task -> { + task.setDescription("Checkout branch in Javadoc repository"); + task.onlyIf(foo -> branch != null); + task.setRev(branch); + task.setNewBranch(false); + task.setDirectory(new File(getJavadocRepoCloneDir(project))); + }); + } + + private CopyTasks createCopyJavadocToStageTasks(Project project) { + Set copyToVersionTasks = new HashSet<>(); + Set copyToCurrentTasks = new HashSet<>(); + + project.getTasksByName("javadocJar", true).stream() + .map(task -> (Jar) task) + .forEach(javadocJarTask -> { + Copy copyToVersionTask = TaskMaker.task(javadocJarTask.getProject(), COPY_JAVADOC_TO_STAGE_VERSION_DIR_TASK, Copy.class, copyTask -> { + copyTask.setDescription("Extracts contents of javadoc jar to the staging /version directory"); + copyTask.dependsOn(javadocJarTask); + copyTask.from(project.zipTree(javadocJarTask.getArchivePath())); + // TODO how? : note that we need to use Closure/Callable because 'baseName' can be set by user later + copyTask.into(getJavadocStageDir(project) + "/" + javadocJarTask.getBaseName() + "/" + project.getVersion()); + }); + copyToVersionTasks.add(copyToVersionTask); + + Copy copyToCurrentTask = TaskMaker.task(javadocJarTask.getProject(), COPY_JAVADOC_TO_STAGE_CURRENT_DIR_TASK, Copy.class, copyTask -> { + copyTask.setDescription("Extracts contents of javadoc jar to the staging /current directory"); + copyTask.dependsOn(copyToVersionTask); + copyTask.from(copyToVersionTask.getDestinationDir()); + // TODO how? : note that we need to use Closure/Callable because 'baseName' can be set by user later + copyTask.into(getJavadocStageDir(project) + "/" + javadocJarTask.getBaseName() + "/current"); + }); + copyToCurrentTasks.add(copyToCurrentTask); + }); + return new CopyTasks(copyToVersionTasks, copyToCurrentTasks); + } + + private Task createRefreshVersionJavadocTask(Project project, Set copyToVersionTasks) { + return TaskMaker.task(project, REFRESH_VERSION_JAVADOC_TASK, task -> { + task.dependsOn(copyToVersionTasks); + task.setDescription("Copy Javadocs from all modules to the staging /version directory"); + }); + } + + private Task createRefreshCurrentJavadocTask(Project project, Set copyToCurrentTasks) { + return TaskMaker.task(project, REFRESH_CURRENT_JAVADOC_TASK, task -> { + task.dependsOn(copyToCurrentTasks); + task.setDescription("Copy Javadocs from all modules to the staging /current directory"); + }); + } + + private Copy createCopyStageToRepoDirTask(Project project, + ShipkitConfiguration conf) { + String directory = conf.getLenient().getJavadoc().getRepositoryDirectory(); + + return TaskMaker.task(project, COPY_JAVADOC_STAGE_TO_REPO_DIR_TASK, Copy.class, task -> { + task.setDescription("Copy prepared Javadocs from stage directory to the repository directory"); + task.from(getJavadocStageDir(project)); + task.into(getJavadocRepoCloneDir(project, directory)); + }); + } + + private GitCommitTask createGitCommitTask(Project project, ShipkitConfiguration conf) { + String directory = conf.getLenient().getJavadoc().getRepositoryDirectory(); + + GitCommitTask commitJavadocTask = GitCommitTaskFactory.createGitCommitTask(project, COMMIT_JAVADOC_TASK, + "Commit changes in Javadoc repository directory"); + + String commitMessage = getCommitMessage(project, conf.getLenient()); + File file = new File(getJavadocRepoCloneDir(project, directory)); + commitJavadocTask.addChange(singletonList(file), commitMessage, null); + commitJavadocTask.setWorkingDir(new File(getJavadocRepoCloneDir(project))); + return commitJavadocTask; + } + + private GitPushTask createPushJavadocTask(Project project, ShipkitConfiguration conf) { + String branch = conf.getLenient().getJavadoc().getRepositoryBranch(); + String javadocRepository = getJavadocRepository(conf); + + return TaskMaker.task(project, PUSH_JAVADOC_TASK, GitPushTask.class, task -> { + task.setDescription("Pushes Javadocs to remote Javadoc repository"); + task.setDryRun(conf.isDryRun()); + task.setWorkingDir(getJavadocRepoCloneDir(project)); + + GitUrlInfo info = new GitUrlInfo(conf, javadocRepository); + task.setUrl(info.getGitUrl()); + task.setSecretValue(info.getWriteToken()); + if (branch != null) { + task.getTargets().add(branch); + } + }); + } + + private Task createReleaseJavadocTask(Project project, CloneGitRepositoryTask cloneJavadocTask, GitCommitTask commitJavadocTask, GitPushTask pushJavadoc) { + return TaskMaker.task(project, RELEASE_JAVADOC_TASK, task -> { + task.setDescription("Clone Javadoc repository, copy Javadocs, commit and push"); + }); + } + + private String getJavadocRepository(ShipkitConfiguration conf) { + String javadocRepository = conf.getLenient().getJavadoc().getRepository(); + if (javadocRepository == null) { + javadocRepository = conf.getGitHub().getRepository() + "-javadoc"; // sensible default + } + return javadocRepository; + } + + private String getJavadocRepoCloneDir(Project project) { + return project.getRootProject().getBuildDir().getAbsolutePath() + "/javadoc-repo"; + } + + private String getJavadocRepoCloneDir(Project project, String subdirectory) { + return getJavadocRepoCloneDir(project) + + "/" + (subdirectory != null ? subdirectory : "."); + } + + private String getJavadocStageDir(Project project) { + return project.getRootProject().getBuildDir().getAbsolutePath() + "/javadoc-stage"; + } + + private boolean containsFileInDir(String directory) { + try { + return Files.walk(Paths.get(directory)) + .anyMatch(path -> path.toFile().isFile()); + } catch (IOException e) { + return false; + } + } + + private String getCommitMessage(Project project, ShipkitConfiguration lenientConf) { + String commitMessage = lenientConf.getJavadoc().getCommitMessage(); + if (isNull(commitMessage)) { + commitMessage = "Update current and ${version} Javadocs."; + } + commitMessage = commitMessage.replaceAll("\\$\\{version\\}", project.getVersion().toString()); + return commitMessage; + } + + private void deleteBuildDIrInRootProjectWhenCleanTask(Project project) { + Set cleanTasks = project.getTasksByName("clean", true); + cleanTasks.forEach(task -> task.doLast(t -> { + project.delete(project.getBuildDir().getAbsolutePath()); + })); + } + + private class CopyTasks { + private final Set copyToVersionTasks; + private final Set copyToCurrentTasks; + + private CopyTasks(Set copyToVersionTasks, Set copyToCurrentTasks) { + this.copyToVersionTasks = copyToVersionTasks; + this.copyToCurrentTasks = copyToCurrentTasks; + } + } +} diff --git a/subprojects/shipkit/src/main/groovy/org/shipkit/internal/gradle/notes/tasks/UpdateReleaseNotes.java b/subprojects/shipkit/src/main/groovy/org/shipkit/internal/gradle/notes/tasks/UpdateReleaseNotes.java index ca921b54..d853ec6f 100644 --- a/subprojects/shipkit/src/main/groovy/org/shipkit/internal/gradle/notes/tasks/UpdateReleaseNotes.java +++ b/subprojects/shipkit/src/main/groovy/org/shipkit/internal/gradle/notes/tasks/UpdateReleaseNotes.java @@ -94,6 +94,7 @@ public String generateNewContent(AbstractReleaseNotesTask task, HeaderProvider h Map contributorsMap = contributorsMap(task.getContributors(), contributorsFromGitHub, task.getDevelopers(), task.getGitHubUrl()); BadgeFormatter badgeFormatter = new BadgeFormatter(); + // TODO release notes contain link to new javadoc String notes = ReleaseNotesFormatters.detailedFormatter(headerMessage, "", task.getGitHubLabelMapping(), vcsCommitTemplate, task.getPublicationRepository(), contributorsMap, task.isEmphasizeVersion(), badgeFormatter) diff --git a/subprojects/shipkit/src/main/groovy/org/shipkit/internal/gradle/versionupgrade/UpgradeDependencyPlugin.java b/subprojects/shipkit/src/main/groovy/org/shipkit/internal/gradle/versionupgrade/UpgradeDependencyPlugin.java index 3e70376a..1056c4e8 100644 --- a/subprojects/shipkit/src/main/groovy/org/shipkit/internal/gradle/versionupgrade/UpgradeDependencyPlugin.java +++ b/subprojects/shipkit/src/main/groovy/org/shipkit/internal/gradle/versionupgrade/UpgradeDependencyPlugin.java @@ -137,7 +137,7 @@ public void run() { gitOriginPlugin.provideOriginRepo(task, new Action() { public void execute(String originRepo) { - GitUrlInfo info = new GitUrlInfo(conf); + GitUrlInfo info = new GitUrlInfo(conf, conf.getGitHub().getRepository()); task.setUrl(info.getGitUrl()); task.setSecretValue(info.getWriteToken()); } @@ -230,7 +230,7 @@ public void execute(final GitPushTask task) { gitOriginPlugin.provideOriginRepo(task, new Action() { public void execute(String originRepo) { - GitUrlInfo info = new GitUrlInfo(conf); + GitUrlInfo info = new GitUrlInfo(conf, conf.getGitHub().getRepository()); task.setUrl(info.getGitUrl()); task.setSecretValue(info.getWriteToken()); } diff --git a/subprojects/shipkit/src/main/groovy/org/shipkit/internal/notes/format/DetailedFormatter.java b/subprojects/shipkit/src/main/groovy/org/shipkit/internal/notes/format/DetailedFormatter.java index abe6463b..51209d12 100644 --- a/subprojects/shipkit/src/main/groovy/org/shipkit/internal/notes/format/DetailedFormatter.java +++ b/subprojects/shipkit/src/main/groovy/org/shipkit/internal/notes/format/DetailedFormatter.java @@ -76,6 +76,7 @@ private static String buildHeader(String version, String prefix) { String releaseSummary(Date date, String version, ContributionSet contributions, Map contributors, String vcsCommitsLink, String publicationRepository) { + // TODO the message at the end of the release points to new javadoc return summaryDatePrefix(date) + authorsSummary(contributions, contributors, vcsCommitsLink) + " - published to " + badgeFormatter.getRepositoryBadge(version, publicationRepository) + "\n" + authorsSummaryAppendix(contributions, contributors); diff --git a/subprojects/shipkit/src/main/resources/META-INF/gradle-plugins/org.shipkit.javadoc.properties b/subprojects/shipkit/src/main/resources/META-INF/gradle-plugins/org.shipkit.javadoc.properties new file mode 100644 index 00000000..3c7701e7 --- /dev/null +++ b/subprojects/shipkit/src/main/resources/META-INF/gradle-plugins/org.shipkit.javadoc.properties @@ -0,0 +1 @@ +implementation-class=org.shipkit.internal.gradle.javadoc.JavadocPlugin diff --git a/subprojects/shipkit/src/test/groovy/org/shipkit/internal/gradle/git/tasks/GitCommitImplTest.groovy b/subprojects/shipkit/src/test/groovy/org/shipkit/internal/gradle/git/tasks/GitCommitImplTest.groovy index 1ed9d775..5f6fe12b 100644 --- a/subprojects/shipkit/src/test/groovy/org/shipkit/internal/gradle/git/tasks/GitCommitImplTest.groovy +++ b/subprojects/shipkit/src/test/groovy/org/shipkit/internal/gradle/git/tasks/GitCommitImplTest.groovy @@ -14,7 +14,7 @@ class GitCommitImplTest extends Specification { getAggregatedCommitMessage(["release notes updated", "version bumped"]) == "release notes updated + version bumped" } - def "git add command"() { + def "git add command for files"() { def f1 = new File("f1") def f2 = new File("f2") diff --git a/subprojects/shipkit/src/test/groovy/org/shipkit/internal/gradle/git/tasks/GitCommitTaskTest.groovy b/subprojects/shipkit/src/test/groovy/org/shipkit/internal/gradle/git/tasks/GitCommitTaskTest.groovy index 6e9b3a0f..337a198d 100644 --- a/subprojects/shipkit/src/test/groovy/org/shipkit/internal/gradle/git/tasks/GitCommitTaskTest.groovy +++ b/subprojects/shipkit/src/test/groovy/org/shipkit/internal/gradle/git/tasks/GitCommitTaskTest.groovy @@ -19,5 +19,20 @@ class GitCommitTaskTest extends Specification { then: gitCommit.descriptions == ["description"] gitCommit.filesToCommit == [f] + gitCommit.dependsOn.contains(task) + } + + def "enables adding changes to commit and null task"() { + def f = new File("foo") + def gitCommit = project.tasks.create("foo", GitCommitTask) + def numberOfDepended = gitCommit.dependsOn.size() + + when: + gitCommit.addChange([f], "description", null) + + then: + gitCommit.descriptions == ["description"] + gitCommit.filesToCommit == [f] + gitCommit.dependsOn.size() == numberOfDepended } } diff --git a/version.properties b/version.properties index ce1034a9..0b9bf961 100644 --- a/version.properties +++ b/version.properties @@ -1,6 +1,6 @@ #Version of the produced binaries. This file is intended to be checked-in. #It will be automatically bumped by release automation. -version=2.1.9 +version=2.2.0 #Last previous release version previousVersion=2.1.8