From cacb7c190d236ed896febf0b697640f7c6d5bd1e Mon Sep 17 00:00:00 2001 From: Joseph Zuniga-Daly Date: Mon, 13 Nov 2023 10:03:31 +0000 Subject: [PATCH] CORE-17369: Enable display of CLI command versions (#201) Read version information from manifest. Example output: ```text corda-cli-plugin-host $ ./build/generatedScripts/corda-cli.sh --version Corda CLI 5.1.0-SNAPSHOT Provider: R3 Commit ID: 25201df7c0dd8a614b97025db0c2b9f37289dee5 corda-cli-plugin-host $ ./build/generatedScripts/corda-cli.sh example-plugin --version example-plugin 5.1.0-SNAPSHOT Provider: R3 Commit ID: 25201df7c0dd8a614b97025db0c2b9f37289dee5 ``` --- .../api/AbstractCordaCliVersionProvider.kt | 35 +++++++++++++++++++ app/build.gradle | 6 ++++ .../kotlin/net/corda/cli/application/Boot.kt | 9 ++++- plugins/build.gradle | 4 +++ .../cli/plugins/examples/ExamplePlugin.kt | 6 +++- .../src/main/resources/META-INF/MANIFEST.MF | 8 +++++ .../cli/plugins/examples/ExamplePluginTest.kt | 14 ++++++++ 7 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 api/src/main/kotlin/net/corda/cli/api/AbstractCordaCliVersionProvider.kt create mode 100644 plugins/example/src/main/resources/META-INF/MANIFEST.MF diff --git a/api/src/main/kotlin/net/corda/cli/api/AbstractCordaCliVersionProvider.kt b/api/src/main/kotlin/net/corda/cli/api/AbstractCordaCliVersionProvider.kt new file mode 100644 index 0000000..ed1804d --- /dev/null +++ b/api/src/main/kotlin/net/corda/cli/api/AbstractCordaCliVersionProvider.kt @@ -0,0 +1,35 @@ +package net.corda.cli.api + +import picocli.CommandLine.IVersionProvider +import java.util.jar.Manifest + +/** + * An abstract class that will read version information out of the plugin manifest. + * + * Builds version information using these attributes: + * - Plugin-Name + * - Plugin-Version + * - Plugin-Provider + * - Plugin-Git-Commit + * + * To apply, inherit from this class: + * + * class VersionProvider : AbstractCordaCliVersionProvider() + * + * Then add to your command annotation: + * + * versionProvider = VersionProvider::class + */ +abstract class AbstractCordaCliVersionProvider : IVersionProvider { + override fun getVersion(): Array = this.javaClass + .getResourceAsStream("/META-INF/MANIFEST.MF") + ?.use { + Manifest(it).mainAttributes.run { + arrayOf( + "${getValue("Plugin-Name")} ${getValue("Plugin-Version")}", + "Provider: ${getValue("Plugin-Provider")}", + "Commit ID: ${getValue("Plugin-Git-Commit")}" + ) + } + } ?: emptyArray() +} \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 3c671e6..1c8d895 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -94,9 +94,15 @@ def cordaCLi = tasks.named('jar', Jar) { } from(mergeLog4j2Plugins) + var cliHostCommitId = com.gradle.Utils.execAndGetStdOut "git", "rev-parse", "--verify", "HEAD" + manifest { attributes["Main-Class"] = appMainClass attributes["Multi-Release"] = true + attributes["Plugin-Name"] = "Corda CLI" + attributes["Plugin-Version"] = "${project.version}" + attributes["Plugin-Provider"] = "R3" + attributes["Plugin-Git-Commit"] = "$cliHostCommitId" } archiveBaseName = 'corda-cli' diff --git a/app/src/main/kotlin/net/corda/cli/application/Boot.kt b/app/src/main/kotlin/net/corda/cli/application/Boot.kt index 154961f..0f9d97e 100644 --- a/app/src/main/kotlin/net/corda/cli/application/Boot.kt +++ b/app/src/main/kotlin/net/corda/cli/application/Boot.kt @@ -1,6 +1,7 @@ package net.corda.cli.application import net.corda.cli.api.CordaCliPlugin +import net.corda.cli.api.AbstractCordaCliVersionProvider import net.corda.cli.application.logger.LoggerStream import org.pf4j.CompoundPluginDescriptorFinder import org.pf4j.DefaultPluginManager @@ -14,13 +15,19 @@ fun main(vararg args: String) { Boot.run(*args) } +class VersionProvider : AbstractCordaCliVersionProvider() + @CommandLine.Command( - name = "corda-cli" + name = "corda-cli", + versionProvider = VersionProvider::class ) class App { @CommandLine.Option(names = ["-h", "--help", "-?", "-help"], usageHelp = true, description = ["Display help and exit."]) @Suppress("unused") var help = false + + @CommandLine.Option(names = ["-V", "--version"], versionHelp = true, description = ["Display version and exit"]) + var showVersion = false } /** diff --git a/plugins/build.gradle b/plugins/build.gradle index 5c4e85b..559a71a 100644 --- a/plugins/build.gradle +++ b/plugins/build.gradle @@ -14,12 +14,16 @@ subprojects { subProject -> archiveBaseName = "plugin-${subProject.pluginId}" + var commitId = com.gradle.Utils.execAndGetStdOut "git", "rev-parse", "--verify", "HEAD" + manifest { attributes['Plugin-Class'] = subProject.pluginClass + attributes["Plugin-Name"] = subProject.pluginId attributes['Plugin-Id'] = subProject.pluginId attributes['Plugin-Version'] = archiveVersion attributes['Plugin-Provider'] = subProject.pluginProvider attributes['Plugin-Description'] = subProject.pluginDescription + attributes["Plugin-Git-Commit"] = "$commitId" } from sourceSets.main.output diff --git a/plugins/example/src/main/kotlin/net/corda/cli/plugins/examples/ExamplePlugin.kt b/plugins/example/src/main/kotlin/net/corda/cli/plugins/examples/ExamplePlugin.kt index 7bb8269..dde41cc 100644 --- a/plugins/example/src/main/kotlin/net/corda/cli/plugins/examples/ExamplePlugin.kt +++ b/plugins/example/src/main/kotlin/net/corda/cli/plugins/examples/ExamplePlugin.kt @@ -3,6 +3,7 @@ package net.corda.cli.plugins.examples import org.pf4j.Extension import org.pf4j.Plugin import net.corda.cli.api.CordaCliPlugin +import net.corda.cli.api.AbstractCordaCliVersionProvider import picocli.CommandLine /** @@ -16,12 +17,15 @@ class ExamplePlugin : Plugin() { override fun stop() { } + class VersionProvider : AbstractCordaCliVersionProvider() + @Extension @CommandLine.Command( name = "example-plugin", subcommands = [SubCommandOne::class], description = ["Example plugin using class based subcommands"], - mixinStandardHelpOptions = true + mixinStandardHelpOptions = true, + versionProvider = VersionProvider::class ) class ExamplePluginEntry : CordaCliPlugin } diff --git a/plugins/example/src/main/resources/META-INF/MANIFEST.MF b/plugins/example/src/main/resources/META-INF/MANIFEST.MF new file mode 100644 index 0000000..02c252b --- /dev/null +++ b/plugins/example/src/main/resources/META-INF/MANIFEST.MF @@ -0,0 +1,8 @@ +Manifest-Version: 1.0 +Main-Class: net.corda.cli.application.BootKt +Multi-Release: true +Plugin-Name: Corda CLI +Plugin-Version: 5.1.0-TEST +Plugin-Provider: R3 +Plugin-Git-Commit: TEST + diff --git a/plugins/example/src/test/kotlin/net/corda/cli/plugins/examples/ExamplePluginTest.kt b/plugins/example/src/test/kotlin/net/corda/cli/plugins/examples/ExamplePluginTest.kt index 35b9604..5b39c41 100644 --- a/plugins/example/src/test/kotlin/net/corda/cli/plugins/examples/ExamplePluginTest.kt +++ b/plugins/example/src/test/kotlin/net/corda/cli/plugins/examples/ExamplePluginTest.kt @@ -1,6 +1,8 @@ package net.corda.cli.plugins.examples +import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertTrue +import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import picocli.CommandLine import java.io.ByteArrayOutputStream @@ -61,6 +63,18 @@ class ExamplePluginTest { ) { outText } } + @Test + fun testVersionOption() { + + val app = ExamplePlugin.ExamplePluginEntry() + + val outText = tapSystemOut { + CommandLine(app).execute("--version") + } + + assertEquals("Corda CLI 5.1.0-TEST\nProvider: R3\nCommit ID: TEST\n", outText) + } + @Test fun testSubCommand() {