mirror of https://github.com/Icinga/icinga2.git
Merge pull request #7146 from Icinga/feature/update-release-docs
Update release procedure
This commit is contained in:
commit
8edcba772d
|
@ -1,4 +1,10 @@
|
||||||
# Icinga 2.x CHANGELOG
|
# Icinga 2 CHANGELOG
|
||||||
|
|
||||||
|
Please make sure to always read our [Upgrading](https://icinga.com/docs/icinga2/latest/doc/16-upgrading-icinga-2/)
|
||||||
|
documentation before switching to a new version.
|
||||||
|
|
||||||
|
Released closed milestones can be found [here](https://github.com/Icinga/icinga2/milestones?state=closed).
|
||||||
|
|
||||||
|
|
||||||
## 2.10.4 (2019-03-19)
|
## 2.10.4 (2019-03-19)
|
||||||
|
|
||||||
|
|
53
RELEASE.md
53
RELEASE.md
|
@ -68,28 +68,10 @@ sed -i "s/Version: .*/Version: $VERSION/g" VERSION
|
||||||
|
|
||||||
## Changelog <a id="changelog"></a>
|
## Changelog <a id="changelog"></a>
|
||||||
|
|
||||||
Update the [CHANGELOG.md](CHANGELOG.md) file.
|
Link to the milestone and closed=1 as filter.
|
||||||
|
|
||||||
### Requirements
|
Manually update the best of collected from the
|
||||||
|
milestone description.
|
||||||
Export these environment variables:
|
|
||||||
|
|
||||||
```
|
|
||||||
export ICINGA_GITHUB_AUTH_USERNAME='user'
|
|
||||||
export ICINGA_GITHUB_AUTH_TOKEN='token'
|
|
||||||
export ICINGA_GITHUB_PROJECT='icinga/icinga2'
|
|
||||||
```
|
|
||||||
|
|
||||||
### Generation
|
|
||||||
|
|
||||||
**Close the version on [GitHub](https://github.com/Icinga/icinga2/milestones).**
|
|
||||||
|
|
||||||
Run the script which updates the [CHANGELOG.md](CHANGELOG.md) file.
|
|
||||||
|
|
||||||
```
|
|
||||||
./changelog.py
|
|
||||||
git diff
|
|
||||||
```
|
|
||||||
|
|
||||||
## Git Tag <a id="git-tag"></a>
|
## Git Tag <a id="git-tag"></a>
|
||||||
|
|
||||||
|
@ -289,9 +271,9 @@ docker run -ti debian:stretch bash
|
||||||
apt-get update && apt-get install -y wget curl gnupg apt-transport-https
|
apt-get update && apt-get install -y wget curl gnupg apt-transport-https
|
||||||
|
|
||||||
DIST=$(awk -F"[)(]+" '/VERSION=/ {print $2}' /etc/os-release); \
|
DIST=$(awk -F"[)(]+" '/VERSION=/ {print $2}' /etc/os-release); \
|
||||||
echo "deb http://packages.icinga.com/debian icinga-${DIST} main" > \
|
echo "deb https://packages.icinga.com/debian icinga-${DIST} main" > \
|
||||||
/etc/apt/sources.list.d/${DIST}-icinga.list
|
/etc/apt/sources.list.d/${DIST}-icinga.list
|
||||||
echo "deb-src http://packages.icinga.com/debian icinga-${DIST} main" >> \
|
echo "deb-src https://packages.icinga.com/debian icinga-${DIST} main" >> \
|
||||||
/etc/apt/sources.list.d/${DIST}-icinga.list
|
/etc/apt/sources.list.d/${DIST}-icinga.list
|
||||||
|
|
||||||
curl https://packages.icinga.com/icinga.key | apt-key add -
|
curl https://packages.icinga.com/icinga.key | apt-key add -
|
||||||
|
@ -303,6 +285,13 @@ icinga2 daemon
|
||||||
|
|
||||||
Create a new release for the newly created Git tag: https://github.com/Icinga/icinga2/releases
|
Create a new release for the newly created Git tag: https://github.com/Icinga/icinga2/releases
|
||||||
|
|
||||||
|
> Hint: Choose [tags](https://github.com/Icinga/icinga2/tags), pick one to edit and
|
||||||
|
> make this a release. You can also create a draft release.
|
||||||
|
|
||||||
|
The release body should contain a short changelog, with links
|
||||||
|
into the roadmap, changelog and blogpost.
|
||||||
|
|
||||||
|
|
||||||
## Chocolatey <a id="chocolatey"></a>
|
## Chocolatey <a id="chocolatey"></a>
|
||||||
|
|
||||||
Navigate to the git repository on your Windows box which
|
Navigate to the git repository on your Windows box which
|
||||||
|
@ -328,6 +317,8 @@ choco push Icinga2-v2.10.0.nupkg --source https://push.chocolatey.org/
|
||||||
|
|
||||||
### Online Documentation <a id="online-documentation"></a>
|
### Online Documentation <a id="online-documentation"></a>
|
||||||
|
|
||||||
|
> Only required for major releases.
|
||||||
|
|
||||||
Navigate to `puppet-customer/icinga.git` and do the following steps:
|
Navigate to `puppet-customer/icinga.git` and do the following steps:
|
||||||
|
|
||||||
#### Testing
|
#### Testing
|
||||||
|
@ -336,12 +327,12 @@ Navigate to `puppet-customer/icinga.git` and do the following steps:
|
||||||
git checkout testing && git pull
|
git checkout testing && git pull
|
||||||
vim files/var/www/docs/config/icinga2-latest.yml
|
vim files/var/www/docs/config/icinga2-latest.yml
|
||||||
|
|
||||||
git commit -av -m "icinga-web1: Update docs for Icinga 2"
|
git commit -av -m "icinga-web: Update docs for Icinga 2"
|
||||||
|
|
||||||
git push
|
git push
|
||||||
```
|
```
|
||||||
|
|
||||||
SSH into icinga-web1 and do a manual Puppet dry run with the testing environment.
|
SSH into the webserver and do a manual Puppet dry run with the testing environment.
|
||||||
|
|
||||||
```
|
```
|
||||||
puppet agent -t --environment testing --noop
|
puppet agent -t --environment testing --noop
|
||||||
|
@ -357,17 +348,25 @@ git merge testing
|
||||||
git push
|
git push
|
||||||
```
|
```
|
||||||
|
|
||||||
SSH into icinga-web2 and do a manual Puppet run from the production environment (default).
|
SSH into the webserver and do a manual Puppet run from the production environment (default).
|
||||||
|
|
||||||
```
|
```
|
||||||
puppet agent -t
|
puppet agent -t
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Manual Generation
|
||||||
|
|
||||||
|
SSH into the webserver or ask @bobapple.
|
||||||
|
|
||||||
|
```
|
||||||
|
cd /usr/local/icinga-docs-tools && ./build-docs.rb -c /var/www/docs/config/icinga2-latest.yml
|
||||||
|
```
|
||||||
|
|
||||||
### Announcement <a id="announcement"></a>
|
### Announcement <a id="announcement"></a>
|
||||||
|
|
||||||
* Create a new blog post on [icinga.com/blog](https://icinga.com/blog) including a featured image
|
* Create a new blog post on [icinga.com/blog](https://icinga.com/blog) including a featured image
|
||||||
* Create a release topic on [community.icinga.com](https://community.icinga.com)
|
* Create a release topic on [community.icinga.com](https://community.icinga.com)
|
||||||
* Release email to team
|
* Release email to net-tech & team
|
||||||
|
|
||||||
### Project Management <a id="project-management"></a>
|
### Project Management <a id="project-management"></a>
|
||||||
|
|
||||||
|
|
233
changelog.py
233
changelog.py
|
@ -1,233 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
# -*- coding:utf-8 -*-
|
|
||||||
|
|
||||||
import requests
|
|
||||||
import re
|
|
||||||
import pickle
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
from datetime import datetime
|
|
||||||
from collections import defaultdict
|
|
||||||
from collections import OrderedDict
|
|
||||||
|
|
||||||
#################################
|
|
||||||
## Env Config
|
|
||||||
|
|
||||||
try:
|
|
||||||
github_auth_username = os.environ['ICINGA_GITHUB_AUTH_USERNAME']
|
|
||||||
except KeyError:
|
|
||||||
print "ERROR: Environment variable 'ICINGA_GITHUB_AUTH_USERNAME' is not set."
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
try:
|
|
||||||
github_auth_token = os.environ['ICINGA_GITHUB_AUTH_TOKEN']
|
|
||||||
except:
|
|
||||||
print "ERROR: Environment variable 'ICINGA_GITHUB_AUTH_TOKEN' is not set."
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
try:
|
|
||||||
project_name = os.environ['ICINGA_GITHUB_PROJECT']
|
|
||||||
except:
|
|
||||||
print "ERROR: Environment variable 'ICINGA_GITHUB_PROJECT' is not set."
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
#################################
|
|
||||||
## Config
|
|
||||||
|
|
||||||
changelog_file = "CHANGELOG.md" # TODO: config param
|
|
||||||
debug = 1
|
|
||||||
|
|
||||||
# Keep this in sync with GitHub labels.
|
|
||||||
ignored_labels = [
|
|
||||||
"high-priority", "low-priority",
|
|
||||||
"bug", "enhancement",
|
|
||||||
"needs-feedback", "question", "duplicate", "invalid", "wontfix",
|
|
||||||
"backported", "build-fix"
|
|
||||||
]
|
|
||||||
|
|
||||||
# Selectively show and collect specific categories
|
|
||||||
#
|
|
||||||
# (category, list of case sensitive matching labels)
|
|
||||||
# The order is important!
|
|
||||||
# Keep this in sync with GitHub labels.
|
|
||||||
categories = OrderedDict(
|
|
||||||
[
|
|
||||||
("Enhancement", ["enhancement"]),
|
|
||||||
("Bug", ["bug", "crash"]),
|
|
||||||
("ITL", ["ITL"]),
|
|
||||||
("Documentation", ["Documentation"]),
|
|
||||||
("Support", ["code-quality", "Tests", "Packages", "Installation"])
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
#################################
|
|
||||||
## Helpers
|
|
||||||
|
|
||||||
def write_changelog(line):
|
|
||||||
clfp.write(line + "\n")
|
|
||||||
|
|
||||||
def log(level, msg):
|
|
||||||
if level <= debug:
|
|
||||||
print " " + msg
|
|
||||||
|
|
||||||
def fetch_github_resources(uri, params = {}):
|
|
||||||
resources = []
|
|
||||||
|
|
||||||
url = 'https://api.github.com/repos/' + project_name + uri + "?per_page=100" # 100 is the maximum
|
|
||||||
|
|
||||||
while True:
|
|
||||||
log(2, "Requesting URL: " + url)
|
|
||||||
resp = requests.get(url, auth=(github_auth_username, github_auth_token), params=params)
|
|
||||||
try:
|
|
||||||
resp.raise_for_status()
|
|
||||||
except requests.exceptions.HTTPError as e:
|
|
||||||
raise e
|
|
||||||
|
|
||||||
data = resp.json()
|
|
||||||
|
|
||||||
if len(data) == 0:
|
|
||||||
break
|
|
||||||
|
|
||||||
resources.extend(data)
|
|
||||||
|
|
||||||
# fetch the next page from headers, do not count pages
|
|
||||||
# http://engineering.hackerearth.com/2014/08/21/python-requests-module/
|
|
||||||
if "next" in resp.links:
|
|
||||||
url = resp.links['next']['url']
|
|
||||||
log(2, "Found next link for Github pagination: " + url)
|
|
||||||
else:
|
|
||||||
break # no link found, we are done
|
|
||||||
log(2, "No more pages to fetch, stop.")
|
|
||||||
|
|
||||||
return resources
|
|
||||||
|
|
||||||
def issue_type(issue):
|
|
||||||
issue_labels = [label["name"] for label in issue["labels"]]
|
|
||||||
|
|
||||||
# start with the least important first (e.g. "Support", "Documentation", "Bug", "Enhancement" as order)
|
|
||||||
for category in reversed(categories):
|
|
||||||
labels = categories[category]
|
|
||||||
|
|
||||||
for label in labels:
|
|
||||||
if label in issue_labels:
|
|
||||||
return category
|
|
||||||
|
|
||||||
return "Support"
|
|
||||||
|
|
||||||
def escape_markdown(text):
|
|
||||||
#tmp = text.replace('&', '&').replace('<', '<').replace('>', '>')
|
|
||||||
tmp = text
|
|
||||||
tmp.replace('\\', '\\\\')
|
|
||||||
|
|
||||||
return re.sub("([<>*_()\[\]#])", r"\\\1", tmp)
|
|
||||||
|
|
||||||
def format_labels(issue):
|
|
||||||
labels = filter(lambda label: label not in ignored_labels, [label["name"] for label in issue["labels"]])
|
|
||||||
|
|
||||||
# Mark PRs as custom label
|
|
||||||
if "pull_request" in issue:
|
|
||||||
labels.append("PR")
|
|
||||||
|
|
||||||
if len(labels):
|
|
||||||
return " (" + ", ".join(labels) + ")"
|
|
||||||
else:
|
|
||||||
return ""
|
|
||||||
|
|
||||||
def format_title(title):
|
|
||||||
# Fix encoding
|
|
||||||
try:
|
|
||||||
issue_title = str(title.encode('ascii', 'ignore').encode('utf-8'))
|
|
||||||
except Error:
|
|
||||||
log(1, "Error: Cannot convert " + title + " to UTF-8")
|
|
||||||
|
|
||||||
# Remove dev.icinga.com tag
|
|
||||||
issue_title = re.sub('\[dev\.icinga\.com #\d+\] ', '', issue_title)
|
|
||||||
|
|
||||||
#log(1, "Issue title: " + issue_title + "Type: " + str(type(issue_title)))
|
|
||||||
|
|
||||||
return escape_markdown(issue_title)
|
|
||||||
|
|
||||||
#################################
|
|
||||||
## MAIN
|
|
||||||
|
|
||||||
milestones = {}
|
|
||||||
issues = defaultdict(lambda: defaultdict(list))
|
|
||||||
|
|
||||||
log(1, "Fetching data from GitHub API for project " + project_name)
|
|
||||||
|
|
||||||
try:
|
|
||||||
tickets = fetch_github_resources("/issues", { "state": "all" })
|
|
||||||
except requests.exceptions.HTTPError as e:
|
|
||||||
log(1, "ERROR " + str(e.response.status_code) + ": " + e.response.text)
|
|
||||||
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
clfp = open(changelog_file, "w+")
|
|
||||||
|
|
||||||
with open('tickets.pickle', 'wb') as fp:
|
|
||||||
pickle.dump(tickets, fp)
|
|
||||||
|
|
||||||
with open('tickets.pickle', 'rb') as fp:
|
|
||||||
cached_issues = pickle.load(fp)
|
|
||||||
|
|
||||||
for issue in cached_issues: #fetch_github_resources("/issues", { "state": "all" }):
|
|
||||||
milestone = issue["milestone"]
|
|
||||||
|
|
||||||
if not milestone:
|
|
||||||
continue
|
|
||||||
|
|
||||||
ms_title = milestone["title"]
|
|
||||||
|
|
||||||
if not re.match('^\d+\.\d+\.\d+$', ms_title):
|
|
||||||
continue
|
|
||||||
|
|
||||||
if ms_title.split(".")[0] != "2":
|
|
||||||
continue
|
|
||||||
|
|
||||||
milestones[ms_title] = milestone
|
|
||||||
|
|
||||||
ms_tickets = issues[ms_title][issue_type(issue)]
|
|
||||||
ms_tickets.append(issue)
|
|
||||||
|
|
||||||
# TODO: Generic header based on project_name
|
|
||||||
write_changelog("# Icinga 2.x CHANGELOG")
|
|
||||||
write_changelog("")
|
|
||||||
|
|
||||||
for milestone in sorted(milestones.values(), key=lambda ms: (ms["due_on"], ms["title"]), reverse=True):
|
|
||||||
if milestone["state"] != "closed":
|
|
||||||
continue
|
|
||||||
|
|
||||||
if milestone["due_on"] == None:
|
|
||||||
print "Warning: Milestone", milestone["title"], "does not have a due date."
|
|
||||||
|
|
||||||
ms_due_on = datetime.strptime(milestone["due_on"], "%Y-%m-%dT%H:%M:%SZ")
|
|
||||||
|
|
||||||
write_changelog("## %s (%s)" % (milestone["title"], ms_due_on.strftime("%Y-%m-%d")))
|
|
||||||
write_changelog("")
|
|
||||||
|
|
||||||
ms_description = milestone["description"]
|
|
||||||
ms_description = re.sub('\r\n', '\n', ms_description)
|
|
||||||
|
|
||||||
if len(ms_description) > 0:
|
|
||||||
write_changelog("### Notes\n\n" + ms_description + "\n") # Don't escape anything, we take care on Github for valid Markdown
|
|
||||||
|
|
||||||
for category, labels in categories.iteritems():
|
|
||||||
try:
|
|
||||||
ms_issues = issues[milestone["title"]][category]
|
|
||||||
except KeyError:
|
|
||||||
continue
|
|
||||||
|
|
||||||
if len(ms_issues) == 0:
|
|
||||||
continue
|
|
||||||
|
|
||||||
write_changelog("### " + category)
|
|
||||||
write_changelog("")
|
|
||||||
|
|
||||||
for issue in ms_issues:
|
|
||||||
write_changelog("* [#" + str(issue["number"]) + "](https://github.com/" + project_name
|
|
||||||
+ "/issues/" + str(issue["number"]) + ")" + format_labels(issue) + ": " + format_title(issue["title"]))
|
|
||||||
|
|
||||||
write_changelog("")
|
|
||||||
|
|
||||||
clfp.close()
|
|
||||||
log(1, "Finished writing " + changelog_file)
|
|
|
@ -2271,6 +2271,7 @@ Name | Language | Description
|
||||||
[Logstash input event stream](https://github.com/bobapple/logstash-input-icinga_eventstream) | Ruby | Forward events as Logstash input
|
[Logstash input event stream](https://github.com/bobapple/logstash-input-icinga_eventstream) | Ruby | Forward events as Logstash input
|
||||||
[Flapjack events](https://github.com/sol1/flapjack-icinga2) | Golang | Dumping events into Redis for Flapjack processing
|
[Flapjack events](https://github.com/sol1/flapjack-icinga2) | Golang | Dumping events into Redis for Flapjack processing
|
||||||
[Stackstorm integration](https://github.com/StackStorm-Exchange/stackstorm-icinga2) | Python | Processing events and fetching status information
|
[Stackstorm integration](https://github.com/StackStorm-Exchange/stackstorm-icinga2) | Python | Processing events and fetching status information
|
||||||
|
[NodeJS consumer](https://community.icinga.com/t/consume-api-event-stream/1010/6) | NodeJS | Example from our community :)
|
||||||
|
|
||||||
### Actions <a id="icinga2-api-clients-actions"></a>
|
### Actions <a id="icinga2-api-clients-actions"></a>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue