From 77cd5819ff1a54727ecfa11e1e73c52c99f29442 Mon Sep 17 00:00:00 2001 From: Andres Almiray Date: Wed, 21 Jul 2021 23:14:34 +0200 Subject: [PATCH] [brew] support the binary stanza in cask template. Resolves #300 --- .../model/validation/BrewValidator.java | 36 +++++++-- .../templates/binary/brew/cask.rb.tpl | 53 +++++++++++++ .../templates/java-binary/brew/cask.rb.tpl | 53 +++++++++++++ .../templates/jlink/brew/cask.rb.tpl | 53 +++++++++++++ .../templates/native-image/brew/cask.rb.tpl | 53 +++++++++++++ .../templates/native-package/brew/cask.rb.tpl | 3 + .../tools/AbstractToolProcessor.java | 2 +- .../jreleaser/tools/BrewToolProcessor.java | 75 ++++++++++++------- .../java/org/jreleaser/util/Constants.java | 1 + 9 files changed, 295 insertions(+), 34 deletions(-) create mode 100644 core/jreleaser-templates/src/main/resources/META-INF/jreleaser/templates/binary/brew/cask.rb.tpl create mode 100644 core/jreleaser-templates/src/main/resources/META-INF/jreleaser/templates/java-binary/brew/cask.rb.tpl create mode 100644 core/jreleaser-templates/src/main/resources/META-INF/jreleaser/templates/jlink/brew/cask.rb.tpl create mode 100644 core/jreleaser-templates/src/main/resources/META-INF/jreleaser/templates/native-image/brew/cask.rb.tpl diff --git a/core/jreleaser-model/src/main/java/org/jreleaser/model/validation/BrewValidator.java b/core/jreleaser-model/src/main/java/org/jreleaser/model/validation/BrewValidator.java index b4b186c3..54274544 100644 --- a/core/jreleaser-model/src/main/java/org/jreleaser/model/validation/BrewValidator.java +++ b/core/jreleaser-model/src/main/java/org/jreleaser/model/validation/BrewValidator.java @@ -27,6 +27,7 @@ import org.jreleaser.model.JReleaserContext; import org.jreleaser.model.JReleaserModel; import org.jreleaser.util.Env; import org.jreleaser.util.Errors; +import org.jreleaser.util.PlatformUtils; import java.util.ArrayList; import java.util.List; @@ -108,36 +109,51 @@ public abstract class BrewValidator extends Validator { } private static void validateCask(JReleaserContext context, Distribution distribution, Brew tool, Errors errors) { + if (distribution.getType() == Distribution.DistributionType.SINGLE_JAR) { + tool.getCask().disable(); + return; + } + context.getLogger().debug("distribution.{}.brew.cask", distribution.getName()); - // look for a .dmg o .pkg + // look for a .dmg, .pkg. or .zip int dmgFound = 0; int pkgFound = 0; + int zipFound = 0; String pkgName = ""; for (Artifact artifact : distribution.getArtifacts()) { - if (!artifact.isActive()) continue; - if (artifact.getPath().endsWith(".dmg") && !isTrue(artifact.getExtraProperties().get("skipBrew"))) + if (!artifact.isActive() || !PlatformUtils.isMac(artifact.getPlatform())) continue; + if (artifact.getPath().endsWith(".dmg") && !isTrue(artifact.getExtraProperties().get("skipBrew"))) { dmgFound++; - if (artifact.getPath().endsWith(".pkg") && !isTrue(artifact.getExtraProperties().get("skipBrew"))) { + } else if (artifact.getPath().endsWith(".pkg") && !isTrue(artifact.getExtraProperties().get("skipBrew"))) { pkgFound++; pkgName = artifact.getEffectivePath(context).getFileName().toString(); + } else if (artifact.getPath().endsWith(".zip") && !isTrue(artifact.getExtraProperties().get("skipBrew"))) { + zipFound++; } } Cask cask = tool.getCask(); - if (dmgFound == 0 && pkgFound == 0) { + if (dmgFound == 0 && pkgFound == 0 && zipFound == 0) { // no artifacts found, disable cask cask.disable(); return; - } else if (dmgFound > 0 && pkgFound > 0) { - errors.configuration("distribution." + distribution.getName() + ".brew can only have a single .dmg or .pkg artifact"); - return; } else if (dmgFound > 1) { errors.configuration("distribution." + distribution.getName() + ".brew has more than one .dmg artifact"); + cask.disable(); return; } else if (pkgFound > 1) { errors.configuration("distribution." + distribution.getName() + ".brew has more than one .pkg artifact"); + cask.disable(); + return; + } else if (zipFound > 1) { + errors.configuration("distribution." + distribution.getName() + ".brew has more than one .zip artifact"); + cask.disable(); + return; + } else if (dmgFound + pkgFound + zipFound > 1) { + errors.configuration("distribution." + distribution.getName() + ".brew can only have a single matching .dmg, .pkg, or .zip artifact"); + cask.disable(); return; } @@ -156,6 +172,10 @@ public abstract class BrewValidator extends Validator { } else if (!cask.getAppName().endsWith(".app")) { cask.setAppName(cask.getAppName() + ".app"); } + if (zipFound > 0) { + cask.setAppName(""); + cask.setPkgName(""); + } if (isBlank(cask.getName())) { cask.setName(tool.getResolvedFormulaName(context).toLowerCase()); diff --git a/core/jreleaser-templates/src/main/resources/META-INF/jreleaser/templates/binary/brew/cask.rb.tpl b/core/jreleaser-templates/src/main/resources/META-INF/jreleaser/templates/binary/brew/cask.rb.tpl new file mode 100644 index 00000000..7dffc661 --- /dev/null +++ b/core/jreleaser-templates/src/main/resources/META-INF/jreleaser/templates/binary/brew/cask.rb.tpl @@ -0,0 +1,53 @@ +cask "{{brewCaskName}}" do + version "{{projectVersion}}" + sha256 "{{distributionChecksumSha256}}" + + url "{{distributionUrl}}", + verified: "{{repoHost}}" + name "{{brewCaskDisplayName}}" + desc "{{projectDescription}}" + homepage "{{projectWebsite}}" + {{#brewCaskHasAppcast}} + appcast {{brewCaskAppcast}} + {{/brewCaskHasAppcast}} + auto_updates true + + {{#brewHasLivecheck}} + livecheck do + {{#brewLivecheck}} + {{.}} + {{/brewLivecheck}} + end + {{/brewHasLivecheck}} + {{#brewDependencies}} + depends_on {{.}} + {{/brewDependencies}} + + {{#brewCaskHasPkg}} + pkg "{{brewCaskPkg}}" + {{/brewCaskHasPkg}} + {{#brewCaskHasApp}} + app "{{brewCaskApp}}" + {{/brewCaskHasApp}} + {{#brewCaskHasBinary}} + binary "{{distributionArtifactName}}/bin/{{distributionExecutable}}" + {{/brewCaskHasBinary}} + {{#brewCaskHasUninstall}} + {{#brewCaskUninstall}} + uninstall {{name}}: [ + {{#items}} + "{{.}}", + {{/items}} + ] + {{/brewCaskUninstall}} + {{/brewCaskHasUninstall}} + {{#brewCaskHasZap}} + {{#brewCaskZap}} + zap {{name}}: [ + {{#items}} + "{{.}}", + {{/items}} + ] + {{/brewCaskZap}} + {{/brewCaskHasZap}} +end \ No newline at end of file diff --git a/core/jreleaser-templates/src/main/resources/META-INF/jreleaser/templates/java-binary/brew/cask.rb.tpl b/core/jreleaser-templates/src/main/resources/META-INF/jreleaser/templates/java-binary/brew/cask.rb.tpl new file mode 100644 index 00000000..7dffc661 --- /dev/null +++ b/core/jreleaser-templates/src/main/resources/META-INF/jreleaser/templates/java-binary/brew/cask.rb.tpl @@ -0,0 +1,53 @@ +cask "{{brewCaskName}}" do + version "{{projectVersion}}" + sha256 "{{distributionChecksumSha256}}" + + url "{{distributionUrl}}", + verified: "{{repoHost}}" + name "{{brewCaskDisplayName}}" + desc "{{projectDescription}}" + homepage "{{projectWebsite}}" + {{#brewCaskHasAppcast}} + appcast {{brewCaskAppcast}} + {{/brewCaskHasAppcast}} + auto_updates true + + {{#brewHasLivecheck}} + livecheck do + {{#brewLivecheck}} + {{.}} + {{/brewLivecheck}} + end + {{/brewHasLivecheck}} + {{#brewDependencies}} + depends_on {{.}} + {{/brewDependencies}} + + {{#brewCaskHasPkg}} + pkg "{{brewCaskPkg}}" + {{/brewCaskHasPkg}} + {{#brewCaskHasApp}} + app "{{brewCaskApp}}" + {{/brewCaskHasApp}} + {{#brewCaskHasBinary}} + binary "{{distributionArtifactName}}/bin/{{distributionExecutable}}" + {{/brewCaskHasBinary}} + {{#brewCaskHasUninstall}} + {{#brewCaskUninstall}} + uninstall {{name}}: [ + {{#items}} + "{{.}}", + {{/items}} + ] + {{/brewCaskUninstall}} + {{/brewCaskHasUninstall}} + {{#brewCaskHasZap}} + {{#brewCaskZap}} + zap {{name}}: [ + {{#items}} + "{{.}}", + {{/items}} + ] + {{/brewCaskZap}} + {{/brewCaskHasZap}} +end \ No newline at end of file diff --git a/core/jreleaser-templates/src/main/resources/META-INF/jreleaser/templates/jlink/brew/cask.rb.tpl b/core/jreleaser-templates/src/main/resources/META-INF/jreleaser/templates/jlink/brew/cask.rb.tpl new file mode 100644 index 00000000..7dffc661 --- /dev/null +++ b/core/jreleaser-templates/src/main/resources/META-INF/jreleaser/templates/jlink/brew/cask.rb.tpl @@ -0,0 +1,53 @@ +cask "{{brewCaskName}}" do + version "{{projectVersion}}" + sha256 "{{distributionChecksumSha256}}" + + url "{{distributionUrl}}", + verified: "{{repoHost}}" + name "{{brewCaskDisplayName}}" + desc "{{projectDescription}}" + homepage "{{projectWebsite}}" + {{#brewCaskHasAppcast}} + appcast {{brewCaskAppcast}} + {{/brewCaskHasAppcast}} + auto_updates true + + {{#brewHasLivecheck}} + livecheck do + {{#brewLivecheck}} + {{.}} + {{/brewLivecheck}} + end + {{/brewHasLivecheck}} + {{#brewDependencies}} + depends_on {{.}} + {{/brewDependencies}} + + {{#brewCaskHasPkg}} + pkg "{{brewCaskPkg}}" + {{/brewCaskHasPkg}} + {{#brewCaskHasApp}} + app "{{brewCaskApp}}" + {{/brewCaskHasApp}} + {{#brewCaskHasBinary}} + binary "{{distributionArtifactName}}/bin/{{distributionExecutable}}" + {{/brewCaskHasBinary}} + {{#brewCaskHasUninstall}} + {{#brewCaskUninstall}} + uninstall {{name}}: [ + {{#items}} + "{{.}}", + {{/items}} + ] + {{/brewCaskUninstall}} + {{/brewCaskHasUninstall}} + {{#brewCaskHasZap}} + {{#brewCaskZap}} + zap {{name}}: [ + {{#items}} + "{{.}}", + {{/items}} + ] + {{/brewCaskZap}} + {{/brewCaskHasZap}} +end \ No newline at end of file diff --git a/core/jreleaser-templates/src/main/resources/META-INF/jreleaser/templates/native-image/brew/cask.rb.tpl b/core/jreleaser-templates/src/main/resources/META-INF/jreleaser/templates/native-image/brew/cask.rb.tpl new file mode 100644 index 00000000..7dffc661 --- /dev/null +++ b/core/jreleaser-templates/src/main/resources/META-INF/jreleaser/templates/native-image/brew/cask.rb.tpl @@ -0,0 +1,53 @@ +cask "{{brewCaskName}}" do + version "{{projectVersion}}" + sha256 "{{distributionChecksumSha256}}" + + url "{{distributionUrl}}", + verified: "{{repoHost}}" + name "{{brewCaskDisplayName}}" + desc "{{projectDescription}}" + homepage "{{projectWebsite}}" + {{#brewCaskHasAppcast}} + appcast {{brewCaskAppcast}} + {{/brewCaskHasAppcast}} + auto_updates true + + {{#brewHasLivecheck}} + livecheck do + {{#brewLivecheck}} + {{.}} + {{/brewLivecheck}} + end + {{/brewHasLivecheck}} + {{#brewDependencies}} + depends_on {{.}} + {{/brewDependencies}} + + {{#brewCaskHasPkg}} + pkg "{{brewCaskPkg}}" + {{/brewCaskHasPkg}} + {{#brewCaskHasApp}} + app "{{brewCaskApp}}" + {{/brewCaskHasApp}} + {{#brewCaskHasBinary}} + binary "{{distributionArtifactName}}/bin/{{distributionExecutable}}" + {{/brewCaskHasBinary}} + {{#brewCaskHasUninstall}} + {{#brewCaskUninstall}} + uninstall {{name}}: [ + {{#items}} + "{{.}}", + {{/items}} + ] + {{/brewCaskUninstall}} + {{/brewCaskHasUninstall}} + {{#brewCaskHasZap}} + {{#brewCaskZap}} + zap {{name}}: [ + {{#items}} + "{{.}}", + {{/items}} + ] + {{/brewCaskZap}} + {{/brewCaskHasZap}} +end \ No newline at end of file diff --git a/core/jreleaser-templates/src/main/resources/META-INF/jreleaser/templates/native-package/brew/cask.rb.tpl b/core/jreleaser-templates/src/main/resources/META-INF/jreleaser/templates/native-package/brew/cask.rb.tpl index 5e0f8008..7dffc661 100644 --- a/core/jreleaser-templates/src/main/resources/META-INF/jreleaser/templates/native-package/brew/cask.rb.tpl +++ b/core/jreleaser-templates/src/main/resources/META-INF/jreleaser/templates/native-package/brew/cask.rb.tpl @@ -29,6 +29,9 @@ cask "{{brewCaskName}}" do {{#brewCaskHasApp}} app "{{brewCaskApp}}" {{/brewCaskHasApp}} + {{#brewCaskHasBinary}} + binary "{{distributionArtifactName}}/bin/{{distributionExecutable}}" + {{/brewCaskHasBinary}} {{#brewCaskHasUninstall}} {{#brewCaskUninstall}} uninstall {{name}}: [ diff --git a/core/jreleaser-tools/src/main/java/org/jreleaser/tools/AbstractToolProcessor.java b/core/jreleaser-tools/src/main/java/org/jreleaser/tools/AbstractToolProcessor.java index 94e03353..f497beb5 100644 --- a/core/jreleaser-tools/src/main/java/org/jreleaser/tools/AbstractToolProcessor.java +++ b/core/jreleaser-tools/src/main/java/org/jreleaser/tools/AbstractToolProcessor.java @@ -323,7 +323,7 @@ abstract class AbstractToolProcessor implements ToolProcessor } Map newProps = new LinkedHashMap<>(props); newProps.put(Constants.KEY_ARTIFACT_FILE_NAME, artifactFileName); - String artifactUrl = applyTemplate(context.getModel().getRelease().getGitService().getDownloadUrl(), newProps, "downloadUrl"); + String artifactUrl = applyTemplate(context.getModel().getRelease().getGitService().getDownloadUrl(), newProps); props.put("artifact" + platform + "Url", artifactUrl); props.putAll(context.getModel().getUpload() .resolveDownloadUrls(context, distribution, artifact, "artifact" + platform)); diff --git a/core/jreleaser-tools/src/main/java/org/jreleaser/tools/BrewToolProcessor.java b/core/jreleaser-tools/src/main/java/org/jreleaser/tools/BrewToolProcessor.java index 351530f2..21065f20 100644 --- a/core/jreleaser-tools/src/main/java/org/jreleaser/tools/BrewToolProcessor.java +++ b/core/jreleaser-tools/src/main/java/org/jreleaser/tools/BrewToolProcessor.java @@ -17,7 +17,9 @@ */ package org.jreleaser.tools; +import org.jreleaser.model.Artifact; import org.jreleaser.model.Brew; +import org.jreleaser.model.Cask; import org.jreleaser.model.Distribution; import org.jreleaser.model.GitService; import org.jreleaser.model.JReleaserContext; @@ -27,12 +29,14 @@ import org.jreleaser.util.Constants; import org.jreleaser.util.MustacheUtils; import java.nio.file.Path; +import java.util.LinkedHashMap; import java.util.Map; import java.util.stream.Collectors; import static org.jreleaser.templates.TemplateUtils.trimTplExtension; import static org.jreleaser.util.MustacheUtils.applyTemplate; import static org.jreleaser.util.MustacheUtils.passThrough; +import static org.jreleaser.util.StringUtils.getFilename; import static org.jreleaser.util.StringUtils.isNotBlank; import static org.jreleaser.util.StringUtils.isTrue; @@ -71,29 +75,44 @@ public class BrewToolProcessor extends AbstractRepositoryToolProcessor { .collect(Collectors.toList())); } - if ((distribution.getType() == Distribution.DistributionType.JAVA_BINARY || + Cask cask = tool.getCask(); + if (cask.isEnabled()) { + props.put(Constants.KEY_BREW_CASK_NAME, cask.getResolvedCaskName(props)); + props.put(Constants.KEY_BREW_CASK_DISPLAY_NAME, cask.getResolvedDisplayName(props)); + props.put(Constants.KEY_BREW_CASK_HAS_UNINSTALL, !cask.getUninstallItems().isEmpty()); + props.put(Constants.KEY_BREW_CASK_HAS_PKG, isNotBlank(cask.getPkgName())); + if (isNotBlank(cask.getPkgName())) { + props.put(Constants.KEY_BREW_CASK_PKG, cask.getResolvedPkgName(props)); + } + props.put(Constants.KEY_BREW_CASK_HAS_APP, isNotBlank(cask.getAppName())); + if (isNotBlank(cask.getAppName())) { + props.put(Constants.KEY_BREW_CASK_APP, cask.getResolvedAppName(props)); + } + props.put(Constants.KEY_BREW_CASK_UNINSTALL, cask.getUninstallItems()); + props.put(Constants.KEY_BREW_CASK_HAS_ZAP, !cask.getZapItems().isEmpty()); + props.put(Constants.KEY_BREW_CASK_ZAP, cask.getZapItems()); + String appcast = cask.getResolvedAppcast(props); + props.put(Constants.KEY_BREW_CASK_HAS_APPCAST, isNotBlank(appcast)); + props.put(Constants.KEY_BREW_CASK_APPCAST, appcast); + + for (Artifact artifact : distribution.getArtifacts()) { + if (!artifact.isActive()) continue; + if (artifact.getPath().endsWith(".zip") && !isTrue(artifact.getExtraProperties().get("skipBrew"))) { + String artifactFileName = artifact.getEffectivePath(context).getFileName().toString(); + Map newProps = new LinkedHashMap<>(props); + newProps.put(Constants.KEY_ARTIFACT_FILE_NAME, artifactFileName); + props.put(Constants.KEY_DISTRIBUTION_ARTIFACT_NAME, getFilename(artifactFileName)); + String artifactUrl = applyTemplate(context.getModel().getRelease().getGitService().getDownloadUrl(), newProps); + props.put(Constants.KEY_DISTRIBUTION_URL, artifactUrl); + props.put(Constants.KEY_BREW_CASK_HAS_BINARY, true); + break; + } + } + } else if ((distribution.getType() == Distribution.DistributionType.JAVA_BINARY || distribution.getType() == Distribution.DistributionType.SINGLE_JAR) && !isTrue(tool.getExtraProperties().get("javaSkip")) && !isTrue(tool.getExtraProperties().get("skipJava"))) { tool.addDependency("openjdk@" + props.get(Constants.KEY_DISTRIBUTION_JAVA_VERSION)); - } else if (distribution.getType() == Distribution.DistributionType.NATIVE_PACKAGE) { - props.put(Constants.KEY_BREW_CASK_NAME, tool.getCask().getResolvedCaskName(props)); - props.put(Constants.KEY_BREW_CASK_DISPLAY_NAME, tool.getCask().getResolvedDisplayName(props)); - props.put(Constants.KEY_BREW_CASK_HAS_UNINSTALL, !tool.getCask().getUninstallItems().isEmpty()); - props.put(Constants.KEY_BREW_CASK_HAS_PKG, isNotBlank(tool.getCask().getPkgName())); - if (isNotBlank(tool.getCask().getPkgName())) { - props.put(Constants.KEY_BREW_CASK_PKG, tool.getCask().getResolvedPkgName(props)); - } - props.put(Constants.KEY_BREW_CASK_HAS_APP, isNotBlank(tool.getCask().getAppName())); - if (isNotBlank(tool.getCask().getAppName())) { - props.put(Constants.KEY_BREW_CASK_APP, tool.getCask().getResolvedAppName(props)); - } - props.put(Constants.KEY_BREW_CASK_UNINSTALL, tool.getCask().getUninstallItems()); - props.put(Constants.KEY_BREW_CASK_HAS_ZAP, !tool.getCask().getZapItems().isEmpty()); - props.put(Constants.KEY_BREW_CASK_ZAP, tool.getCask().getZapItems()); - String appcast = tool.getCask().getResolvedAppcast(props); - props.put(Constants.KEY_BREW_CASK_HAS_APPCAST, isNotBlank(appcast)); - props.put(Constants.KEY_BREW_CASK_APPCAST, appcast); } props.put(Constants.KEY_BREW_DEPENDENCIES, tool.getDependenciesAsList() @@ -113,12 +132,18 @@ public class BrewToolProcessor extends AbstractRepositoryToolProcessor { throws ToolProcessingException { fileName = trimTplExtension(fileName); - Path outputFile = "formula.rb".equals(fileName) ? - outputDirectory.resolve("Formula").resolve(distribution.getExecutable().concat(".rb")) : - ("cask.rb".equals(fileName) ? + if (tool.getCask().isEnabled()) { + if ("formula.rb".equals(fileName)) return; + Path outputFile = "cask.rb".equals(fileName) ? outputDirectory.resolve("Casks").resolve(tool.getCask().getResolvedCaskName(props).concat(".rb")) : - outputDirectory.resolve(fileName)); - - writeFile(content, outputFile); + outputDirectory.resolve(fileName); + writeFile(content, outputFile); + } else { + if ("cask.rb".equals(fileName)) return; + Path outputFile = "formula.rb".equals(fileName) ? + outputDirectory.resolve("Formula").resolve(distribution.getExecutable().concat(".rb")) : + outputDirectory.resolve(fileName); + writeFile(content, outputFile); + } } } diff --git a/core/jreleaser-utils/src/main/java/org/jreleaser/util/Constants.java b/core/jreleaser-utils/src/main/java/org/jreleaser/util/Constants.java index fe01ef24..3ad4a974 100644 --- a/core/jreleaser-utils/src/main/java/org/jreleaser/util/Constants.java +++ b/core/jreleaser-utils/src/main/java/org/jreleaser/util/Constants.java @@ -136,6 +136,7 @@ public interface Constants { String KEY_BREW_CASK_ZAP = "brewCaskZap"; String KEY_BREW_CASK_HAS_APPCAST = "brewCaskHasAppcast"; String KEY_BREW_CASK_APPCAST = "brewCaskAppcast"; + String KEY_BREW_CASK_HAS_BINARY = "brewCaskHasBinary"; // Docker String KEY_DOCKER_SPEC_NAME = "dockerSpecName";