[JAVA] Automatically register deliverables in Nexus Repository (Maven Central) serverless (Walter + GitHook)

This post is a blog post by @ takahi-i, [Automatic Java Artifacts Upload to Nexus Repository with Walter and Git Hooks](https://walter-cd.net/2016/11/18/automatic-upload-aritfacts- Japanese translation of to-nexus-repository /).

TL;DR

Maven release plugin

The author of this article is a development member of Walter, but written in Java called RedPen. He is also a development member of the proofreading tool. The artifacts of this tool (Jar and War files) are added to the Maven Central repository with each release. Previously, you used Maven's ** release plugin ** to add artifacts to the Maven Central repository.

Setting up to use the Maven release plugin ( pom.xml and digital signature) is quite difficult. For details, please read the article here. However, once configured, it's convenient to be able to add artifacts to the Maven Centaral repository simply by running the mvn release command at the time of release.

But lately, I've been having trouble running the release plugin for each release. Therefore, in this article, we will consider how to automate the release process. But first, let's consider the release process using the release plugin.

Processing using the Release plugin

When you run a release plugin, it does a lot of work interactively. The following prepares the reelealse plugin It is in the state where release: prepare is executed.

➜  redpen git:(master) mvn release:prepare
[INFO] Scanning for projects...
...
[INFO] Checking dependencies and plugins for snapshots ...
What is the release version for "redpen"? (cc.redpen:redpen) 1.7.5: :

You will first be asked to enter the release version. The release plugin presents the release version from the current snapshot version (1.7.5 in the example above). If the presented version is different from the version you want to release, enter the version number manually.

The plugin will then ask for a future Development Version. Enter it manually if necessary.

What is the new development version for "redpen"? (cc.redpen:redpen)
1.7.6-SNAPSHOT: :

Once this is done, the plugin will make a new version number change to git and commit to git. Then build in the current state.

If the build is successful, the plugin will say to push the version number change to the remote repository.

[INFO] Working directory: /Users/takahi-i/IdeaProjects/redpen
Username for 'https://github.com': Password for 'https://github.com':

You can see that the GitHub username and password are required. After this, even if mvn release: prepare succeeds, you still need to enter various things interactively in the release: perform command to be executed next. I'm afraid I typed it incorrectly and started over and over again: fearful:

Automate release process

The release plugin we saw in the previous section is awkward to use due to the interactive input work.

Preceding case

So, when I tweeted if there was an example that solved this problem, the slide "You are also an OSS developer! Various tips when uploading your own library to the Maven central repository .net / nabedge / 20140405-maven-5java) ”was taught. According to the slide, substituting the mvn versions: set and mvn deploy commands eliminates the need for interaction.

Try using Walter

The slide above uses the Jenkins server to execute the required commands. However, I thought that a small tool like RedPen would be costly to run on a server. As a motivation, I want to somehow automate without server management. It can also be automated with an external CI service such as Wercker, and the operation can be left to the service, so it's easy.

However, when the deployment process with these services does not work well, log analysis and re-execution (commit and push again) are a little difficult, so I would like to execute it on the local PC if possible.

So I let the build pipeline tool Walter do what the release plugin is doing. Walter enumerates the commands you want to execute in YAML format. For more information, see here.

Below is a flow of what the release plugin is doing with Walter.

pipeline:
    - name: Set Version
      command: mvn versions:set -DnewVersion=$REDPEN_VERSION
    - name: Add Files to the Next Changes
      command: git add pom.xml; git add **/*.xml
    - name: Commit Version Changes
      command: git commit -m "Set version in pom.xml to $REDPEN_VERSION"
    - name: Delopy to Sonatype
      command: mvn clean deploy -DperformRelease --settings
~/.m2/settings.xml > redpen-distribution/target/walter.log
    - name: Create Release Tag
      command: git tag -a redpen-$REDPEN_VERSION -m "RedPen release
$REDPEN_VERSION"
    - name: Flush Next Release Version Number
      command: echo $REDPEN_VERSION | awk -F. -v OFS=. 'NF==1{print
++$NF}; NF>1{if(length($NF+1)>length($NF))$(NF-1)++;
$NF=sprintf("%0*d-SNAPSHOT", length($NF), ($NF+1)%(10^length($NF)));
print}'
    - name: Echo Next Version
      command: echo __OUT["Flush Next Release Version Number"]
    - name: Set next version
      command: mvn versions:set -DnewVersion=__OUT["Flush Next Release
Version Number"]
    - name: Git Add
      command: git add .
    - name: Commit New Snapshot version
      command: git commit -m "Update versions in pom.xml for next release"

First, mvn version sets the version given by the environment variable. Then register your changes in git. Now you are ready to register your artifacts in Maven Central. In Delopy to Sonatype, mvn clean deploy will register the artifacts in Sonatype.

Then specify the development version after release. The version name of developement usually has the suffix -SNAPSHOT. First, we calculate the next version number ("Flush Next Release Version Number") and specify that version with "mvn versions: set". __OUT is used to reuse the standard output used in the specified stage. Register this file in the RedPen repository with the name release.yml.

Now all you have to do is run the walter -c release.yml command to complete the release process (although Sonatype requires you to manually close the artifacts).

Combine with Git Hook

Executing a single command in the above way now completes the release process. However, there is still one problem left. RedPen allows you to check the version with a command or server. All versions used by RedPen can be changed by rewriting a line in the RedPen.java file. For example, the image below shows RedPen server 1.7.7.

Screen Shot 2017-03-19 at 23.33.01.png

However, I'm afraid I forgot to raise the version number and released it: fearful: I thought about solving this problem with GitHook.

GitHook is a mechanism that executes the specified script when a specific git command is executed. This time, when git commit, I will try to make the release command automatically executed only when the commit message is Bump version ... ``.

I put the following files in ./git/hooks/post-commit.

#!/bin/bash

LATEST_MESSAGE=`git log -1 --pretty=%B`

if echo $LATEST_MESSAGE | grep -q "^Bump version " ; then
   export REDPEN_VERSION=`echo $LATEST_MESSAGE | grep -o "[0-9.]\+"`
   echo "Extracted Version: " $REDPEN_VERSION
    ./walter -c release.yml
else
   echo "Not changed version"
fi

With this file in place, if the commit message is "Bump vesrion" (the commit message that changes the RedPen version is Bump version), the release process will be executed. For this reason, it is possible to prevent an accident in which the release process is performed even though the internal version has not been upgraded (should).

from now on

RedPen switches the Sample Server on Heroku (http://redpen.herokuapp.com/) to a newer version each time a commit is pushed to a remote repository. I'm currently using Jenkins, but in the future I'll consider whether the sample server switching process can be automated locally.

Recommended Posts

Automatically register deliverables in Nexus Repository (Maven Central) serverless (Walter + GitHook)
Procedure to publish to Maven Central Repository