Project Polygene has retired. For details please refer to its Attic page.
Releasing Zest™

Releasing Zest™


You need a unix-like environment to actually perform the release process. This tutorial is known to work on Linux and Mac.

This tutorial is intended for Apache Zest™ commiters who want to release a new version of Apache Zest™ (Java Edition) at The Apache Software Foundation. It describes the tools and processes of a typical release.

It is intended to be a recommendation of best practices for the Apache Zest™ project. The instructions provided here are consistent with, but not a replacement for the ASF Release Guidelines.

Preparing a release

Select a Release Manager

A Zest committer (normally one of the development team) should post an email to the development list proposing that a release be made and nominating a release manager. Typically, the proposer volunteers as the release manager and it passes by lazy consensus.

Clone/Checkout all repositories

Clone/checkout all needed repositories, next to each other:

mkdir zest-repos
cd zest-repos
git clone zest-java
svn checkout zest-web
svn checkout --depth empty zest-dist
cd zest-dist
svn update --set-depth immediates dev
svn update --set-depth immediates release
svn update --set-depth infinity dev/zest
svn update --set-depth infinity release/zest

You should then get the following directory tree:

└── zest-repos
    ├── zest-java           # Apache Zest™ (Java Edition) source
    ├── zest-web            # website
    └── zest-dist
        ├── dev
        |   └── zest        # Releases candidate distributions
        └── release
            └── zest        # Releases distributions


From now on, all command line snippets start from the zest-repos directory.

Build Apache Zest™ (Java Edition)

Ensure you can test, build Apache Zest™ (Java Edition), including the documentation minisite generation using Asciidoc and artifact signing.

Here is what should pass before going further:

cd zest-java
./gradlew -Dversion="<RELEASE-VERSION>" website signArchives

See the Build System tutorial for details.

Install Jekyll

Moreover, you will need to have a valid Jekyll installation as the Apache Zest™ website is generated using it.

Setup git flow

git-flow is a git extension that add git commands to easily use the git flow branching model the Apache Zest™ project follows. See the installation instructions.

Setup git signing

Ensure you can sign git tags.

git config --global user.signingkey <YOUR-PGP-ID>

See the Git Tools - Signing Your Work section of the Git book.

Setup Apache Nexus credentials

See the Apache Publishing Maven Artifacts guide and the Apache Zest™ (Java Edition) Build System tutorial.

Update the KEYS files if needed.

The reference KEYS file can be found at the zest-java repository’s root, that is zest-java/KEYS. Ensure that it contains your public key.

Next, diff it against the ones present in the dev and release distribution areas:

diff zest-java/KEYS zest-dist/dev/zest/KEYS
diff zest-java/KEYS zest-dist/release/zest/KEYS

And update them if needed:

cp zest-java/KEYS zest-dist/dev/zest/KEYS
cp zest-java/KEYS zest-dist/release/zest/KEYS
cd zest-dist/dev/zest
svn add dev/zest/KEYS release/zest/KEYS
svn commit -m "zest: updating Zest KEYS"

Creating a Release Candidate

Resolve JIRA issues

Resolve all issues on that version! They can be resolved by:

  • fixing
  • marking them as INVALID or WONTFIX
  • changing their fix version to another unreleased version

See the ZEST project on JIRA.

Prepare Release-Notes

Apache Zest™ release-notes are generated from JIRA issues.

Open the target Zest™ version’s release-notes in JIRA and review them.

JIRA can produces release-notes as HTML or plain-text. Set it up to generate plain-text release-notes.

We will need these in several formats. Starting from the plain-text one we will generate the others.

First save the text-plain release-notes in a file named apache-zest-java-<RELEASE-VERSION>-release-notes.txt. A good place for this file would be in the zest-repos directory created earlier, alongside all repositories.

Convert to Asciidoc:

cat "apache-zest-java-<RELEASE-VERSION>-release-notes.txt" | \
  sed -e "s/* \[ZEST-\([0-9]\)*\]/- https:\/\/\/jira\/browse\/ZEST-\1[ZEST-\1]/" | \
  sed -e "s/^\*\*/===/" > "apache-zest-java-<RELEASE-VERSION>-release-notes.adoc"

Convert to Markdown:

cat "apache-zest-java-<RELEASE-VERSION>-release-notes.txt" | \
  sed -e "s/* \[ZEST-\([0-9]\)*\]/- [ZEST-\1](https:\/\/\/jira\/browse\/ZEST-\1)/" | \
  sed -e "s/^\*\*/###/" > "apache-zest-java-<RELEASE-VERSION>"

You should then have the following files:

├── apache-zest-java-<RELEASE-VERSION>-release-notes.txt
├── apache-zest-java-<RELEASE-VERSION>-release-notes.adoc
└── apache-zest-java-<RELEASE-VERSION>

We will use them later.

Create a RC branch

We use <RELEASE-VERSION>-RC# where RELEASE-VERSION is the target release version and RC# for Release Candidate and an incremental number in case the release process has to be done several times.

cd zest-java
git flow release start "<RELEASE-VERSION>-RC#"

This will eventually generates a <RELEASE-VERSION>-RC# tag that we will amend with a <RELEASE-VERSION> signed tag if the vote passes, see below.

Audit artifacts and distributions

Make a complete build, deploying maven artifacts locally:

cd zest-java
./gradlew -Dversion="<RELEASE-VERSION>" -PuploadRepository="file://$(pwd)/build/repositories/zest-java" \
    clean assemble checkDists uploadArchives

Review maven artifacts in build/repositories/zest-java.

Also review the release distributions in build/distributions where you should find the following files:

├── apache-zest-java-<RELEASE-VERSION>-bin.tgz
├── apache-zest-java-<RELEASE-VERSION>-bin.tgz.MD5
├── apache-zest-java-<RELEASE-VERSION>-bin.tgz.SHA-512
├── apache-zest-java-<RELEASE-VERSION>-bin.tgz.asc
├── apache-zest-java-<RELEASE-VERSION>
├── apache-zest-java-<RELEASE-VERSION>
├── apache-zest-java-<RELEASE-VERSION>
├── apache-zest-java-<RELEASE-VERSION>
├── apache-zest-java-<RELEASE-VERSION>-src.tgz
├── apache-zest-java-<RELEASE-VERSION>-src.tgz.MD5
├── apache-zest-java-<RELEASE-VERSION>-src.tgz.SHA-512
├── apache-zest-java-<RELEASE-VERSION>-src.tgz.asc
├── apache-zest-java-<RELEASE-VERSION>
├── apache-zest-java-<RELEASE-VERSION>
├── apache-zest-java-<RELEASE-VERSION>
└── apache-zest-java-<RELEASE-VERSION>

If any, make the required changes, commit them and iterate.

Close the RC branch

Once you are satisfied with the produced artifacts, close the release candidate branch:

cd zest-java
git flow release finish "<RELEASE-VERSION>-RC#"
Checkout the RC tag

To build the release candidate bits, we need to checkout the release candidate tag, that will eventually be promoted as a signed release tag, because the Apache Zest™ build system generates versionning information based on git metadata.

cd zest-java
git checkout "<RELEASE-VERSION>-RC#"
Build RC artifacts and distributions
cd zest-java
./gradlew -Dversion="<RELEASE-VERSION>" clean assemble
Stage RC maven artifacts

Stage artifacts to :

cd zest-java
./gradlew -Dversion="<RELEASE-VERSION>" uploadArchives

Close the staging Nexus repository by following the Closing the staged repository guide.

Upload RC distributions

Source and binary distributions, checksums and signatures must be uploaded to This build created these in the buid/distributions directory, named apache-zest-java-<RELEASE-VERSION>-[src|bin]*.*. As this release still is a simple candidate, we’ll rename them before upload to advertise this in their names.

# Source ZIP
cp "zest-java/build/distributions/apache-zest-java-<RELEASE-VERSION>" "zest-dist/dev/zest/apache-zest-java-<RELEASE-VERSION>"
cp "zest-java/build/distributions/apache-zest-java-<RELEASE-VERSION>" "zest-dist/dev/zest/apache-zest-java-<RELEASE-VERSION>"
cp "zest-java/build/distributions/apache-zest-java-<RELEASE-VERSION>" "zest-dist/dev/zest/apache-zest-java-<RELEASE-VERSION>"
cp "zest-java/build/distributions/apache-zest-java-<RELEASE-VERSION>" "zest-dist/dev/zest/apache-zest-java-<RELEASE-VERSION>"
# Source TAR.GZ
cp "zest-java/build/distributions/apache-zest-java-<RELEASE-VERSION>-src.tgz" "zest-dist/dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-src.tgz"
cp "zest-java/build/distributions/apache-zest-java-<RELEASE-VERSION>-src.tgz.MD5" "zest-dist/dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-src.tgz.MD5"
cp "zest-java/build/distributions/apache-zest-java-<RELEASE-VERSION>-src.tgz.SHA-512" "zest-dist/dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-src.tgz.SHA-512"
cp "zest-java/build/distributions/apache-zest-java-<RELEASE-VERSION>-src.tgz.asc" "zest-dist/dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-src.tgz.asc"
# Binary ZIP
cp "zest-java/build/distributions/apache-zest-java-<RELEASE-VERSION>" "zest-dist/dev/zest/apache-zest-java-<RELEASE-VERSION>"
cp "zest-java/build/distributions/apache-zest-java-<RELEASE-VERSION>" "zest-dist/dev/zest/apache-zest-java-<RELEASE-VERSION>"
cp "zest-java/build/distributions/apache-zest-java-<RELEASE-VERSION>" "zest-dist/dev/zest/apache-zest-java-<RELEASE-VERSION>"
cp "zest-java/build/distributions/apache-zest-java-<RELEASE-VERSION>" "zest-dist/dev/zest/apache-zest-java-<RELEASE-VERSION>"
# Binary TAR.GZ
cp "zest-java/build/distributions/apache-zest-java-<RELEASE-VERSION>-bin.tgz" "zest-dist/dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-bin.tgz"
cp "zest-java/build/distributions/apache-zest-java-<RELEASE-VERSION>-bin.tgz.MD5" "zest-dist/dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-bin.tgz.MD5"
cp "zest-java/build/distributions/apache-zest-java-<RELEASE-VERSION>-bin.tgz.SHA-512" "zest-dist/dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-bin.tgz.SHA-512"
cp "zest-java/build/distributions/apache-zest-java-<RELEASE-VERSION>-bin.tgz.asc" "zest-dist/dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-bin.tgz.asc"

And then upload them:

cd zest-dist/dev/zest
svn add * --force
svn commit -m "zest: upload <RELEASE-VERSION> to dist/dev/zest"

Run the vote

Send a "VOTE" to the developer mailing list including links to release artifacts. A VOTE always contains two parts. Send an email to the developer mailing list with the subject line:

[VOTE] Release Zest (Java Edition) version <RELEASE-VERSION>

Here is a sample template:

Dear community,

I am happy to start the VOTE thread for Apache Zest (Java Edition) <RELEASE-VERSION>!

The changelog for this release can be found here:


The distributions to be voted on are located here:

Convenience artifacts in a maven repository are staged here:

Release distributions and convenience artifacts are signed with the following key:

Please vote on releasing this package as Apache Zest (Java Edition) <RELEASE-VERSION>.

The vote is open for the next 72 hours and passes if a majority of at least three +1 PMC votes are cast and there must be more positive than negative votes.

[ ] +1 Release Apache Zest (Java Edition) <RELEASE-VERSION>
[ ]  0 I don't have a strong opinion about this, but I assume it's ok
[ ] -1 Do not release Apache Zest (Java Edition) <RELEASE-VERSION> because...

Here is my vote:

+1 (binding)


After the vote is over, send a "RESULT" email to the list with the subject line:

[RESULT][VOTE] Release Zest (Java Edition) version <RELEASE-VERSION>

Here is a sample template:

To: "Zest Developers List" <>
CC: "Zest Project Management Committee List" <>
Subject: [RESULT][VOTE] Release Zest (Java Edition) version <RELEASE-VERSION>


The vote has passed|failed with the following result:

+1 (binding): <<list of names>>
+1 (non binding): <<list of names>>

I will promote|drop the distributions and artifacts.

Votes on whether a package is ready to be released use majority approval — i.e., at least three PMC members must vote affirmatively for release, and there must be more positive than negative votes.

VOTE passes

Seal the release

Create and sign the release git tag from the unsigned release candidate tag:

cd zest-java

Push all git changes:

cd zest-java
git checkout master
git push origin master
git checkout develop
git push origin master
git push origin --tags
Publish bits

Promote the staged Nexus repository so it gets synched to Maven Central by following the Promoting a repo guide.

Move the release distributions, checksums and signatures from zest-dist/dev/zest to zest-dist/release/zest:

cd zest-dist
# Source ZIP
svn move "dev/zest/apache-zest-java-<RELEASE-VERSION>" "release/zest/apache-zest-java-<RELEASE-VERSION>"
svn move "dev/zest/apache-zest-java-<RELEASE-VERSION>" "release/zest/apache-zest-java-<RELEASE-VERSION>"
svn move "dev/zest/apache-zest-java-<RELEASE-VERSION>" "release/zest/apache-zest-java-<RELEASE-VERSION>"
svn move "dev/zest/apache-zest-java-<RELEASE-VERSION>" "release/zest/apache-zest-java-<RELEASE-VERSION>"
# Source TAR.GZ
svn move "dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-src.tgz" "release/zest/apache-zest-java-<RELEASE-VERSION>-src.tgz"
svn move "dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-src.tgz.MD5" "release/zest/apache-zest-java-<RELEASE-VERSION>-src.tgz.MD5"
svn move "dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-src.tgz.SHA-512" "release/zest/apache-zest-java-<RELEASE-VERSION>-src.tgz.SHA-512"
svn move "dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-src.tgz.asc" "release/zest/apache-zest-java-<RELEASE-VERSION>-src.tgz.asc"
# Binary ZIP
svn move "dev/zest/apache-zest-java-<RELEASE-VERSION>" "release/zest/apache-zest-java-<RELEASE-VERSION>"
svn move "dev/zest/apache-zest-java-<RELEASE-VERSION>" "release/zest/apache-zest-java-<RELEASE-VERSION>"
svn move "dev/zest/apache-zest-java-<RELEASE-VERSION>" "release/zest/apache-zest-java-<RELEASE-VERSION>"
svn move "dev/zest/apache-zest-java-<RELEASE-VERSION>" "release/zest/apache-zest-java-<RELEASE-VERSION>"
# Binary TAR.GZ
svn move "dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-bin.tgz" "release/zest/apache-zest-java-<RELEASE-VERSION>-bin.tgz"
svn move "dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-bin.tgz.MD5" "release/zest/apache-zest-java-<RELEASE-VERSION>-bin.tgz.MD5"
svn move "dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-bin.tgz.SHA-512" "release/zest/apache-zest-java-<RELEASE-VERSION>-bin.tgz.SHA-512"
svn move "dev/zest/apache-zest-java-<RELEASE-VERSION>-RC#-bin.tgz.asc" "release/zest/apache-zest-java-<RELEASE-VERSION>-bin.tgz.asc"

And upload them:

cd zest-dist
svn commit -m "zest: <RELEASE-VERSION>-RC# vote passed, promoted as <RELEASE-VERSION> release"
Wait 24 hours

For mirrors to pick up the new bits.

Prepare an announcement

Coordinate a press release with


You can reuse the release-notes content from the txt/adoc/md files created earlier.

This annoucement will be used in a variety of media like emails, websites etc… Start with a text version and once satisfied create at least a Markdown version for the website, see below.

Update the Zest™ website

Generate the documentation and javadoc minisite:

cd zest-java
./gradlew -Dversion="<RELEASE-VERSION>" archiveJavadocs manuals

This will automatically put all files into the zest-web website repository.

Create a new post on the Zest™ website by creating a new Markdown file:

cd zest-web
touch "site/src/_posts/YYYY-MM-DD-apache-zest-java-<RELEASE-VERSION>.md"
open !$

You can reuse the Markdown formatted announcement content.

Add the new released version in zest-web/site/content/java/versions.json below the latest entry:

    "develop": "develop",
    "latest": "latest",
    "2.0": "2.0",
    "<=1.4.x": "1.4"

Finally, edit zest-web/site/src/_data/releases.yml with the new release data. Upmost is the latest:

- version: <RELEASE-VERSION>
  announcement: YYYY/MM/DD/apache-zest-java-<RELEASE-VERSION>
  signer: John Doe
  pgpId: FB751943

You can run the Zest™ website locally:

cd zest-web
jekyll serve

Open to live-preview your changes.

Once you are satisfied with the changes, build the production website:

cd zest-web
jekyll build

And publish it:

svn add * --force
svn commit -m "zest: update website"
Register the release

Register the new release at


Finally, send an announcement to dev@ and users@ mailing lists. Email announcements should have the subject line:

[ANNOUNCE] Released Zest (Java Edition) version <RELEASE-VERSION>

The announcement email should contains the release-notes as text, remember they are in the apache-zest-java-<RELEASE-VERSION>-release-notes.txt file you created earlier.

VOTE fails

Record failure

We keep the release candidate git history. It can be useful for reviewers to have access to it. Remember, we created a release candidate branch and tags, no signed release tag.

cd zest-java
git checkout master
git push origin master
git checkout develop
git push origin master
git push origin --tags
Drop RC artifacts and distributions

Drop the Nexus staging repository by following the Dropping a repo guide.

Drop distributions, checksums and signatures from zest-dist/dev/zest

cd zest-dist/dev/zest/
svn add * --force
svn commit -m "zest: dropping <RELEASE-VERSION>-RC# from dist/dev/zest as the vote failed"
Start over

If a new RC is to be created, restart the process as described above.