Add release-announcement.py imported from gerrit project

Imported as-is from gerrit master at 23f9be8eba3ca4877b21da95ebce15e59c997e16

Change-Id: Id939482022c45d3ee74fcca8f2a6e4b6c20c7177
diff --git a/release-announcement-template.txt b/release-announcement-template.txt
new file mode 100644
index 0000000..2702f57
--- /dev/null
+++ b/release-announcement-template.txt
@@ -0,0 +1,26 @@
+Gerrit version {{ data.version }} is now available.{% if data.summary %} {{ data.summary }} {% endif %}Please see the release notes for details.
+
+Release Notes:
+https://www.gerritcodereview.com/releases/{{ data.version.major }}.md{% if data.version.patch %}#{{ data.version.patch }}{% endif %}
+
+Documentation:
+http://gerrit-documentation.storage.googleapis.com/Documentation/{{ data.version }}/index.html
+{% if data.previous %}
+Log of changes since {{ data.previous }}:
+https://gerrit.googlesource.com/gerrit/+log/v{{ data.previous }}..v{{ data.version }}?no-merges
+{% endif %}
+Download:
+https://gerrit-releases.storage.googleapis.com/gerrit-{{ data.version }}.war
+
+SHA1:
+{{ data.sha1 }}
+
+SHA256:
+{{ data.sha256 }}
+
+MD5:
+{{ data.md5 }}
+
+Maintainers' public keys:
+https://www.gerritcodereview.com/releases/public-keys.md
+
diff --git a/release-announcement.py b/release-announcement.py
new file mode 100644
index 0000000..a25a340
--- /dev/null
+++ b/release-announcement.py
@@ -0,0 +1,156 @@
+#!/usr/bin/env python
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed 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.
+
+# Generates the text to paste into the email for announcing a new
+# release of Gerrit. The text is generated based on a template that
+# is filled with values either passed to the script or calculated
+# at runtime.
+#
+# The script outputs a plain text file with the announcement text:
+#
+#   release-announcement-gerrit-X.Y.txt
+#
+# and, if GPG is available, the announcement text wrapped with a
+# signature:
+#
+#   release-announcement-gerrit-X.Y.txt.asc
+#
+# Usage:
+#
+#   ./tools/release-announcement.py -v 2.14.2 -p 2.14.1 \
+#      -s "This release fixes several bugs since 2.14.1"
+#
+# Parameters:
+#
+#   --version (-v): The version of Gerrit being released.
+#
+#   --previous (-p): The previous version of Gerrit.  Optional. If
+#   specified, the generated text includes a link to the gitiles
+#   log of commits between the previous and new versions.
+#
+#   --summary (-s): Short summary of the release. Optional. When
+#   specified, the summary is inserted in the introductory sentence
+#   of the generated text.
+#
+# Prerequisites:
+#
+# - The Jinja2 python library [1] must be installed.
+#
+# - For GPG signing to work, the python-gnupg library [2] must be
+#   installed, and the ~/.gnupg folder must exist.
+#
+# - The war file must have been installed to the local Maven repository
+#   using the `./tools/mvn/api.sh war_install` command.
+#
+# [1] http://jinja.pocoo.org/
+# [2] http://pythonhosted.org/gnupg/
+
+
+from __future__ import print_function
+import argparse
+import hashlib
+import os
+import sys
+from gnupg import GPG
+from jinja2 import Template
+
+
+class Version:
+    def __init__(self, version):
+        self.version = version
+        parts = version.split('.')
+        if len(parts) > 2:
+            self.major = ".".join(parts[:2])
+            self.patch = version
+        else:
+            self.major = version
+            self.patch = None
+
+    def __str__(self):
+        return self.version
+
+
+def _main():
+    descr = 'Generate Gerrit release announcement email text'
+    parser = argparse.ArgumentParser(
+        description=descr,
+        formatter_class=argparse.ArgumentDefaultsHelpFormatter)
+    parser.add_argument('-v', '--version', dest='version',
+                        required=True,
+                        help='gerrit version to release')
+    parser.add_argument('-p', '--previous', dest='previous',
+                        help='previous gerrit version (optional)')
+    parser.add_argument('-s', '--summary', dest='summary',
+                        help='summary of the release content (optional)')
+    options = parser.parse_args()
+
+    summary = options.summary
+    if summary and not summary.endswith("."):
+        summary = summary + "."
+
+    data = {
+        "version": Version(options.version),
+        "previous": options.previous,
+        "summary": summary
+    }
+
+    war = os.path.join(
+        os.path.expanduser("~/.m2/repository/com/google/gerrit/gerrit-war/"),
+        "%(version)s/gerrit-war-%(version)s.war" % data)
+    if not os.path.isfile(war):
+        print("Could not find war file for Gerrit %s in local Maven repository"
+              % data["version"], file=sys.stderr)
+        sys.exit(1)
+
+    md5 = hashlib.md5()
+    sha1 = hashlib.sha1()
+    sha256 = hashlib.sha256()
+    BUF_SIZE = 65536  # Read data in 64kb chunks
+    with open(war, 'rb') as f:
+        while True:
+            d = f.read(BUF_SIZE)
+            if not d:
+                break
+            md5.update(d)
+            sha1.update(d)
+            sha256.update(d)
+
+    data["sha1"] = sha1.hexdigest()
+    data["sha256"] = sha256.hexdigest()
+    data["md5"] = md5.hexdigest()
+
+    template = Template(open("tools/release-announcement-template.txt").read())
+    output = template.render(data=data)
+
+    filename = "release-announcement-gerrit-%s.txt" % data["version"]
+    with open(filename, "w") as f:
+        f.write(output)
+
+    gpghome = os.path.abspath(os.path.expanduser("~/.gnupg"))
+    if not os.path.isdir(gpghome):
+        print("Skipping signing due to missing gnupg home folder")
+    else:
+        try:
+            gpg = GPG(homedir=gpghome)
+        except TypeError:
+            gpg = GPG(gnupghome=gpghome)
+        signed = gpg.sign(output)
+        filename = filename + ".asc"
+        with open(filename, "w") as f:
+            f.write(str(signed))
+
+
+if __name__ == "__main__":
+    _main()