Skip to content

Conversation

@czpilar
Copy link
Contributor

@czpilar czpilar commented Jan 25, 2026

Resolves #1286

@czpilar
Copy link
Contributor Author

czpilar commented Jan 25, 2026

I've created records BuildProperties and GitProperties within Version command to avoid adding spring-boot dependency to spring-shell-core.

@fmbenhassine
Copy link
Contributor

LGTM! However, this will only work with Spring Boot right? I am thinking about non boot users.

Moreover, I can't seem to get build and git details when testing the change set. Here are the changes I tried on the Boot sample:

Index: spring-shell-samples/spring-shell-sample-spring-boot/pom.xml
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/spring-shell-samples/spring-shell-sample-spring-boot/pom.xml b/spring-shell-samples/spring-shell-sample-spring-boot/pom.xml
--- a/spring-shell-samples/spring-shell-sample-spring-boot/pom.xml	(revision e7a56eedeec72f95fd14b677e3d8fc9b355ea008)
+++ b/spring-shell-samples/spring-shell-sample-spring-boot/pom.xml	(date 1769592876333)
@@ -26,4 +26,24 @@
         </dependency>
 	</dependencies>
 
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.springframework.boot</groupId>
+				<artifactId>spring-boot-maven-plugin</artifactId>
+				<executions>
+					<execution>
+						<phase>package</phase>
+						<goals>
+							<goal>repackage</goal>
+						</goals>
+						<configuration>
+							<mainClass>org.springframework.shell.samples.helloworld.boot.SpringShellApplication</mainClass>
+						</configuration>
+					</execution>
+				</executions>
+			</plugin>
+		</plugins>
+	</build>
+
 </project>
Index: spring-shell-samples/spring-shell-sample-spring-boot/src/main/resources/application.properties
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>ISO-8859-1
===================================================================
diff --git a/spring-shell-samples/spring-shell-sample-spring-boot/src/main/resources/application.properties b/spring-shell-samples/spring-shell-sample-spring-boot/src/main/resources/application.properties
--- a/spring-shell-samples/spring-shell-sample-spring-boot/src/main/resources/application.properties	(revision e7a56eedeec72f95fd14b677e3d8fc9b355ea008)
+++ b/spring-shell-samples/spring-shell-sample-spring-boot/src/main/resources/application.properties	(date 1769593001068)
@@ -1,1 +1,11 @@
-spring.application.name=spring-shell-hello-world
\ No newline at end of file
+spring.application.name=spring-shell-hello-world
+spring.shell.command.version.show-build-artifact=true
+spring.shell.command.version.show-build-group=true
+spring.shell.command.version.show-build-version=true
+spring.shell.command.version.show-build-time=true
+spring.shell.command.version.show-build-name=true
+
+spring.shell.command.version.show-git-branch=true
+spring.shell.command.version.show-git-commit-time=true
+spring.shell.command.version.show-git-commit-id=true
+spring.shell.command.version.show-git-short-commit-id=true
\ No newline at end of file

Building a jar file and running it with java -jar target/spring-shell-sample-spring-boot-4.0.1-SNAPSHOT.jar does not show the details when I run the version command. I might be missing something or a config on how these details are gathered by Boot.

@fmbenhassine fmbenhassine added the status/need-feedback Calling participant to provide feedback label Jan 28, 2026
@czpilar
Copy link
Contributor Author

czpilar commented Jan 28, 2026

Hello @fmbenhassine,
You need to add Maven plugins like this:

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<executions>
					<execution>
						<phase>package</phase>
						<goals>
							<goal>repackage</goal>
						</goals>
						<configuration>
							<mainClass>org.springframework.shell.samples.helloworld.boot.SpringShellApplication</mainClass>
						</configuration>
					</execution>
					<execution>
						<id>build-info</id>
						<goals>
							<goal>build-info</goal>
						</goals>
					</execution>
				</executions>
			</plugin>
			<plugin>
				<groupId>io.github.git-commit-id</groupId>
				<artifactId>git-commit-id-maven-plugin</artifactId>
				<version>9.0.2</version>
				<executions>
					<execution>
						<goals>
							<goal>revision</goal>
						</goals>
						<configuration>
							<generateGitPropertiesFile>true</generateGitPropertiesFile>
							<generateGitPropertiesFilename>${project.build.outputDirectory}/git.properties</generateGitPropertiesFilename>
							<failOnNoGitDirectory>false</failOnNoGitDirectory>
						</configuration>
					</execution>

				</executions>
			</plugin>
		</plugins>
	</build>

This will generate git.properties and META-INF/build-info.properties files with build information. By default, this is for Spring Boot applications, which use BuildPropertiesRuntimeHints and GitPropertiesRuntimeHints.
For non-Spring Boot applications, I would suggest creating a new Version() and using the setBuildProperties and setGitProperties methods to set those properties manually by using the new records created for that purpose.
I do not know how to create a non-Spring Boot Shell application, but in my opinion, this could be a follow-up issue.

obrazek

@czpilar
Copy link
Contributor Author

czpilar commented Jan 28, 2026

Ah, yeah... there is an example spring-shell-sample-hello-world with non-boot spring application... I will look at this...

@czpilar
Copy link
Contributor Author

czpilar commented Jan 28, 2026

For non-Spring users, this can be done in a similar way by adding the required plugins to their build tool configuration, for example:

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<executions>
					<execution>
						<phase>package</phase>
						<goals>
							<goal>repackage</goal>
						</goals>
						<configuration>
							<mainClass>org.springframework.shell.samples.helloworld.SpringShellApplication</mainClass>
						</configuration>
					</execution>
					<execution>
						<id>build-info</id>
						<goals>
							<goal>build-info</goal>
						</goals>
					</execution>
				</executions>
			</plugin>
			<plugin>
				<groupId>io.github.git-commit-id</groupId>
				<artifactId>git-commit-id-maven-plugin</artifactId>
				<version>9.0.2</version>
				<executions>
					<execution>
						<goals>
							<goal>revision</goal>
						</goals>
						<configuration>
							<generateGitPropertiesFile>true</generateGitPropertiesFile>
							<generateGitPropertiesFilename>${project.build.outputDirectory}/git.properties</generateGitPropertiesFilename>
							<failOnNoGitDirectory>false</failOnNoGitDirectory>
						</configuration>
					</execution>

				</executions>
			</plugin>
		</plugins>
	</build>

This would then require implementing something like the following in EnableCommandRegistrar:

registry.registerBeanDefinition("version", new RootBeanDefinition(Version.class, this::createVersion));
private Version createVersion() {
    Version version = new Version();
    version.setShowBuildVersion(true);
    version.setShowBuildTime(true);
    version.setShowGitCommitId(true);
    version.setShowGitShortCommitId(true);
    version.setShowGitCommitTime(true);
    version.setShowGitBranch(true);
    version.setShowBuildGroup(true);
    version.setShowBuildArtifact(true);
    version.setShowBuildName(true);
    version.setBuildProperties(new Version.BuildProperties("org.springframework.shell", "spring-shell-core",
            "Spring Shell", this.getClass().getPackage().getImplementationVersion(), Instant.now()));
    version.setGitProperties(new Version.GitProperties("main", "abcdef1234567890", "abcdef1", Instant.now()));
    return version;
}

In the createVersion method, this essentially need to replicate GitProperties and BuildProperties from Spring Boot.

I’m not sure this replication is the right approach, as it effectively duplicates existing code.

As mentioned earlier, this could be done as a follow-up, and at least provide build information for Spring Boot users, who I believe will be the majority.

@czpilar
Copy link
Contributor Author

czpilar commented Jan 28, 2026

Also this approach is for non-boot users possible:

package org.springframework.shell.samples.helloworld;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.shell.core.ShellRunner;
import org.springframework.shell.core.command.Version;
import org.springframework.shell.core.command.annotation.Command;
import org.springframework.shell.core.command.annotation.EnableCommand;
import org.springframework.shell.core.command.annotation.Option;

import java.time.Instant;

@EnableCommand(SpringShellApplication.class)
public class SpringShellApplication implements InitializingBean, ApplicationContextAware {

	public static void main(String[] args) throws Exception {
		ApplicationContext context = new AnnotationConfigApplicationContext(SpringShellApplication.class);
		ShellRunner runner = context.getBean(ShellRunner.class);
		runner.run(args);
	}

	@Command(name = "hello", description = "Say hello to a given name", group = "Greetings",
			help = "A command that greets the user with 'Hello ${name}!'. Usage: hello [-n | --name]=<name>")
	public void sayHello(@Option(shortName = 'n', longName = "name", description = "the name of the person to greet",
			defaultValue = "World") String name) {
		System.out.println("Hello " + name + "!");
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		Version version = applicationContext.getBean(Version.class);
		version.setShowBuildVersion(true);
		version.setShowBuildTime(true);
		version.setShowGitCommitId(true);
		version.setShowGitShortCommitId(true);
		version.setShowGitCommitTime(true);
		version.setShowGitBranch(true);
		version.setShowBuildGroup(true);
		version.setShowBuildArtifact(true);
		version.setShowBuildName(true);
		version.setBuildProperties(new Version.BuildProperties("org.springframework.shell", "spring-shell-core",
				"Spring Shell", this.getClass().getPackage().getImplementationVersion(), Instant.now()));
		version.setGitProperties(new Version.GitProperties("main", "abcdef1234567890", "abcdef1", Instant.now()));
	}

	private ApplicationContext applicationContext;

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		this.applicationContext = applicationContext;
	}

}

@fmbenhassine
Copy link
Contributor

Thank you for your feedback about these plugins configuration @czpilar ! I was sure I was missing something 😂

For non-Spring Boot applications, I would suggest creating a new Version() and using the setBuildProperties and setGitProperties methods to set those properties manually by using the new records created for that purpose.

Ideally, all features should be the same in both worlds (boot and non-boot) without having two versions of the same command. The added value of Boot would be auto-configuring things. The fact that it's difficult to achieve this easily shows how tied v3 was to Boot. I really struggled with this, see #1207 and #1206.

Anyway, I am not keen to merge a "feature" that works only for Boot, so we need to figure out how to make this work in both worlds. The good thing is that you introduced two new types: BuildProperties and GitProperties. One way of approaching the problem is to make the version command look for two beans of these types from the application context and use them to populate the output of the command.

In a non-boot world, the user has to provide them manually (like any other config). In a Boot world, those beans would be provided automatically. With that in place, we would have the same version command in both worlds. Wdyt?

@czpilar
Copy link
Contributor Author

czpilar commented Jan 29, 2026

@fmbenhassine fully understand... I have now some idea. Will look at this later...

Signed-off-by: David Pilar <david@czpilar.net>
@czpilar czpilar force-pushed the patches/1286-restore-version-command branch from ab155b7 to 1205290 Compare January 29, 2026 14:04
@czpilar
Copy link
Contributor Author

czpilar commented Jan 29, 2026

Now it is complete and works for both Boot and non-Boot users. Non-Boot users just need to register Spring beans for Version.BuildProperties and Version.GitProperties, as shown in the following example:

package org.springframework.shell.samples.helloworld;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.shell.core.ShellRunner;
import org.springframework.shell.core.command.Version;
import org.springframework.shell.core.command.annotation.Command;
import org.springframework.shell.core.command.annotation.EnableCommand;
import org.springframework.shell.core.command.annotation.Option;

import java.time.Instant;

@EnableCommand(SpringShellApplication.class)
public class SpringShellApplication {

	public static void main(String[] args) throws Exception {
		ApplicationContext context = new AnnotationConfigApplicationContext(SpringShellApplication.class);
		ShellRunner runner = context.getBean(ShellRunner.class);
		runner.run(args);
	}

	@Command(name = "hello", description = "Say hello to a given name", group = "Greetings",
			help = "A command that greets the user with 'Hello ${name}!'. Usage: hello [-n | --name]=<name>")
	public void sayHello(@Option(shortName = 'n', longName = "name", description = "the name of the person to greet",
			defaultValue = "World") String name) {
		System.out.println("Hello " + name + "!");
	}

	@Bean
	public Version.BuildProperties versionBuildProperties() {
		return new Version.BuildProperties("com.example", "spring-shell-sample", "Spring Shell Sample", "1.0.0",
				Instant.now());
	}

	@Bean
	public Version.GitProperties versionGitProperties() {
		return new Version.GitProperties("main", "abc1234", "abc1234", Instant.now());
	}

}

And that's it. Of course, boot-users can also register those beans which will override autoconfigured settings.

Screenshot for boot users:

obrazek

Screenshot for non-boot users:

obrazek

Please have a look @fmbenhassine

@fmbenhassine
Copy link
Contributor

Fantastic! This is exactly what I meant here #1298 (comment).

I can't thank you enough for all your help on Spring Shell 🙏

@fmbenhassine fmbenhassine merged commit 10d33a8 into spring-projects:main Jan 29, 2026
2 checks passed
@czpilar czpilar deleted the patches/1286-restore-version-command branch January 29, 2026 15:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

status/need-feedback Calling participant to provide feedback

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Restore version command result as in v3

2 participants