////
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements.  See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License.  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
////
= Release Process

This document describes the steps required to release a version of TinkerPop.  The release is handled by a "release
manager" (a committer fulfills this role), who ensures that the steps in this document are executed. The process is
multi-phased and can therefore take several weeks to complete given the time needed for Apache voting and community
feedback.  Once a release point has been identified, the following phases represent the flow of "release":

* Release manager key setup.
* Pre-flight check.
* Optionally, produce a release candidate for community feedback.
* Submit the official release for PMC vote.
* Release and promote.

NOTE: It might be helpful to use this document as generated from the currently release as opposed to one generate
from a previous version or from recent `SNAPSHOT`. When using one generated for release, all the "versions" in the
commands end up being set to the version that is being released, making cut and paste of those commands less labor
intensive and error prone.

IMPORTANT: The following instructions assume that the release manager's <<development-environment,environment>> is setup
properly for release and includes a `.glv` file in `gremlin-python` as described in the <<python-environment,Python Environment>>
section, so that the `gremlin-python` module builds in full.

=== Development Versions

A "development version" or snapshot (in Java parlance) is not an "official" release. Artifacts produced for a
snapshot are solely for the convenience of providers and other developers who want to use the latest releases of
TinkerPop. These releases do not require a VOTE and do not require a "release manager". Any PMC member can deploy them.
It is important to note that these releases cannot be promoted outside of the developer mailing list and should not be
recommended for use beyond the purpose of evaluation and testing.

IMPORTANT: A development release must contain the suffix "-SNAPSHOT" in the `pom.xml`.

For JVM-based artifacts, simply use the following command:

[source,text]
mvn clean deploy

and artifacts will be pushed to the link:http://repository.apache.org/snapshots/[Apache Snapshot Repository]. Python
development artifacts must be generated and deployed separately with additional commands:

[source,text]
mvn clean install -Pglv-python
mvn deploy -pl gremlin-python -Dpypi

Python does not use the snapshot model the JVM does, however, the build is smart in that it will dynamically
generate a development version number for the Python artifacts when "-SNAPSHOT" is in the `pom.xml`. The previous
command will push the development version to link:https://pypi.python.org/pypi/gremlinpython/[pypi] for distribution.
Use the `testpypi` test environment by updating the `gremlin-python/pom.xml` to verify the `mvn deploy` command works.

IMPORTANT: The `clean` in the above commands is more important to the pypi deployment because the process will deploy
anything found in the `target/python-packaged/dist` directory. Since the names of the artifacts are based on
timestamps, they will not overwrite one another and multiple artifacts will get uploaded.

For .NET and NuGet, development artifacts can be created as follows:

[source,text]
mvn clean install -pl :gremlin-dotnet,:gremlin-dotnet-source -Dnuget
mvn deploy -pl :gremlin-dotnet-source -Dnuget

As with PyPi, NuGet does not support a snapshot model as Java does. The commands above will dynamically generate a
version number when "-SNAPSHOT" is in the `pom.xml`. Use the `staging.nuget.org` environment by updating the
`gremlin-dot-source/pom.xml` to ensure the `mvn deploy` command works.

IMPORTANT: These commands will dynamically edit the `gremlin-dotnet-source/Gremlin.Net.csproj`. Take care to commit
or not commit changes related to that as necessary.

== Release Manager Requirements

If this is your first time as release manager, you will need to setup keys for signing purposes per the Apache
release process.  Generally speaking, this will mean that you will need to generate a key-pair and then upload your
public key to a public keyserver.

For a general overview of key basics, refer to link:https://www.apache.org/dev/release-signing.html#key-basics[this].  For detailed
step-by-step instructions, please follow the instructions link:https://www.apache.org/dev/openpgp.html#generate-key[here].

After completing the key-pair setup instructions, be sure to add yourself to the `PGP signature` section of `bin/validate-distribution.sh`.

[source,text]
----
echo -n "  * PGP signature ... "
[ `gpg ${ZIP_FILENAME}.asc 2>&1 | grep -c '^gpg: Good signature from "Stephen Mallette <spmallette@apache.org>"$'` -eq 1 ] || \
[ `gpg ${ZIP_FILENAME}.asc 2>&1 | grep -c '^gpg: Good signature from "Marko Rodriguez <okram@apache.org>"$'` -eq 1 ] || \
[ `gpg ${ZIP_FILENAME}.asc 2>&1 | grep -c '^gpg: Good signature from "Theodore Ratte Wilmes (CODE SIGNING KEY) <twilmes@apache.org>"'` -eq 1 ] || \
{ echo "failed"; exit 1; }
echo "OK"
----

== Pre-flight Check

The "pre-flight check" is a list of things performed by the release manager during the weeks leading up to a scheduled
day to release.  These checks will help to ensure that that release day goes smoothly by identifying problems up early
and communicating with other members of the community.

. Fourteen days before release, issue an email to the dev mailing list to remind the community of the pending release.
.. Note any important issues open in JIRA in that post.
.. Request review and update of the "upgrade documentation" and CHANGELOG.
. Seven days before release, announce the code freeze on the dev mailing list to remind the community that the branch
under release is protected. Tweaks to documentation and other odds and ends related to release are still allowed
during this period.
. At some point during the week:
.. Run the full integration test suite: `mvn clean install -DskipIntegrationTests=false -DincludeNeo4j`
.. Deploy a final SNAPSHOT to the snapshot repository as well as GLV pre-releases.
.. Review LICENSE and NOTICE files to make sure that no <<dependencies,changes are needed>>.
.. Review javadoc filters on the "Core API" docs to be sure nothing needs to change.
.. Review JIRA tickets in the release and ensure that:
... All tickets categorized by having a "Component" assigned.
... All tickets are either of type "Bug" or "Improvement".
... All tickets where work was completed are "Closed"
.... Search for "closed the pull request" in comments for hints on possible tickets that were left open by mistake.
.... Look for tickets marked as "Resolved" as some users might not have rights to mark as "Closed" - convert these to "Closed".
... All tickets not marked "Fixed", "Done", or "Implemented" for their Resolution should not have a Fix Version
assigned (use common sense when reviewing these tickets before removing the Fix Version as it is possible the incorrect
Resolution may have been assigned).
.. Be sure that `gremlin-io-test` has been updated (from 3.3.0 on - this module was not available prior to the 3.3.x line)
... This is typically a post-release task, but it's worthing checking to be sure in case the step was somehow overlooked.
... Instructions for updating the module are described in the <<io,IO Documentation and Testing Section>>.
. When all documentation changes are in place, use `bin/publish-docs.sh` to deploy a final `SNAPSHOT` representation
of the docs and thus validate that there are no issues with the documentation generation process. Request review
of the published documentation on the dev mailing list.

== Release Candidate

A release candidate is an unofficial release that is represented by a tagged version in the Git repository.  It is
offered in cases where there is significant change in a particular version and the potential for upgrades and problems
might be high. Release candidates do not require a vote thread. Lazy consensus is acceptable for confirming their
deployment.

. `mvn clean install -DincludeNeo4j`
.. `mvn verify -DskipIntegrationTests=false -DincludeNeo4j`
. `bin/publish-docs.sh <username>` - note that under a release candidate the documentation is published as SNAPSHOT
. `mvn versions:set -DnewVersion=xx.yy.zz -DgenerateBackupPoms=false` to update the project files to reference a non-SNAPSHOT version
. `pushd gremlin-console/bin; ln -fs ../target/apache-tinkerpop-gremlin-console-xx.yy.zz-standalone/bin/gremlin.sh gremlin.sh; popd`
. `git diff` and review the updated files
. `git commit -a -m "TinkerPop xx.yy.zz release"` and `git push`
. `git tag -a -m "TinkerPop xx.yy.zz release" xx.yy.zz` and `git push --tags`
. `mvn clean install`
. `mvn versions:set -DnewVersion=xx.yy.zz-SNAPSHOT -DgenerateBackupPoms=false` to go back to SNAPSHOT
. `pushd gremlin-console/bin; ln -fs ../target/apache-tinkerpop-gremlin-console-xx.yy.zz-SNAPSHOT-standalone/bin/gremlin.sh gremlin.sh; popd`
. `git commit -a -m "Returned to xx.yy.zz-SNAPSHOT"` and `git push`
. Announce the release candidate to `dev` mailing list and await feedback
. Repeat as required or proceed to the next phase

Note that release candidates need not require the release of all artifacts. For example, if the risk is with one
particular GLV, then a release candidate can be prepared of just that particular artifact. In those cases, a tag on
the commit that represents the release candidate is sufficient and does not necessarily require that the versions
be bumped to reflect the actual "-rc" version. In other words, if preparing a release candidate for .NET, then there
is no need to go through the processing of bumping versions in Java artifacts and all GLVs. Nor is it necessary to
alter the version of .NET to include the release candidate versioning. It can simply be altered locally by the
release manager and deployed.

== PMC Vote

This section describes the process that process that prepares a release for VOTE by the community. If there are multiple
releases (as there usually are) being prepared, it may be best for downstream releases to wait for upstream releases
to complete their process to assure that no last minute commits are required to get the upstream release completed.
It is up to the discretion of the release managers to decide how they wish to proceed with respect to preparing releases
in parallel or in a more serial fashion.

. By this point, the testing performed during the code freeze should have validated the release.  If however there
are additional tests to perform that the release manager feels are relevant, they should be performed now. In other
words, there is no need to rebuild the `SNAPSHOT` yet another time unless there are circumstances that would call its
validity into question.
. Update `CHANGELOG.asciidoc`:
.. Update the release date - the release date is the date of the vote. Double check the header to be sure that it is
formatted properly - the easiest way to is to view the `CHANGELOG.asciidoc` to be sure that it produces a link in the
GitHub viewer.
.. Generate the JIRA release notes report for the current version and append them to the `CHANGELOG.asciidoc`.
... Use an "advanced" search to filter out JIRA issues already released on other versions. For example:
`project = TINKERPOP and status = Closed AND fixVersion = 3.2.0 AND fixVersion not in (3.1.3, 3.1.2, 3.1.1, 3.1.0) ORDER BY type, Id ASC`.
... Consider use of an "Excel" export to organize and prepare the JIRA tickets to be pasted to `CHANGELOG.asciidoc`.
This formula can help construct each line item for the CHANGELOG if column `A` is the issue number, `B` is the
issue title and `D` is the label field: `="* "&A2&" "&B2&(IF(D2="breaking"," \*(breaking)*",""))`
... Be sure to include a link to other versions in the `CHANGELOG.asciidoc` that were previously released while the
current release was under development as this new release will have those changes included within it. Please see
3.2.1 for an example.
.. Format "breaking" changes to be clearly marked (use JIRA and the "breaking" label to identify those)
. Update "upgrade documentation":
.. Update the release date.
.. Update the link to `CHANGELOG.asciidoc` - this link may already be correct but will not exist until the repository is tagged.
. Update homepage with references in `/site` to latest distribution and to other internal links elsewhere on the page.
.. This step should only be performed by the release manager for the newest line of code (i.e. if release 3.3.x, 3.2.x and 3.1.x,
then only do this step for 3.3.x, but update the site for 3.2.x and 3.1.x).
.. Update the `template/header-footer.html`.
.. Update `index.html`.
.. Update link:http://tinkerpop.apache.org/downloads.html[Downloads] page, when moving "Current Releases" to "Archived
Releases" recall that the hyperlink must change to point to version in the link:https://archive.apache.org/dist/tinkerpop/[Apache Archives].
.. Preview changes locally with `bin/generate-home.sh` then commit changes to git.
. `mvn versions:set -DnewVersion=xx.yy.zz -DgenerateBackupPoms=false` to update project files to reference the non-SNAPSHOT version
. `pushd gremlin-console/bin; ln -fs ../target/apache-tinkerpop-gremlin-console-xx.yy.zz-standalone/bin/gremlin.sh gremlin.sh; popd`
. `git diff` and review the updated files
. `mvn clean install` - need to build first so that the right version of the console is used with `bin/publish-docs.sh`
.. This step should update the Gremlin.Net project file and Gremlin Javascript package file with the newly bumped version.
. `git commit -a -m "TinkerPop xx.yy.zz release"` and push
. `bin/process-docs.sh` and validate the generated documentation locally. Don't rely on "BUILD SUCCESS" - scroll up through logs to ensure there were no errors and view the HTML directly. Code blocks that did not execute properly have a gray background and do not show the results of the commands.
. `bin/publish-docs.sh <username>` - Note that this step requires no additional processing as the previous step handled
document generation and this step now merely needs to upload what was generated. Note that this step will be responsible
for generating javadoc and without that the binary distributions won't contain that documentation.
. `mvn deploy -Papache-release -DcreateChecksum=true -DskipTests` - deploy signed artifacts with checksums to link:https://repository.apache.org/[Apache Nexus].
. Review generated artifacts to be sure they have both javadocs and asciidocs present (request another committer to review as well) then "close" the repo - if the repo is left open it will be automatically dropped after five days and closing the repo will allow it to stay available for a full ninety days which is more than enough time to complete a vote. Do NOT "release" the repository at this time.
. Upload artifacts to `https://dist.apache.org/repos/dist/dev/tinkerpop` for `[VOTE]` review.
.. Use `svn rm` to delete past versions that were up for review in the same line of code. In other words, if uploading 3.2.3 then remove instances of 3.2.2 or any other past 3.2.x releases.
.. `svn co --depth empty https://dist.apache.org/repos/dist/dev/tinkerpop/ dev` and `mkdir dev/xx.yy.zz`
.. `cp ~/.m2/repository/org/apache/tinkerpop/gremlin-console/xx.yy.zz/gremlin-console-xx.yy.zz-distribution.zip* dev/xx.yy.zz`
.. `cp ~/.m2/repository/org/apache/tinkerpop/gremlin-server/xx.yy.zz/gremlin-server-xx.yy.zz-distribution.zip* dev/xx.yy.zz`
.. `cp ~/.m2/repository/org/apache/tinkerpop/tinkerpop/xx.yy.zz/tinkerpop-xx.yy.zz-source-release.zip* dev/xx.yy.zz`
.. `rm -f dev/*.md5
.. `cd dev/xx.yy.zz`
.. pass:[<code>ls * | xargs -n1 -I {} echo "mv apache-tinkerpop-{} {}" | sed -e 's/distribution/bin/' -e 's/source-release/src/' -e 's/tinkerpop-tinkerpop/tinkerpop/' -e s'/^\(.*\) \(.*\) \(.*\)$/\1 \3 \2/' | /bin/bash</code>]
.. `cd ..; svn add xx.yy.zz/; svn ci -m "TinkerPop xx.yy.zz release"`
. Execute `bin/validate-distribution.sh` and any other relevant testing.
. `git tag -a -m "TinkerPop xx.yy.zz release" xx.yy.zz` and `git push --tags`
. Submit for `[VOTE]` at `dev@tinkerpop.apache.org` (see email template below)
. *Wait for vote acceptance* (72 hours)

== Release & Promote

. Login to link:https://repository.apache.org/[Apache Nexus] and release the previously closed repository.
. Deploy the GLVs
.. This build will likely occur from the tag for the release, so be sure to checkout the tag first before executing this step.
.. `mvn clean install -DskipTests -Dnuget`
.. `mvn deploy -pl gremlin-python -DskipTests -Dpypi`
.. `mvn deploy -pl :gremlin-dotnet-source -DskipTests -Dnuget`
.. `mvn deploy -pl gremlin-javascript -DskipTests -Dnpm`
. `svn co --depth empty https://dist.apache.org/repos/dist/dev/tinkerpop dev; svn up dev/xx.yy.zz`
. `svn co --depth empty https://dist.apache.org/repos/dist/release/tinkerpop release; mkdir release/xx.yy.zz`
. Copy release files from `dev/xx.yy.zz` to `release/xx.yy.zz`.
. `cd release; svn add xx.yy.zz/; svn ci -m "TinkerPop xx.yy.zz release"`
. Wait for Apache Sonatype to sync the artifacts to Maven Central at (link:http://repo1.maven.org/maven2/org/apache/tinkerpop/tinkerpop/[http://repo1.maven.org/maven2/org/apache/tinkerpop/tinkerpop/]).
. Report the release through link:https://reporter.apache.org/addrelease.html?tinkerpop[reporter.apache.org] (an email reminder should arrive shortly following the svn command above to do the release)
. Wait for zip distributions to to sync to the Apache mirrors (i.e ensure the download links work from a mirror).
. `bin/publish-home.sh <username>` to publish the updated web site with new releases.
. Execute `bin/update-current-docs.sh` to migrate to the latest documentation set for `/current`.
. This step should only occur after the website is updated and all links are working. If there are releases present in
SVN that represents lines of code that are no longer under development, then remove those releases. In other words,
if `3.2.0` is present and `3.2.1` is released then remove `3.2.0`.  However, if `3.1.3` is present and that line of
code is still under potential development, it may stay.
. Announce release on `dev@`/`gremlin-users@` mailing lists and tweet from `@apachetinkerpop`

== Post-release Tasks

A number of administration tasks should be taken care of after release is public. Some of these items can be performed
during the VOTE period at the release manager's discretion, though it may be wise to wait until a successful VOTE is
eminent before reopening development:

. Perform JIRA administration tasks:
.. "Release" the current version and set the "release date"
.. If there is to be a follow on release in the current line of code, create that new version specifying the "start date"
. Prepare Git administration tasks. Apply the following steps as needed per release branch:
.. Make the appropriate branching changes as required by the release and bump the version to `SNAPSHOT` with
`mvn versions:set -DnewVersion=xx.yy.zz-SNAPSHOT -DgenerateBackupPoms=false`.
.. `pushd gremlin-console/bin; ln -fs ../target/apache-tinkerpop-gremlin-console-xx.yy.zz-SNAPSHOT-standalone/bin/gremlin.sh gremlin.sh; popd`
.. Update CHANGELOG and upgrade docs to have the appropriate headers for the next version.
.. `mvn clean install -DskipTests` - need to build first so that the right version of the console is used with `bin/publish-docs.sh`
.. `mvn deploy -DskipTests` - deploy the new `SNAPSHOT`
.. `bin/process-docs.sh` and validate the generated `SNAPSHOT` documentation locally and then `bin/publish-docs.sh <username>`
.. Commit and push the `SNAPSHOT` changes to git
. Send email to advise that code freeze is lifted.
. Generate a list of dead branches that will be automatically deleted and post them as a DISCUSS thread for review, then once consensus is reached removed those branches.
. Set up the IO tests for the current `SNAPSHOT` as discussed in the <<io,IO Documentation and Testing Section>>

== Email Templates

=== Release VOTE

[source,text]
----
Subject: [VOTE] TinkerPop xx.yy.zz Release

Hello,

We are happy to announce that TinkerPop xx.yy.zz is ready for release.

The release artifacts can be found at this location:
	https://dist.apache.org/repos/dist/dev/tinkerpop/xx.yy.zz/

The source distribution is provided by:
	apache-tinkerpop-xx.yy.zz-src.zip

Two binary distributions are provided for user convenience:
	apache-tinkerpop-gremlin-console-xx.yy.zz-bin.zip
	apache-tinkerpop-gremlin-server-xx.yy.zz-bin.zip

The GPG key used to sign the release artifacts is available at:
    https://dist.apache.org/repos/dist/dev/tinkerpop/KEYS

The online docs can be found here:
	http://tinkerpop.apache.org/docs/xx.yy.zz/ (user docs)
	http://tinkerpop.apache.org/docs/xx.yy.zz/upgrade/ (upgrade docs)
	http://tinkerpop.apache.org/javadocs/xx.yy.zz/core/ (core javadoc)
	http://tinkerpop.apache.org/javadocs/xx.yy.zz/full/ (full javadoc)

The tag in Apache Git can be found here:
	https://git-wip-us.apache.org/repos/asf?p=tinkerpop.git;XXXXXXXXXXXXXXXXXX

The release notes are available here:
	https://github.com/apache/tinkerpop/blob/master/CHANGELOG.asciidoc#XXXXXXXXXXXXXXXXXX

The [VOTE] will be open for the next 72 hours --- closing <DayOfTheWeek> (<Month> <Day> <Year>) at <Time> <TimeZone>.

My vote is +1.

Thank you very much,
<TinkerPop Committer Name>
----

=== Dev Release RESULT VOTE

[source,text]
----
Subject: [RESULT][VOTE] TinkerPop xx.yy.zz Release

This vote is now closed with a total of X +1s, no +0s and no -1s. The results are:

BINDING VOTES:

+1  (X -- list of voters)
0   (0)
-1  (0)

NON-BINDING VOTES:

+1 (X -- list of voters)
0  (0)
-1 (0)

Thank you very much,
<TinkerPop Committer Name>
----

=== General Release Announcement

The template below refers to the "name of release line" and the "release line logo". Every release line has a name
and logo. For example, 3.1.x had the name, "A 187 On The Undercover Gremlinz" and the logo shown
link:http://tinkerpop.apache.org/docs/current/upgrade/#_tinkerpop_3_1_0[here] in the upgrade documentation.

[source,text]
----
Subject: TinkerPop xx.yy.zz Released: [name of release line]

Hello,

TinkerPop xx.yy.zz has just been released. [some text to introduce the release - e.g. whether or not
there is breaking change, an important game-changing feature or two, etc.]

The release artifacts can be found at this location:

https://www.apache.org/dyn/closer.lua/tinkerpop/xx.yy.zz/apache-tinkerpop-gremlin-console-xx.yy.zz-bin.zip
https://www.apache.org/dyn/closer.lua/tinkerpop/xx.yy.zz/apache-tinkerpop-gremlin-server-xx.yy.zz-bin.zip
https://www.apache.org/dyn/closer.lua/tinkerpop/xx.yy.zz/apache-tinkerpop-xx.yy.zz-src.zip

The online docs can be found here:

http://tinkerpop.apache.org/docs/xx.yy.zz/reference/ (user docs)
http://tinkerpop.apache.org/docs/xx.yy.zz/upgrade/#XXXXXXXXXXXXXXXXXX (upgrade docs)
http://tinkerpop.apache.org/javadocs/xx.yy.zz/core/ (core javadoc)
http://tinkerpop.apache.org/javadocs/xx.yy.zz/full/ (full javadoc)
http://tinkerpop.apache.org/docs/xx.yy.zz/some-new-content/ (some new content) [NEW!]

The release notes are available here:

https://github.com/apache/tinkerpop/blob/xx.yy.zz/CHANGELOG.asciidoc#XXXXXXXXXXXXXXXXXX

The Central Maven repo has sync'd as well:

https://repo1.maven.org/maven2/org/apache/tinkerpop/tinkerpop/xx.yy.zz/

Python artifacts are available in pypi:

https://pypi.python.org/pypi/gremlinpython/xx.yy.zz

.NET artifacts are available in NuGet:

https://www.nuget.org/packages/Gremlin.Net/xx.yy.zz

Javascript artifacts are available in npm:

https://www.npmjs.com/package/gremlin

[include the release line logo image]
----
