How to release junixsocket
This is mostly relevant only if you're the project admin or going to fork the project.
Prerequisites
llvm and mingw-w64
In order to build for all supported target platforms included in the release, our development machine (the one where we do the compilation), needs to have clang and llvm, as well as x86_64-w64-mingw32-gcc, a GCC compiler binary to allow building for Windows.
On Mac, run the following command.
brew install llvm mingw-w64
If you don't have Homebrew, obtain it from here first.
Note that there currently is an incompatibility with mingw 12.0. To use mingw 11.0, run the following commands:
brew remove mingw-w64
wget https://raw.githubusercontent.com/Homebrew/homebrew-core/0247512f8a852f36f14b11809ac08a402de1f9e5/Formula/m/mingw-w64.rb
brew install ./mingw-w64.rb
brew pin mingw-w64
github.com credentials
- On github.com, create an OAuth token with write permissions to the repo.
- Add the credentials to your keychain
GPG keys
Instructions for macOS
-
Install gpg and helper tools
brew install gpg gpg2 gpg-agent pinentry-mac
-
Enable pinentry-mac
This gives a nice GUI for the passphrase, and allows us to store the GPG key passphrase in the macOS keychain)
-
Open or create
~/.gnupg/gpg-agent.conf
then add the following line if it doesn't exist yet:pinentry-program /usr/local/bin/pinentry-mac
-
Generate a GPG key
gpg2 --generate-key
Follow on-screen instructions. Use a long, memorable passphrase.
-
Remember the GPG key ID. Publish the corresponding GPG public key on the GPG keyservers:
gpg2 --send-key THEKEYID
Build environment for other platforms
Currently, the easiest way to build for other platforms is to have a working Java 9 (or later) environment, Maven 3+ and the junixsocket project ready. Just spin up a virtual machine (or emulator), install Java, Maven and junixsocket, and you should be good to go.
Common tasks
Update changelog, website, README.md
Update junixsocket/src/site/markdown/changelog.md
with a section for the new version and all
noteworthy changes.
Check all mentions (execpet for changelog.md
) of the current junixsocket under
junixsocket/src/site/markdown
, and replace accordingly:
grep X.Y.Z src/site/markdown/* | grep -v changelog.md:
Also update the dependency statement in junixsocket/README.md
.
NOTE: (Replace X.Y.Z with the current version)
Ensure GraalVM native configs are still up-to-date
Run junixsocket-native-graalvm/bin/with-graalvm junixsocket-native-graalvm/bin/build-selftest
If, at the end, you see changes to the json files in junixsocket-native-graalvm/output
, review
them, modify the json files in
junixsocket-{common,tipc,vsock,selftest,...}/src/main/resources/META-INF/native-image
accordingly,
and add/commit both sets of changes.
Ensure the code is properly formatted and licenses are in place
First, view the LICENSE
file and verify that it's up to date. Then run the code formatters and commit.
cd junixsocket
mvn process-sources -Dreformat
# git add / commit here...
Bump project version
cd junixsocket
mvn versions:set -DnewVersion=X.Y.Z
# git add / commit here...
NOTE: (Replace X.Y.Z with the actual new version)
Build native libraries on other supported, common platforms
NOTE: This section can presently be skipped since all targets shipped in
junixsocket-native-common
cross-compile with-Drelease
.
On the target machine, install junixsocket. Make sure you use the very same version as on your development machine from where you do the release!
cd junixsocket
mvn clean install -Dstrict
The platform-dependent nar files should now be available in the local maven repository cache.
Use the provided script to copy the corresponding nar to a project folder:
cd junixsocket
junixsocket-native-prebuilt/bin/copy-nar-from-m2repo.sh X.Y.Z
NOTE: (Replace X.Y.Z with the actual version)
Now copy the nar files from the target machine to your development computer (from where you do the release). By convention, copy the files to the same folder as on the target machine (junixsocket/junixsocket-native-prebuilt/bin)
On the development computer, install the nar files in the local Maven repository cache:
cd junixsocket
junixsocket-native-prebuilt/bin/install-to-m2repo.sh junixsocket-native-prebuilt/nar/*nar
Create binary distribution
This will create a directory, a .tar.gz and a .zip archive, containing the project jars and a script to run the demo classes from the command-line.
cd junixsocket
mvn clean install -Dstrict -Drelease
The files can be found in
junixsocket/junixsocket-dist/target/junixsocket-dist-X.Y.Z-bin
junixsocket/junixsocket-dist/target/junixsocket-dist-X.Y.Z-bin.tar.gz
junixsocket/junixsocket-dist/target/junixsocket-dist-X.Y.Z-bin.zip
NOTE: (Replace X.Y.Z with the actual version)
Verify that Selftest works
Run java -jar junixsocket-selftest/target/junixsocket-selftest-X.Y.Z-jar-with-dependencies.jar
. It should end with Selftest PASSED
.
Also run the selftest with Java 8, e.g.:
/Library/Java/JavaVirtualMachines/1.8.0.jdk/Contents/Home/bin/java -jar junixsocket-selftest/target/junixsocket-selftest-2.10.1-jar-with-dependencies.jar
Run junixsocket-native-graalvm/bin/with-graalvm mvn package -pl junixsocket-selftest-native-image -Dnative
(on all native-image supported platforms) to build the GraalVM native-image. Test the native-image
by running junixsocket-selftest-native-image/target/junixsocket-selftest-native-image-X.Y.Z
.
NOTE: (Replace X.Y.Z with the actual version)
Deploy code to Maven central
Tag the release, push to upstream (i.e., GitHub)
mvn scm:tag
If you need to make a revision afterwards, retag with git tag -f TAG
and git push origin TAG --force
.
Deploy to staging
cd junixsocket
mvn clean install -Drelease -Dstrict
mvn clean deploy -Drelease -Ddeploy -Dignorant -D -DskipTests -Dsigned -Dgpgkeyname=$(git config --get user.email) -Dgpg.executable=$(which gpg)
Notes
-Drelease
makes sure we include all common native binaries in junixsocket-native-common.
-Dstrict
enforces code quality checks to succeed (e.g., spotbugs, checkstyle).
-Dignorant
disables linters, code quality checks, javadoc, source jars, etc.
-Ddeploy
re-enable javadoc/attach-sources even with -Dignorant
set.
-DskipTests
skips unit testing.
-Dsigned
enables signing the artifacts with our GPG key (using the key name specified with -Dgpgkeyname=
and the gpg executable specified with -Dgpg.executable=
).
In case of failures while staging:
If the deployment fails with Remote staging failed: Staging rules failure!
and due to
No public key: Key with id: (...) was not able to be located on ...
,
then that means that the GPG key you created above has not been fully distributed among the GPG key
servers. Try to manually push to the ones mentioned in the error message, and try again.
For example:
gpg2 --keyserver http://keyserver.ubuntu.com:11371 --send-key THEKEYID
If you get an error Remote staging failed: A message body reader for Java class com.sonatype.nexus.staging.api.dto.StagingProfileRepositoryDTO, and Java type class com.sonatype.nexus.staging.api.dto.StagingProfileRepositoryDTO, and MIME media type text/html was not found
, then simply try again; see OSSRH-51097.
Review the deployed artifacts
The URL of the staging repository is https://oss.sonatype.org/content/groups/staging
.
The artifacts can be found here.
If you're deploying a -SNAPSHOT
version, you can find the artifacts
here.
IMPORTANT Double-check that the staged junixsocket-native-common artifact contains all required library binaries (macOS, Linux 64-bit, etc.).
Review selftest on all supported platforms
Download junixsocket-selftest-X.Y.Z-jar-with-dependencies.jar
from staging to all supported platforms:
https://oss.sonatype.org/content/groups/staging/com/kohlschutter/junixsocket/junixsocket-selftest/X.Y.Z/junixsocket-selftest-X.Y.Z-jar-with-dependencies.jar
Run java -jar junixsocket-selftest-X.Y.Z-jar-with-dependencies.jar
on all supported platforms and supported JDK combinations.
Depending on the platform, it should end with Selftest PASSED
or Selftest PASSED WITH ISSUES
.
Also check the header, especially the Git properties
at the beginning of the output:
- The version numbers (
junixsocket selftest version
andgit.build.version
) should match the expected version number git.dirty
should befalse
git.commit.id.describe
should match the new git tag.
Release artifact to Maven Central
IMPORTANT Once released, it cannot be undone! Make sure you verify the staged artifact first!
MAVEN_OPTS="--add-opens java.base/java.util=ALL-UNNAMED" mvn nexus-staging:release -Drelease
NOTE: There can be quite a delay (30 minutes?) until the artifact is deployed in Maven Central.
Release on GitHub
-
Log in to GitHub, go to Releases -> Draft a new release.
-
Select the newly created tag (= search for the version).
-
Release title = “junixsocket” + version>, e.g., “junixsocket X.Y.Z”
-
Paste changelog contents to text field
-
Upload binaries:
junixsocket-dist/target/junixsocket-dist-X.Y.Z-bin.tar.gz
/junixsocket-dist-X.Y.Z-bin.zip
as well asjunixsocket-selftest/target/junixsocket-selftest-X.Y.Z-jar-with-dependencies.jar
-
Hit “Publish release”
NOTE: (Replace X.Y.Z with the actual version)
Publish website
NOTE: Maven 3.9.7 and 3.9.8 contain a bug (MNG-8178) that prevents building the site. Use Maven 3.9.6 instead.
This builds the Maven site
cd junixsocket
./scripts/build-site
The website should now be inspected at junixsocket/target/staging/index.html
If everything looks good, we can publish it to https://kohlschutter.github.io/junixsocket/:
mvn scm-publish:publish-scm -Dstrict -Drelease
NOTE: There can be a 10-minute delay until the pages get updated.
FIXME: We currently don't aggregate code coverage from all platforms. Therefore, especially for
TIPC
andVSOCK
support, the coverage reported is misleading.
Prepare next version
mvn versions:set -DnewVersion=X.Y.Z-SNAPSHOT
mvn clean install
NOTE: (Replace X.Y.Z with the actual version)