IkeGoal.java
package network.ike.plugin;
import network.ike.plugin.support.GoalRef;
import network.ike.support.enums.ConstantBackedEnum;
import org.apache.maven.api.plugin.Mojo;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
/**
* Compile-time identity for every {@code ike:*} goal in this plugin. Each
* value wraps the bare goal name, the mojo class that implements it, and
* a short human description. Draft/publish siblings expose each other
* through {@link #pair()}.
*
* <p>Parallels {@code network.ike.plugin.ws.WsGoal} in the ws plugin.
* Callers that invoke ike goals from Java — for subprocess exec, for
* report identification, for javadoc examples that survive a rename —
* should reference these enum values rather than string literals.
*
* <p>Implements {@link ConstantBackedEnum}: each constant is paired with
* a {@code public static final String NAME_*} mirror, and class-load
* verification keeps the two in lockstep. The mirror is a constant
* expression, so the {@code @Mojo(name = IkeGoal.NAME_*)} annotation can
* reference the enum as its single source of truth.
*
* <p>See issues #166 and #453.
*/
public enum IkeGoal implements GoalRef, ConstantBackedEnum {
/** {@code ike:cascade-export} — export the release cascade topology for CI. */
CASCADE_EXPORT(IkeGoal.NAME_CASCADE_EXPORT, IkeCascadeExportMojo.class,
"Export the foundation release cascade topology as JSON "
+ "or .properties so a CI meta-runner can generate "
+ "build-chain edges from release-cascade.yaml "
+ "instead of hand-wiring them."),
/** {@code ike:central-status} — report async Maven Central deploy state (#484). */
CENTRAL_STATUS(IkeGoal.NAME_CENTRAL_STATUS, CentralStatusMojo.class,
"Report the status of asynchronous Maven Central deploys "
+ "spawned by ike:release-publish "
+ "-Dike.deploy.central.async=true. Walks the "
+ "sentinel cache (~/.cache/ike-release/) and "
+ "reports state, attempts, and log paths."),
/** {@code ike:codesign-natives} — sign macOS native binaries in a runtime image. */
CODESIGN_NATIVES(IkeGoal.NAME_CODESIGN_NATIVES, CodesignNativesMojo.class,
"Sign macOS native libraries and executables inside a runtime image."),
/** {@code ike:codesign-pkg} — sign a {@code .pkg} installer with Developer ID. */
CODESIGN_PKG(IkeGoal.NAME_CODESIGN_PKG, CodesignPkgMojo.class,
"Sign a .pkg installer with a Developer ID Installer certificate."),
/** {@code ike:env} — print runtime environment / terminal diagnostics. */
ENV(IkeGoal.NAME_ENV, IkeEnvMojo.class,
"Print runtime environment diagnostics — terminal/console "
+ "capability, stdin, and relevant system properties. "
+ "Run from both IntelliJ's Maven tool window and the "
+ "Terminal tool window to compare (ike-issues#385)."),
/** {@code ike:generate-bom} — generate the auto-managed BOM. */
GENERATE_BOM(IkeGoal.NAME_GENERATE_BOM, GenerateBomMojo.class,
"Generate the auto-managed BOM from the current dependencyManagement."),
/** {@code ike:help} — list {@code ike:*} goals from the plugin descriptor. */
HELP(IkeGoal.NAME_HELP, IkeHelpMojo.class,
"List ike:* goals discovered from the plugin descriptor."),
/** {@code ike:inject-breadcrumb} — inject breadcrumbs into rendered HTML. */
INJECT_BREADCRUMB(IkeGoal.NAME_INJECT_BREADCRUMB, InjectBreadcrumbMojo.class,
"Inject breadcrumb navigation into rendered HTML."),
/** {@code ike:inject-javadoc-theme} — overlay the IKE green stylesheet on generated Javadoc apidocs. */
INJECT_JAVADOC_THEME(IkeGoal.NAME_INJECT_JAVADOC_THEME,
InjectJavadocThemeMojo.class,
"Overlay the IKE green stylesheet onto generated Javadoc apidocs."),
/** {@code ike:jpackage-props} — emit jpackage properties from reactor config. */
JPACKAGE_PROPS(IkeGoal.NAME_JPACKAGE_PROPS, JpackagePropsMojo.class,
"Emit jpackage properties files from reactor configuration."),
/** {@code ike:knowledge-bindings} — generate a knowledge set's bindings class. */
KNOWLEDGE_BINDINGS(IkeGoal.NAME_KNOWLEDGE_BINDINGS, KnowledgeBindingsMojo.class,
"Generate the bindings class for a ledger-form knowledge set: "
+ "discovers the project's KnowledgeSetSource on its dependency "
+ "classpath, composes it, writes the TinkarTerm-idiom "
+ "constants class into generated-sources, and registers "
+ "the source root (ike-issues#824)."),
/** {@code ike:knowledge-export} — export a knowledge set's protobuf change set. */
KNOWLEDGE_EXPORT(IkeGoal.NAME_KNOWLEDGE_EXPORT, KnowledgeExportMojo.class,
"Export a ledger-form knowledge set as its protobuf change-set "
+ "artifact: composes the project's KnowledgeSetSource, "
+ "replays into a fresh ephemeral store, exports the store, "
+ "and attaches the file as the changeset classifier "
+ "(ike-issues#824)."),
/** {@code ike:notarize} — submit a {@code .pkg}/{@code .app} to Apple notary. */
NOTARIZE(IkeGoal.NAME_NOTARIZE, NotarizeMojo.class,
"Submit a .pkg or .app to Apple notary service and staple the ticket."),
/** {@code ike:release-draft} — preview releasing the current project. */
RELEASE_DRAFT(IkeGoal.NAME_RELEASE_DRAFT, ReleaseDraftMojo.class,
"Preview releasing the current project."),
/** {@code ike:release-publish} — release the current project (tag + publish). */
RELEASE_PUBLISH(IkeGoal.NAME_RELEASE_PUBLISH, ReleasePublishMojo.class,
"Release the current project (tag + publish)."),
/** {@code ike:release-cascade} — release the whole foundation cascade in order. */
RELEASE_CASCADE(IkeGoal.NAME_RELEASE_CASCADE, IkeReleaseCascadeMojo.class,
"Walk the decentralized release cascade assembled from "
+ "the per-project release-cascade.yaml manifests "
+ "and run ike:release-publish on every foundation "
+ "repo that has unreleased changes, in topological "
+ "order."),
/** {@code ike:release-changelog} — render a release changelog for CI notifications (#699). */
RELEASE_CHANGELOG(IkeGoal.NAME_RELEASE_CHANGELOG, IkeReleaseChangelogMojo.class,
"Render a 'What's changed' changelog from the commits in a "
+ "release range — machinery filtered, each entry "
+ "annotated with its full owner/repo#N issue refs — "
+ "for a CI release notification to consume."),
/** {@code ike:rename} — rename output files to a canonical pattern. */
RENAME(IkeGoal.NAME_RENAME, RenameMojo.class,
"Rename output files to a canonical pattern."),
/** {@code ike:built-with} — generate a Built With page from the SBOM and a curated supplement (#336). */
BUILT_WITH(IkeGoal.NAME_BUILT_WITH, BuiltWithMojo.class,
"Generate a curated Built-With page from the CycloneDX "
+ "SBOM and an optional project-wide supplement "
+ "YAML. Replaces the legacy 'Third-Party Notices' "
+ "naming with a friendlier scannable label and "
+ "supports per-module rendering by walking up "
+ "the filesystem to find the reactor's "
+ "supplement.yaml."),
/** {@code ike:render-sbom-viewer} — generate dependencies.adoc from the CycloneDX SBOM (#341). */
RENDER_SBOM_VIEWER(IkeGoal.NAME_RENDER_SBOM_VIEWER, RenderSbomViewerMojo.class,
"Generate a Web-friendly dependencies.adoc page from "
+ "the CycloneDX SBOM with a sortable component "
+ "table. Maven Site renders it to "
+ "dependencies.html, replacing the auto-"
+ "generated dependency report."),
/** {@code ike:render-spdx-licenses} — generate licenses.adoc from the CycloneDX SBOM (#335). */
RENDER_SPDX_LICENSES(IkeGoal.NAME_RENDER_SPDX_LICENSES, RenderSpdxLicensesMojo.class,
"Generate an SPDX-grouped licenses.adoc page from the "
+ "CycloneDX SBOM. Maven Site renders it to "
+ "licenses.html with the project skin chrome."),
/** {@code ike:scaffold-draft} — preview ike-build-standards scaffold changes. */
SCAFFOLD_DRAFT(IkeGoal.NAME_SCAFFOLD_DRAFT, ScaffoldDraftMojo.class,
"Preview what ike:scaffold-publish would apply from the "
+ "ike-build-standards scaffold."),
/** {@code ike:scaffold-publish} — apply the scaffold to disk. */
SCAFFOLD_PUBLISH(IkeGoal.NAME_SCAFFOLD_PUBLISH, ScaffoldPublishMojo.class,
"Apply the ike-build-standards scaffold to disk and "
+ "update per-project and per-user lockfiles."),
/** {@code ike:scaffold-revert} — undo a previous scaffold-publish. */
SCAFFOLD_REVERT(IkeGoal.NAME_SCAFFOLD_REVERT, ScaffoldRevertMojo.class,
"Undo a previous ike:scaffold-publish, leaving "
+ "user-edited files alone."),
/** {@code ike:site-draft} — report deployed-site drift (#398). */
SITE_DRAFT(IkeGoal.NAME_SITE_DRAFT, IkeSiteDraftMojo.class,
"Report drift in deployed-site state — version on "
+ "server vs current project version, landing-page "
+ "registration status — with copy-paste opt-out "
+ "commands inline."),
/** {@code ike:site-publish} — apply deployed-site convergence (#398). */
SITE_PUBLISH(IkeGoal.NAME_SITE_PUBLISH, IkeSitePublishMojo.class,
"Deploy the current version to gh-pages and update the "
+ "IKE Network landing page registration. Flags: "
+ "-DupdateSite=false, -DupdateRegistration=false, "
+ "-Dsite=removed (uninstall: deregister + cleanup)."),
/** {@code ike:setup} — one-time setup for an IKE development machine. */
SETUP(IkeGoal.NAME_SETUP, SetupMojo.class,
"One-time setup for an IKE development machine."),
/** {@code ike:unpack-zip} — unpack a zip artifact into a target directory. */
UNPACK_ZIP(IkeGoal.NAME_UNPACK_ZIP, UnpackZipMojo.class,
"Unpack a zip artifact into a target directory."),
/** {@code ike:verify-release-published} — verify all post-release publication targets (#374). */
VERIFY_RELEASE_PUBLISHED(IkeGoal.NAME_VERIFY_RELEASE_PUBLISHED,
VerifyReleasePublishedMojo.class,
"Verify all post-release publication targets are "
+ "reachable for the current project + version: "
+ "site (current/versioned/latest), org-site "
+ "landing, Nexus artifact, GitHub release tag. "
+ "Read-only; exits non-zero on any failure.");
// ── Mirror constants (ConstantBackedEnum) ───────────────────
// One public static final String per constant, named NAME_<CONSTANT>.
// These are the constant expressions referenced by @Mojo(name = ...)
// and by each enum constant's constructor call above (a forward
// reference to a constant variable, permitted by JLS 8.3.3).
// ConstantBackedEnum.verify() — run from the static initializer
// below — fails class-load if any constant and its mirror drift.
/** Mirror for {@link #CASCADE_EXPORT}. */
public static final String NAME_CASCADE_EXPORT = "cascade-export";
/** Mirror for {@link #CENTRAL_STATUS}. */
public static final String NAME_CENTRAL_STATUS = "central-status";
/** Mirror for {@link #CODESIGN_NATIVES}. */
public static final String NAME_CODESIGN_NATIVES = "codesign-natives";
/** Mirror for {@link #CODESIGN_PKG}. */
public static final String NAME_CODESIGN_PKG = "codesign-pkg";
/** Mirror for {@link #ENV}. */
public static final String NAME_ENV = "env";
/** Mirror for {@link #GENERATE_BOM}. */
public static final String NAME_GENERATE_BOM = "generate-bom";
/** Mirror for {@link #HELP}. */
public static final String NAME_HELP = "help";
/** Mirror for {@link #INJECT_BREADCRUMB}. */
public static final String NAME_INJECT_BREADCRUMB = "inject-breadcrumb";
/** Mirror for {@link #INJECT_JAVADOC_THEME}. */
public static final String NAME_INJECT_JAVADOC_THEME = "inject-javadoc-theme";
/** Mirror for {@link #JPACKAGE_PROPS}. */
public static final String NAME_JPACKAGE_PROPS = "jpackage-props";
/** Mirror for {@link #KNOWLEDGE_BINDINGS}. */
public static final String NAME_KNOWLEDGE_BINDINGS = "knowledge-bindings";
/** Mirror for {@link #KNOWLEDGE_EXPORT}. */
public static final String NAME_KNOWLEDGE_EXPORT = "knowledge-export";
/** Mirror for {@link #NOTARIZE}. */
public static final String NAME_NOTARIZE = "notarize";
/** Mirror for {@link #RELEASE_DRAFT}. */
public static final String NAME_RELEASE_DRAFT = "release-draft";
/** Mirror for {@link #RELEASE_PUBLISH}. */
public static final String NAME_RELEASE_PUBLISH = "release-publish";
/** Mirror for {@link #RELEASE_CASCADE}. */
public static final String NAME_RELEASE_CASCADE = "release-cascade";
/** Mirror for {@link #RELEASE_CHANGELOG}. */
public static final String NAME_RELEASE_CHANGELOG = "release-changelog";
/** Mirror for {@link #RENAME}. */
public static final String NAME_RENAME = "rename";
/** Mirror for {@link #BUILT_WITH}. */
public static final String NAME_BUILT_WITH = "built-with";
/** Mirror for {@link #RENDER_SBOM_VIEWER}. */
public static final String NAME_RENDER_SBOM_VIEWER = "render-sbom-viewer";
/** Mirror for {@link #RENDER_SPDX_LICENSES}. */
public static final String NAME_RENDER_SPDX_LICENSES = "render-spdx-licenses";
/** Mirror for {@link #SCAFFOLD_DRAFT}. */
public static final String NAME_SCAFFOLD_DRAFT = "scaffold-draft";
/** Mirror for {@link #SCAFFOLD_PUBLISH}. */
public static final String NAME_SCAFFOLD_PUBLISH = "scaffold-publish";
/** Mirror for {@link #SCAFFOLD_REVERT}. */
public static final String NAME_SCAFFOLD_REVERT = "scaffold-revert";
/** Mirror for {@link #SITE_DRAFT}. */
public static final String NAME_SITE_DRAFT = "site-draft";
/** Mirror for {@link #SITE_PUBLISH}. */
public static final String NAME_SITE_PUBLISH = "site-publish";
/** Mirror for {@link #SETUP}. */
public static final String NAME_SETUP = "setup";
/** Mirror for {@link #UNPACK_ZIP}. */
public static final String NAME_UNPACK_ZIP = "unpack-zip";
/** Mirror for {@link #VERIFY_RELEASE_PUBLISHED}. */
public static final String NAME_VERIFY_RELEASE_PUBLISHED = "verify-release-published";
/** Shared {@code ike:} prefix for all goals in this plugin. */
public static final String PLUGIN_PREFIX = "ike";
private static final String DRAFT_SUFFIX = "-draft";
private static final String PUBLISH_SUFFIX = "-publish";
/** Reverse lookup by bare goal name; also a duplicate-literal guard. */
private static final Map<String, IkeGoal> BY_NAME;
static {
// Class-load guard: every constant must have a matching NAME_*
// mirror whose value is the kebab-case form of the constant
// name. A drift here makes IkeGoal unloadable rather than
// letting a stale @Mojo name reach plugin.xml.
ConstantBackedEnum.verify(IkeGoal.class,
ConstantBackedEnum.defaultPrefix(),
(g, v) -> v.equals(
g.name().toLowerCase(Locale.ROOT).replace('_', '-')));
BY_NAME = ConstantBackedEnum.index(IkeGoal.class);
}
private final String goalName;
private final Class<? extends Mojo> mojoClass;
private final String description;
IkeGoal(String goalName,
Class<? extends Mojo> mojoClass,
String description) {
this.goalName = goalName;
this.mojoClass = mojoClass;
this.description = description;
}
/**
* The bare goal name as it appears in {@code @Mojo(name = ...)}.
*
* @return the bare goal name
*/
@Override
public String goalName() {
return goalName;
}
/**
* The String literal carried by this constant — the bare goal name.
* Satisfies {@link ConstantBackedEnum}.
*
* @return the bare goal name
*/
@Override
public String literalName() {
return goalName;
}
/**
* The {@code ike} plugin prefix — shared by every goal in this enum.
*
* @return {@link #PLUGIN_PREFIX}
*/
@Override
public String pluginPrefix() {
return PLUGIN_PREFIX;
}
/**
* The fully-qualified goal invocation, e.g. {@code "ike:release-publish"}.
*
* @return the fully-qualified goal invocation
*/
@Override
public String qualified() {
return PLUGIN_PREFIX + ":" + goalName;
}
/**
* The mojo class that implements this goal.
*
* @return the mojo class
*/
public Class<? extends Mojo> mojoClass() {
return mojoClass;
}
/**
* One-line human description of what this goal does.
*
* @return the human description
*/
@Override
public String description() {
return description;
}
/**
* True if this is the {@code -draft} counterpart of a draft/publish pair.
*
* @return {@code true} when this goal is a draft variant
*/
public boolean isDraft() {
return goalName.endsWith(DRAFT_SUFFIX);
}
/**
* True if this is the {@code -publish} counterpart of a draft/publish pair.
*
* @return {@code true} when this goal is a publish variant
*/
public boolean isPublish() {
return goalName.endsWith(PUBLISH_SUFFIX);
}
/**
* The paired draft/publish sibling, if this goal belongs to a pair.
*
* @return the sibling goal, or empty if this goal is a singleton
*/
public Optional<IkeGoal> pair() {
if (isDraft()) {
return byName(stripSuffix(goalName, DRAFT_SUFFIX) + PUBLISH_SUFFIX);
}
if (isPublish()) {
return byName(stripSuffix(goalName, PUBLISH_SUFFIX) + DRAFT_SUFFIX);
}
return Optional.empty();
}
/**
* Look up a goal by its bare name (e.g. {@code "release-publish"}).
*
* @param goalName the bare goal name, without the {@code ike:} prefix
* @return the matching goal, or empty if none
*/
public static Optional<IkeGoal> byName(String goalName) {
return Optional.ofNullable(BY_NAME.get(goalName));
}
private static String stripSuffix(String s, String suffix) {
return s.substring(0, s.length() - suffix.length());
}
}