'
"
dv/'45co%!@Ⱦ##nP!;D*
\ No newline at end of file
diff --git a/projects/spring-cloud/src/test/resources/projects/spring-docs-actions/git/objects/f2/50c03491a1c322ce1b51e4ea2298711735ceeb b/projects/spring-cloud/src/test/resources/projects/spring-docs-actions/git/objects/f2/50c03491a1c322ce1b51e4ea2298711735ceeb
new file mode 100644
index 00000000..1808386d
Binary files /dev/null and b/projects/spring-cloud/src/test/resources/projects/spring-docs-actions/git/objects/f2/50c03491a1c322ce1b51e4ea2298711735ceeb differ
diff --git a/projects/spring-cloud/src/test/resources/projects/spring-docs-actions/git/objects/f7/eeae9068b3845a5f48ea04d11f169b2b8a7994 b/projects/spring-cloud/src/test/resources/projects/spring-docs-actions/git/objects/f7/eeae9068b3845a5f48ea04d11f169b2b8a7994
new file mode 100644
index 00000000..5cd7c5b3
Binary files /dev/null and b/projects/spring-cloud/src/test/resources/projects/spring-docs-actions/git/objects/f7/eeae9068b3845a5f48ea04d11f169b2b8a7994 differ
diff --git a/projects/spring-cloud/src/test/resources/projects/spring-docs-actions/git/objects/f8/41901875c78a360d73fd6e1fc1dc1c77c9a993 b/projects/spring-cloud/src/test/resources/projects/spring-docs-actions/git/objects/f8/41901875c78a360d73fd6e1fc1dc1c77c9a993
new file mode 100644
index 00000000..d9286f36
Binary files /dev/null and b/projects/spring-cloud/src/test/resources/projects/spring-docs-actions/git/objects/f8/41901875c78a360d73fd6e1fc1dc1c77c9a993 differ
diff --git a/projects/spring-cloud/src/test/resources/projects/spring-docs-actions/git/refs/heads/main b/projects/spring-cloud/src/test/resources/projects/spring-docs-actions/git/refs/heads/main
new file mode 100644
index 00000000..94153cac
--- /dev/null
+++ b/projects/spring-cloud/src/test/resources/projects/spring-docs-actions/git/refs/heads/main
@@ -0,0 +1 @@
+018554f12b64fc2fb8a0ea306455c8d0da30b891
diff --git a/projects/spring-cloud/src/test/resources/projects/spring-docs-actions/git/refs/tags/v0.0.16 b/projects/spring-cloud/src/test/resources/projects/spring-docs-actions/git/refs/tags/v0.0.16
new file mode 100644
index 00000000..54306abd
--- /dev/null
+++ b/projects/spring-cloud/src/test/resources/projects/spring-docs-actions/git/refs/tags/v0.0.16
@@ -0,0 +1 @@
+aef500da0cf73a881df5e7d7ddf0d6533d5f2610
diff --git a/projects/spring-cloud/src/test/resources/projects/spring-docs-actions/rsync-antora-reference/src/action.sh b/projects/spring-cloud/src/test/resources/projects/spring-docs-actions/rsync-antora-reference/src/action.sh
new file mode 100755
index 00000000..f250c034
--- /dev/null
+++ b/projects/spring-cloud/src/test/resources/projects/spring-docs-actions/rsync-antora-reference/src/action.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+set -e
+set -f
+
+setup_ssh.sh
+
+echo "Synced docs"
+echo 'Synced docs' > /tmp/executed_docs
+
+exit_code=$?
+
+exit $exit_code
diff --git a/projects/spring-cloud/src/test/resources/projects/spring-docs-actions/rsync-antora-reference/src/setup_ssh.sh b/projects/spring-cloud/src/test/resources/projects/spring-docs-actions/rsync-antora-reference/src/setup_ssh.sh
new file mode 100755
index 00000000..5cea1b50
--- /dev/null
+++ b/projects/spring-cloud/src/test/resources/projects/spring-docs-actions/rsync-antora-reference/src/setup_ssh.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+echo "Setup ssh"
diff --git a/projects/spring-cloud/src/test/resources/spring-docs-action-runner.sh b/projects/spring-cloud/src/test/resources/spring-docs-action-runner.sh
new file mode 100755
index 00000000..f108c2be
--- /dev/null
+++ b/projects/spring-cloud/src/test/resources/spring-docs-action-runner.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+# Get the current directory
+current_dir=$(pwd)
+
+# Add the current directory to the PATH variable
+export PATH=$PATH:$current_dir
+
+action.sh "$@"
diff --git a/releaser-core/src/main/java/releaser/internal/Releaser.java b/releaser-core/src/main/java/releaser/internal/Releaser.java
index 3dadae76..f52f60b2 100644
--- a/releaser-core/src/main/java/releaser/internal/Releaser.java
+++ b/releaser-core/src/main/java/releaser/internal/Releaser.java
@@ -97,6 +97,15 @@ public class Releaser {
return this.projectGitHandler.cloneProjectFromOrg(projectName);
}
+ public ExecutionResult buildAntoraDocs(File project) {
+ String currentBranch = projectGitHandler.currentBranch(project);
+ projectGitHandler.cloneAndCheckoutDocsBuild(project);
+ this.projectCommandExecutor.runAntora(this.releaserProperties, originalVersion(project),
+ new ProjectVersion(project), project.getAbsolutePath());
+ projectGitHandler.checkout(project, currentBranch);
+ return ExecutionResult.success();
+ }
+
public Projects retrieveVersionsFromBom() {
return this.projectPomUpdater.retrieveVersionsFromReleaseTrainBom();
}
@@ -129,6 +138,12 @@ public class Releaser {
return ExecutionResult.success();
}
+ public ExecutionResult runAntoraBuild(ReleaserProperties properties, ProjectVersion originalVersion,
+ ProjectVersion versionFromBom) {
+ this.projectCommandExecutor.runAntora(properties, originalVersion, versionFromBom, properties.getWorkingDir());
+ return ExecutionResult.success();
+ }
+
public ExecutionResult commitAndPushTags(File project, ProjectVersion changedVersion) {
this.projectGitHandler.commitAndTagIfApplicable(project, changedVersion);
log.info("\nCommit was made and tag was pushed successfully");
@@ -142,9 +157,9 @@ public class Releaser {
return ExecutionResult.success();
}
- public ExecutionResult publishDocs(ReleaserProperties properties, ProjectVersion originalVersion,
- ProjectVersion changedVersion) {
- this.projectCommandExecutor.publishDocs(properties, originalVersion, changedVersion);
+ public ExecutionResult publishDocs(ReleaserProperties properties, File project) {
+ File springDocsActionsProject = this.projectGitHandler.cloneAndCheckoutSpringDocsActions();
+ this.projectCommandExecutor.publishAntoraDocs(springDocsActionsProject, project, properties);
log.info("\nThe docs were published successfully");
return ExecutionResult.success();
}
diff --git a/releaser-core/src/main/java/releaser/internal/ReleaserProperties.java b/releaser-core/src/main/java/releaser/internal/ReleaserProperties.java
index aff6b89f..195199e7 100644
--- a/releaser-core/src/main/java/releaser/internal/ReleaserProperties.java
+++ b/releaser-core/src/main/java/releaser/internal/ReleaserProperties.java
@@ -78,6 +78,8 @@ public class ReleaserProperties implements Serializable {
private Versions versions = new Versions();
+ private Antora antora = new Antora();
+
private boolean commercial = false;
private Bundles bundles = new Bundles();
@@ -210,6 +212,14 @@ public class ReleaserProperties implements Serializable {
this.commercial = commercial;
}
+ public Antora getAntora() {
+ return antora;
+ }
+
+ public void setAntora(Antora antora) {
+ this.antora = antora;
+ }
+
public Bundles getBundles() {
return bundles;
}
@@ -224,7 +234,7 @@ public class ReleaserProperties implements Serializable {
+ this.pom + ", maven=" + this.maven + ", gradle=" + this.gradle + ", sagan=" + this.sagan
+ ", fixedVersions=" + this.fixedVersions + ", metaRelease=" + this.metaRelease + ", template="
+ this.template + ", versions=" + this.versions + ", commercial=" + this.commercial + ", bundles="
- + this.bundles + '}';
+ + this.bundles + ", antora=" + this.antora + '}';
}
public ReleaserProperties copy() {
@@ -447,6 +457,87 @@ public class ReleaserProperties implements Serializable {
}
+ public static class Antora implements Serializable {
+
+ /**
+ * URL to Spring Docs Actions repo.
+ */
+ private String springDocsActionsUrl;
+
+ /**
+ * Command to sync Antora docs.
+ */
+ private String syncAntoraDocsCommand;
+
+ /**
+ * Tag for Spring Docs Actions repo.
+ */
+ private String springDocsActionsTag;
+
+ private String springDocsSshUsername;
+
+ private String springDocsSshKeyPath;
+
+ private String springDocsSshHostKey;
+
+ public String getSpringDocsActionsUrl() {
+ return springDocsActionsUrl;
+ }
+
+ public void setSpringDocsActionsUrl(String springDocsActionsUrl) {
+ this.springDocsActionsUrl = springDocsActionsUrl;
+ }
+
+ public String getSpringDocsActionsTag() {
+ return springDocsActionsTag;
+ }
+
+ public void setSpringDocsActionsTag(String springDocsActionsTag) {
+ this.springDocsActionsTag = springDocsActionsTag;
+ }
+
+ public String getSyncAntoraDocsCommand() {
+ return syncAntoraDocsCommand;
+ }
+
+ public void setSyncAntoraDocsCommand(String syncAntoraDocsCommand) {
+ this.syncAntoraDocsCommand = syncAntoraDocsCommand;
+ }
+
+ public String getSpringDocsSshUsername() {
+ return springDocsSshUsername;
+ }
+
+ public void setSpringDocsSshUsername(String springDocsSshUsername) {
+ this.springDocsSshUsername = springDocsSshUsername;
+ }
+
+ public String getSpringDocsSshKeyPath() {
+ return springDocsSshKeyPath;
+ }
+
+ public void setSpringDocsSshKeyPath(String springDocsSshKeyPath) {
+ this.springDocsSshKeyPath = springDocsSshKeyPath;
+ }
+
+ public String getSpringDocsSshHostKey() {
+ return springDocsSshHostKey;
+ }
+
+ public void setSpringDocsSshHostKey(String springDocsSshHostKey) {
+ this.springDocsSshHostKey = springDocsSshHostKey;
+ }
+
+ @Override
+ public String toString() {
+ return "Antora{" + "springDocsActionsUrl='" + springDocsActionsUrl + '\'' + ", syncAntoraDocsCommand='"
+ + syncAntoraDocsCommand + '\'' + ", springDocsActionsTag='" + springDocsActionsTag + '\''
+ + ", springDocsSshUsername='" + springDocsSshUsername + '\'' + ", springDocsSshKey='"
+ + springDocsSshKeyPath + '\'' + ", springDocsSshHostKey='" + springDocsSshHostKey + '\'' + '}';
+ }
+
+ }
+
public static class Git implements Serializable {
/**
@@ -1032,6 +1123,11 @@ public class ReleaserProperties implements Serializable {
private String generateReleaseTrainDocsCommand = "bash release_train.sh "
+ "--retrieveversions --version {{version}} --ghpages --auto";
+ /**
+ * Command to be executed to run Antora.
+ */
+ private String runAntoraCommand = "./mvnw antora -Pdocs {{systemProps}}";
+
/**
* Additional system properties that should be passed to the build / deploy
* commands. If present in other commands "{{systemProps}}" will be substituted
@@ -1112,12 +1208,20 @@ public class ReleaserProperties implements Serializable {
this.systemProperties = systemProperties;
}
+ public String getRunAntoraCommand() {
+ return runAntoraCommand;
+ }
+
+ public void setRunAntoraCommand(String runAntoraCommand) {
+ this.runAntoraCommand = runAntoraCommand;
+ }
+
@Override
public String toString() {
return "Maven{" + "buildCommand='" + this.buildCommand + '\'' + ", deployCommand='" + this.deployCommand
+ '\'' + ", publishDocsCommand=" + this.publishDocsCommand + "generateReleaseTrainDocsCommand='"
- + this.generateReleaseTrainDocsCommand + '\'' + ", waitTimeInMinutes=" + this.waitTimeInMinutes
- + '}';
+ + this.generateReleaseTrainDocsCommand + '\'' + ", runAntoraCommand= " + runAntoraCommand
+ + ", waitTimeInMinutes=" + this.waitTimeInMinutes + '}';
}
}
@@ -1327,6 +1431,11 @@ public class ReleaserProperties implements Serializable {
*/
private long waitTimeInMinutes = 20;
+ /**
+ * Command to be executed to run Antora.
+ */
+ private String runAntoraCommand = "./gradlew antora {{systemProps}}";
+
@Override
public String getBuildCommand() {
return this.buildCommand;
@@ -1411,6 +1520,14 @@ public class ReleaserProperties implements Serializable {
this.ignoredGradleRegex = ignoredGradleRegex;
}
+ public String getRunAntoraCommand() {
+ return runAntoraCommand;
+ }
+
+ public void setRunAntoraCommand(String runAntoraCommand) {
+ this.runAntoraCommand = runAntoraCommand;
+ }
+
@Override
public String toString() {
return new StringJoiner(", ", Gradle.class.getSimpleName() + "[", "]")
@@ -1420,6 +1537,7 @@ public class ReleaserProperties implements Serializable {
.add("deployGuidesCommand='" + deployGuidesCommand + "'")
.add("publishDocsCommand=" + publishDocsCommand)
.add("generateReleaseTrainDocsCommand='" + generateReleaseTrainDocsCommand + "'")
+ .add("runAntoraCommand='" + runAntoraCommand + "'")
.add("systemProperties='" + systemProperties + "'").add("waitTimeInMinutes=" + waitTimeInMinutes)
.toString();
}
diff --git a/releaser-core/src/main/java/releaser/internal/git/GitRepo.java b/releaser-core/src/main/java/releaser/internal/git/GitRepo.java
index 49096bf2..3be1842d 100644
--- a/releaser-core/src/main/java/releaser/internal/git/GitRepo.java
+++ b/releaser-core/src/main/java/releaser/internal/git/GitRepo.java
@@ -184,6 +184,17 @@ class GitRepo {
}
}
+ void checkoutTag(String tagName) {
+ try (Git git = this.gitFactory.open(file(this.basedir))) {
+ ObjectId tagId = findTagIdByName(tagName, false)
+ .orElseThrow(() -> new IllegalStateException("Tag with name [" + tagName + "] not found"));
+ git.checkout().setName(tagId.getName()).call();
+ }
+ catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
/**
* Attempt to retrieve a tag id from a name, prepending the name with /refs/tags/.
*/
diff --git a/releaser-core/src/main/java/releaser/internal/git/ProjectGitHandler.java b/releaser-core/src/main/java/releaser/internal/git/ProjectGitHandler.java
index fcdf3eb8..618b1ed0 100644
--- a/releaser-core/src/main/java/releaser/internal/git/ProjectGitHandler.java
+++ b/releaser-core/src/main/java/releaser/internal/git/ProjectGitHandler.java
@@ -130,6 +130,20 @@ public class ProjectGitHandler implements Closeable {
this.properties.getGit().getSpringProjectBranch());
}
+ public void cloneAndCheckoutDocsBuild(File project) {
+ checkout(project, "docs-build");
+ }
+
+ public File cloneAndCheckoutSpringDocsActions() {
+ File project = cloneProject(this.properties.getAntora().getSpringDocsActionsUrl());
+ String tag = this.properties.getAntora().getSpringDocsActionsTag();
+ if (StringUtils.hasText(tag)) {
+ log.info("Checking out tag [{}] for project [{}]", tag, project.getAbsolutePath());
+ checkoutTag(project, this.properties.getAntora().getSpringDocsActionsTag());
+ }
+ return project;
+ }
+
private File cloneAndCheckOut(String springProjectUrl, String springProjectUrlBranch) {
File clonedProject = cloneProject(springProjectUrl);
checkout(clonedProject, springProjectUrlBranch);
@@ -146,12 +160,7 @@ public class ProjectGitHandler implements Closeable {
* @return location of the cloned project
*/
public File cloneProjectFromOrg(String projectName) {
- String orgUrl = this.properties.getMetaRelease().getGitOrgUrl();
- String fullUrl = orgUrl.endsWith("/") ? (orgUrl + projectName)
- : (orgUrl + "/" + addCommercialSuffix(projectName) + suffixNonHttpRepo(orgUrl));
- if (log.isDebugEnabled()) {
- log.debug("Full url of the project is [{}]", fullUrl);
- }
+ String fullUrl = createRepoUrlFromProject(projectName);
File clonedProject = cloneProject(fullUrl);
if (log.isDebugEnabled()) {
log.debug("Successfully cloned the project to [{}]", clonedProject);
@@ -192,6 +201,16 @@ public class ProjectGitHandler implements Closeable {
return findAndCheckOutBranchForVersion(clonedProject, versions);
}
+ private String createRepoUrlFromProject(String projectName) {
+ String orgUrl = this.properties.getMetaRelease().getGitOrgUrl();
+ String fullUrl = orgUrl.endsWith("/") ? (orgUrl + projectName)
+ : (orgUrl + "/" + addCommercialSuffix(projectName) + suffixNonHttpRepo(orgUrl));
+ if (log.isDebugEnabled()) {
+ log.debug("Full url of the project is [{}]", fullUrl);
+ }
+ return fullUrl;
+ }
+
private File findAndCheckOutBranchForVersion(File clonedProject, String[] versions) {
if (log.isDebugEnabled()) {
log.debug("Checking versions {} for project [{}]", versions, clonedProject);
@@ -271,6 +290,11 @@ public class ProjectGitHandler implements Closeable {
return new File(destinationFolder, projectUrl.getHumanishName());
}
+ public void checkoutTag(File project, String tag) {
+ log.info("checkout tag: " + tag);
+ gitRepo(project).checkoutTag(tag);
+ }
+
public void checkout(File project, String branch) {
log.info("checkout project: " + project + " with branch: " + branch);
gitRepo(project).checkout(branch);
diff --git a/releaser-core/src/main/java/releaser/internal/project/ProjectCommandExecutor.java b/releaser-core/src/main/java/releaser/internal/project/ProjectCommandExecutor.java
index 050600d5..97984d78 100644
--- a/releaser-core/src/main/java/releaser/internal/project/ProjectCommandExecutor.java
+++ b/releaser-core/src/main/java/releaser/internal/project/ProjectCommandExecutor.java
@@ -37,6 +37,7 @@ import org.slf4j.LoggerFactory;
import releaser.internal.ReleaserProperties;
import releaser.internal.tech.ReleaserProcessExecutor;
+import org.springframework.core.io.ClassPathResource;
import org.springframework.util.StringUtils;
/**
@@ -52,6 +53,13 @@ public class ProjectCommandExecutor {
private static final String NEXT_VERSION_MUSTACHE = "{{nextVersion}}";
+ private static final String RSYNC_ACTIONS_PROJECT_DIR = "/rsync-antora-reference/src";
+
+ private static final String SPRING_DOCS_ACTION_RUNNER = "spring-docs-action-runner.sh";
+
+ private static final String RUNNER_DESTINATION = RSYNC_ACTIONS_PROJECT_DIR + File.separator
+ + SPRING_DOCS_ACTION_RUNNER;
+
public void build(ReleaserProperties properties, ProjectVersion originalVersion,
ProjectVersion versionFromReleaseTrain) {
build(properties, originalVersion, versionFromReleaseTrain, properties.getWorkingDir());
@@ -96,6 +104,19 @@ public class ProjectCommandExecutor {
}
}
+ public void runAntora(ReleaserProperties properties, ProjectVersion originalVersion,
+ ProjectVersion versionFromReleaseTrain, String projectRoot) {
+ try {
+ String command = new CommandPicker(properties, projectRoot).runAntoraCommand(versionFromReleaseTrain);
+ String[] commands = replaceAllPlaceHolders(originalVersion, versionFromReleaseTrain, command).split(" ");
+ runCommand(properties, projectRoot, commands);
+ }
+ catch (Exception e) {
+ String message = properties + "\n" + originalVersion + "\n" + versionFromReleaseTrain + "\n" + projectRoot;
+ throw new IllegalStateException(message, e);
+ }
+ }
+
public void generateReleaseTrainDocs(ReleaserProperties properties, String version, String projectRoot) {
try {
String updatedCommand = new CommandPicker(properties, projectRoot)
@@ -166,6 +187,34 @@ public class ProjectCommandExecutor {
return new ReleaserProcessExecutor(workDir);
}
+ public void publishAntoraDocs(File antoraDocsProject, File project, ReleaserProperties properties) {
+ try {
+ copyRunnerToActions(antoraDocsProject);
+ String command = new CommandPicker(properties).publishAntoraDocsCommand(project, properties);
+ log.info("Executing command for publishing Antora docs " + command + " / " + properties);
+ String[] commands = command.split(" ");
+ for (int i = 0; i < commands.length; i++) {
+ if (commands[i].contains("{{host-key}}")) {
+ commands[i] = commands[i].replace("{{host-key}}",
+ "\"" + properties.getAntora().getSpringDocsSshHostKey()) + "\"";
+ }
+ }
+ runCommand(properties, antoraDocsProject.getAbsolutePath() + RSYNC_ACTIONS_PROJECT_DIR, commands);
+ }
+ catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ public void copyRunnerToActions(File antoraDocsProject) throws IOException {
+ File destination = new File(antoraDocsProject.getAbsolutePath() + RUNNER_DESTINATION);
+ if (!destination.exists()) {
+ ClassPathResource runner = new ClassPathResource(SPRING_DOCS_ACTION_RUNNER);
+ Files.copy(runner.getInputStream(), destination.toPath());
+ destination.setExecutable(true);
+ }
+ }
+
public void publishDocs(ReleaserProperties properties, ProjectVersion originalVersion,
ProjectVersion changedVersion) {
try {
@@ -307,6 +356,30 @@ class CommandPicker {
return bashCommandWithSystemProps(releaserProperties.getBash().getBuildCommand());
}
+ String runAntoraCommand(ProjectVersion version) {
+ if (projectType == ProjectType.GRADLE) {
+ return gradleCommandWithSystemProps(releaserProperties.getGradle().getRunAntoraCommand());
+ }
+ return mavenCommandWithSystemProps(releaserProperties.getMaven().getRunAntoraCommand(), version);
+ }
+
+ String publishAntoraDocsCommand(File project, ReleaserProperties properties) {
+ ProjectVersion version = new ProjectVersion(project);
+ // the GitHub project for spring-cloud-starter-build is spring-cloud-release
+ String projectName = version.projectName.equals("spring-cloud-starter-build") ? "spring-cloud-release"
+ : version.projectName;
+ String repo = properties.getGit().getOrgName() + "/" + projectName;
+ String command = properties.getAntora().getSyncAntoraDocsCommand().replace("{{github-repo}}", repo)
+ .replace("{{site-path}}", project.getAbsolutePath() + "/target/antora/site");
+ if (StringUtils.hasText(properties.getAntora().getSpringDocsSshUsername())) {
+ command = command.replace("{{ssh-username}}", properties.getAntora().getSpringDocsSshUsername());
+ }
+ if (StringUtils.hasText(properties.getAntora().getSpringDocsSshKeyPath())) {
+ command = command.replace("{{ssh-key-path}}", properties.getAntora().getSpringDocsSshKeyPath());
+ }
+ return command;
+ }
+
String version() {
// makes more sense to use PomReader
if (projectType == ProjectType.GRADLE) {
diff --git a/releaser-core/src/main/resources/spring-docs-action-runner.sh b/releaser-core/src/main/resources/spring-docs-action-runner.sh
new file mode 100755
index 00000000..658d89c8
--- /dev/null
+++ b/releaser-core/src/main/resources/spring-docs-action-runner.sh
@@ -0,0 +1,123 @@
+#!/bin/bash
+set -e
+set -f
+
+# Get the current directory
+current_dir=$(pwd)
+
+# Add the current directory to the PATH variable
+export PATH=$PATH:$current_dir
+
+__action_usage() {
+ echo "usage: action.sh [OPTION]...
+
+ --docs-username=USERNAME the username used to connect to ssh
+ --docs-host=HOST the host to connect to ssh
+ --docs-ssh-key-path=KEY the path to the private key used to connect to ssh
+ --docs-ssh-host-key=HOST_KEY the host key used to connect to ssh
+ --dry-run signals that rsync should be in dry run mode
+ --site-path=PATH the local directory path to sync to the server. Default build/site
+ --github-repository=GH_REPO the github repository (e.g. spring-projects/spring-security)
+ --httpdocs-path=PATH the optional base httpdocs path (e.g. https://docs.spring.io/spring-security/reference would be /spring-security/reference)
+ If this is set, then the project must own the directory by ensuring to have a .github-repository file with the
+