Building your artifact(s)
Everything starts form a single source file
and as the time goes by, it gradually transforms into multiple modules, bulky source files and a source control repository. Mostly by this time the team has already adopted a a build tool, and a repository to publish the versioned artifacts.
Journey is similar for every project successful or not.
The choice of tools can be pre-defined or adopted as explored, but the last step is almost similar for everyone, where you have to publish a release binary.
In this blog, I will try to talk about the last step only, as the other tools and choices have already been made for me and I am just publishing a convenient way of building & publishing your artifacts in a JFrog
repository.
Tools
JFrog
repository to store thesnapshot
andrelease
versions.- User account that has pubilsh/delete access to these repo(s)
- Maven as the build tool
- Java OpenJDK preferably
- Any IDE ( I use IntelliJ )
- Access to GitHub (User name and Personal Access Token)
mvn: Version
mvn -version
Apache Maven 3.8.2 (ea98e05a04480131370aa0c110b8c54cf726c06f)
Maven home: /usr/local/Cellar/maven/3.8.2/libexec
Java version: 17, vendor: Homebrew, runtime: /usr/local/Cellar/openjdk/17/libexec/openjdk.jdk/Contents/Home
Default locale: en_IN, platform encoding: UTF-8
OS name: "mac os x", version: "10.15.7", arch: "x86_64", family: "mac"
Java: version
java -version
openjdk version "16.0.1" 2021-04-20
OpenJDK Runtime Environment AdoptOpenJDK-16.0.1+9 (build 16.0.1+9)
OpenJDK 64-Bit Server VM AdoptOpenJDK-16.0.1+9 (build 16.0.1+9, mixed mode, sharing)
Project Setup (GITHUB)
I will be using the source code from the location mentioned below
To create a personal access token (you can find steps here) that shall be used in the server.xml
for scm settings please refer to documentation here.
mvn scm:checkout -DconnectionUrl=scm:git:https://github.com/samarthya/release-demo.git -DscmVersion=main -DscmVersionType=branch -DcheckoutDirectory=.
It will checkout the code in the current directory. (More information available here)
JFrog repository
This repo shall have all the artifacts we wish to publish
A shout out to @JFROG for providing the trial license that helped me build the repo a docker deployment
root@docker>docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
51b8aba2293b releases-docker.jfrog.io/jfrog/xray-analysis:3.27.4 "./bin/wrapper.sh" 13 days ago Up 13 days xray_analysis
a948186f1326 releases-docker.jfrog.io/jfrog/xray-indexer:3.27.4 "./bin/wrapper.sh" 13 days ago Up 13 days xray_indexer
0a6671c91fec releases-docker.jfrog.io/jfrog/xray-persist:3.27.4 "./bin/wrapper.sh" 13 days ago Up 13 days xray_persist
7142c819fd51 releases-docker.jfrog.io/jfrog/xray-server:3.27.4 "./bin/wrapper.sh" 13 days ago Up 13 days xray_server
8e4309d97e51 releases-docker.jfrog.io/jfrog/artifactory-pro:7.25.6 "/entrypoint-artifac…" 13 days ago Up 13 days 0.0.0.0:8081-8082->8081-8082/tcp, :::8081-8082->8081-8082/tcp artifactory
5507e78cca13 releases-docker.jfrog.io/jfrog/router:7.21.4 "/opt/jfrog/router/a…" 13 days ago Up 13 days 8082/tcp, 0.0.0.0:8083->8083/tcp, :::8083->8083/tcp xray_router
20b266981815 releases-docker.jfrog.io/postgres:13.2-alpine "docker-entrypoint.s…" 13 days ago Up 13 days 0.0.0.0:5432->5432/tcp, :::5432->5432/tcp postgresql
23a68fd1c8f5 releases-docker.jfrog.io/jfrog/xray-rabbitmq:3.8.14-management "/bin/bash -c ' (/se…" 13 days ago Up 13 days 5671/tcp, 0.0.0.0:4369->4369/tcp, :::4369->4369/tcp, 15671/tcp, 10.109.34.77:5672->5672/tcp, 0.0.0.0:15672->15672/tcp, :::15672->15672/tcp, 15691-15692/tcp, 10.109.34.77:25672->25672/tcp xray_rabbitmq
SCM: pom.xml
<scm>
<developerConnection>scm:git:${project.scm.url}</developerConnection>
<connection>scm:git:${project.scm.url}</connection>
<url>https://github.com/samarthya/release-demo.git</url>
</scm>
The repository for source goes into the SCM connection
and developerConnection
.
Before I walk through the process of how you can use a release and snapShot build let’s have a look at the release
plugin and the POM
.
maven-release-plugin
Releasing is a two step process
mvn release:prepare
Steps through several phases to ensure the POM is ready to be released and then prepares SCM to eventually contain a tagged version of the release and a record in the local copy of the parameters used.
In case of error and if you need to run again you can use
mvn release:prepare -Dresume=false
or you can use mvn release:clean
mvn release:perform
After completion of the previous step (no failure) you can perform the release. (Examples)
POM.xml
Wont go into each plugin details here but just for reference you can identify the maven-enforcer-plugin
which enforces the maven
and JDK
version requirements
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>${maven.enforcer.version}</version>
<executions>
<execution>
<id>enforce-matching-compiler-target-and-bundle-required-execution-environment</id>
<phase>validate</phase>
</execution>
<execution>
<id>enforce-build-tools-versions</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireJavaVersion>
<version>[11,)</version>
<message>Invalid Java Version (min 11)
</message>
</requireJavaVersion>
<requireMavenVersion>
<version>[3.6.2,)</version>
<message>Invalid Maven Version. (min 3.6.2)
</message>
</requireMavenVersion>
<banDuplicatePomDependencyVersions />
</rules>
<fail>true</fail>
</configuration>
</execution>
</executions>
</plugin>
You can also see the plugin for maven-release-plugin with configuration as below.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>${maven.release.version}</version>
<configuration>
<scmCommentPrefix>[scm bot]</scmCommentPrefix>
<tagNameFormat>@{project.version}</tagNameFormat>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
Where,
scmCommentPrefix
– The message prefix to use for all SCM changes.tagNameFormat
– Format to use when generating the tag name.
If you are not using setting.xml
for the SCM you can also use username
and password
to specify the credentials. In my example I am using the setting.xml.
<server>
<id>github.com</id>
<username><myusername></username>
<password><my token></password>
</server>
The complete source code is available in github.
Main pom.xml
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>${maven.resources.plugin.version}</version>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven.compiler.plugin.version}</version>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>${maven.release.version}</version>
<configuration>
<scmCommentPrefix>[scm bot]</scmCommentPrefix>
<tagNameFormat>@{project.version}</tagNameFormat>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>${maven.enforcer.version}</version>
<executions>
<execution>
<id>enforce-matching-compiler-target-and-bundle-required-execution-environment</id>
<phase>validate</phase>
</execution>
<execution>
<id>enforce-build-tools-versions</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireJavaVersion>
<version>[11,)</version>
<message>Invalid Java Version. It should be Java 11.0.x at
least.
</message>
</requireJavaVersion>
<requireMavenVersion>
<version>[3.6.2,)</version>
<message>Invalid Maven Version. It should be Maven 3.6.2 at
least.
</message>
</requireMavenVersion>
<banDuplicatePomDependencyVersions />
</rules>
<fail>true</fail>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>${maven.source.plugin.version}</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>${maven.javadoc.plugin.version}</version>
<configuration>
<encoding>UTF-8</encoding>
<author>true</author>
</configuration>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-scm-plugin</artifactId>
<version>${maven.scm.plugin.version}</version>
<configuration>
<goals>install</goals>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven.surefire.version}</version>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring.boot.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Now, it is time to use the plugin to prepare
and perform
.
Step 0
Check the snapshot version currently marked in the pom.xml
mvn -Dexec.executable='echo' -Dexec.args='${project.groupId}:${project.version}:${project.artifactId}:${project.packaging}' exec:exec -q
me.samarthya:1.0.1-SNAPSHOT:release-demo:jar
Step 1
mvn release:prepare
mvn release:prepare
[INFO] Scanning for projects...
[INFO]
[INFO] ---------------------< me.samarthya:release-demo >----------------------
[INFO] Building release-demo 1.0.1-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-release-plugin:3.0.0-M4:prepare (default-cli) @ release-demo ---
[INFO] phase verify-release-configuration
[INFO] starting prepare goal, composed of 17 phases: check-poms, scm-check-modifications, check-dependency-snapshots, create-backup-poms, map-release-versions, input-variables, map-development-versions, rewrite-poms-for-release, generate-release-poms, run-preparation-goals, scm-commit-release, scm-tag, rewrite-poms-for-development, remove-release-poms, run-completion-goals, scm-commit-development, end-release
[INFO] [prepare] 1/17 check-poms
[INFO] [prepare] 2/17 scm-check-modifications
[INFO] Verifying that there are no local modifications...
[INFO] [prepare] 4/17 create-backup-poms
[INFO] [prepare] 5/17 map-release-versions
What is the release version for "release-demo"? (me.samarthya:release-demo) 1.0.1: :
[INFO] [prepare] 6/17 input-variables
What is the SCM release tag or label for "release-demo"? (me.samarthya:release-demo) 1.0.1: : v1.0.1
[INFO] [prepare] 7/17 map-development-versions
What is the new development version for "release-demo"? (me.samarthya:release-demo) 1.0.2-SNAPSHOT: :
[INFO] [prepare] 8/17 rewrite-poms-for-release
[INFO] Transforming 'release-demo'...
[INFO] [prepare] 9/17 generate-release-poms
[INFO] Not generating release POMs
[INFO] [prepare] 10/17 run-preparation-goals
[INFO] Executing goals 'clean verify'...
[WARNING] Maven will be executed in interactive mode, but no input stream has been configured for this MavenInvoker instance.
[INFO] [prepare] 17/17 end-release
[INFO] Release preparation complete.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 23.413 s
[INFO] Finished at: 2021-09-23T20:58:13+05:30
[INFO] ------------------------------------------------------------------------
It generates a release.properties
#release configuration
#Thu Sep 23 20:58:13 IST 2021
projectVersionPolicyId=default
scm.branchCommitComment=@{prefix} prepare branch @{releaseLabel}
pinExternals=false
project.scm.me.samarthya\:release-demo.connection=scm\:git\:${project.scm.url}
project.scm.me.samarthya\:release-demo.tag=v1.0.0
project.rel.me.samarthya\:release-demo=1.0.1
exec.activateProfiles=profile-mine
pushChanges=true
project.scm.me.samarthya\:release-demo.developerConnection=scm\:git\:${project.scm.url}
project.dev.me.samarthya\:release-demo=1.0.2-SNAPSHOT
scm.rollbackCommitComment=@{prefix} rollback the release of @{releaseLabel}
remoteTagging=true
scm.commentPrefix=[scm bot]
releaseStrategyId=default
completedPhase=end-release
scm.url=scm\:git\:https\://github.com/samarthya/release-demo.git
scm.id=github.com
scm.developmentCommitComment=@{prefix} prepare for next development iteration
scm.tagNameFormat=@{project.version}
project.scm.me.samarthya\:release-demo.url=https\://github.com/samarthya/release-demo.git
scm.tag=v1.0.1
exec.snapshotReleasePluginAllowed=false
preparationGoals=clean verify
scm.releaseCommitComment=@{prefix} prepare release @{releaseLabel}
exec.pomFileName=pom.xml
Step 2
Time to perform
release
mvn release:perform
[INFO] Uploaded to virtual-repo-release: http://reposerver.samarthya.me:8082/artifactory/maven-local-release/me/samarthya/release-demo/1.0.1/release-demo-1.0.1-sources.jar (4.2 kB at 4.8 kB/s)
[INFO] Uploading to virtual-repo-release: http://reposerver.samarthya.me:8082/artifactory/maven-local-release/me/samarthya/release-demo/1.0.1/release-demo-1.0.1-javadoc.jar
[INFO] Progress (1): 4.1/125 kB
[INFO] Progress (1): 8.2/125 kB
[INFO] Progress (1): 12/125 kB
[INFO] Progress (1): 16/125 kB
[INFO] Progress (1): 20/125 kB
[INFO] Progress (1): 25/125 kB
[INFO] Progress (1): 29/125 kB
[INFO] Progress (1): 33/125 kB
[INFO] Progress (1): 37/125 kB
[INFO] Progress (1): 41/125 kB
[INFO] Progress (1): 45/125 kB
[INFO] Progress (1): 49/125 kB
[INFO] Progress (1): 53/125 kB
[INFO] Progress (1): 57/125 kB
[INFO] Progress (1): 61/125 kB
[INFO] Progress (1): 66/125 kB
[INFO] Progress (1): 70/125 kB
[INFO] Progress (1): 74/125 kB
[INFO] Progress (1): 78/125 kB
[INFO] Progress (1): 82/125 kB
[INFO] Progress (1): 86/125 kB
[INFO] Progress (1): 90/125 kB
[INFO] Progress (1): 94/125 kB
[INFO] Progress (1): 98/125 kB
[INFO] Progress (1): 102/125 kB
[INFO] Progress (1): 106/125 kB
[INFO] Progress (1): 111/125 kB
[INFO] Progress (1): 115/125 kB
[INFO] Progress (1): 119/125 kB
[INFO] Progress (1): 123/125 kB
[INFO] Progress (1): 125 kB
[INFO]
[INFO] Uploaded to virtual-repo-release: http://reposerver.samarthya.me:8082/artifactory/maven-local-release/me/samarthya/release-demo/1.0.1/release-demo-1.0.1-javadoc.jar (125 kB at 134 kB/s)
[INFO] [INFO] ------------------------------------------------------------------------
[INFO] [INFO] BUILD SUCCESS
[INFO] [INFO] ------------------------------------------------------------------------
[INFO] [INFO] Total time: 19.830 s
[INFO] [INFO] Finished at: 2021-09-23T21:07:09+05:30
[INFO] [INFO] ------------------------------------------------------------------------
[INFO] phase cleanup
[INFO] Cleaning up after release...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 30.575 s
[INFO] Finished at: 2021-09-23T21:07:09+05:30
[INFO] ------------------------------------------------------------------------
In the source repository also it has created a tag for the new build (an automated build)
We can manually now mark a new release in the GitRepo.
Finally!