mirror of
https://github.com/ansible/awx.git
synced 2026-05-07 09:27:36 -02:30
Refined release documentation (#14221)
This commit is contained in:
@@ -1,9 +1,27 @@
|
|||||||
# Releasing AWX (and awx-operator)
|
# Releasing AWX (and awx-operator)
|
||||||
|
|
||||||
The release process for AWX is completely automated as of version 19.5.0.
|
The release process for AWX is mostly automated as of version 19.5.0.
|
||||||
|
|
||||||
If you need to revert a release, please refer to the [Revert a Release](#revert-a-release) section.
|
If you need to revert a release, please refer to the [Revert a Release](#revert-a-release) section.
|
||||||
## Get latest release version and list of new work
|
|
||||||
|
## Select the next release version
|
||||||
|
|
||||||
|
There are two methods you can use to get the next release version. The manual way and the automated way.
|
||||||
|
|
||||||
|
### Automated Way
|
||||||
|
|
||||||
|
#### Get a github token
|
||||||
|
|
||||||
|
Log into your github account, under your user icon go to Settings => Developer Settings => Personal Access Tokens => Tokens (classic).
|
||||||
|
Select the Generate new token => Generate new token (classic)
|
||||||
|
Fill in the note, select no scopes select "Generate token".
|
||||||
|
Copy the token and create a file in your awx repo called `.github_creds`. Enter the token in this file.
|
||||||
|
Run `./tools/scripts/get_next_release.py`
|
||||||
|
This will use your token to go query for the PRs in the release and scan their bodies to select X/Y/Z and suggest new versions and spit out notifications.
|
||||||
|
|
||||||
|
### Manual Way
|
||||||
|
|
||||||
|
#### Get latest release version and list of new work
|
||||||
|
|
||||||
1. Open the main project page for [AWX](https://github.com/ansible/awx/releases) and [AWX Operator](https://github.com/ansible/awx-operator/releases).
|
1. Open the main project page for [AWX](https://github.com/ansible/awx/releases) and [AWX Operator](https://github.com/ansible/awx-operator/releases).
|
||||||
|
|
||||||
@@ -20,10 +38,10 @@ The page will now automatically update with a list of PRs that are in `AWX/devel
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Select the next release version
|
|
||||||
|
|
||||||
Use this list of PRs to decide if this is a X-stream (major) release, Y-stream (minor) release, or a Z-stream (patch) release. Use [semver](https://semver.org/#summary) to help determine what kind of release is needed.
|
Use this list of PRs to decide if this is a X-stream (major) release, Y-stream (minor) release, or a Z-stream (patch) release. Use [semver](https://semver.org/#summary) to help determine what kind of release is needed.
|
||||||
|
|
||||||
|
#### Select the next release version
|
||||||
|
|
||||||
Indicators of a Z-stream release:
|
Indicators of a Z-stream release:
|
||||||
|
|
||||||
- No significant new features have been merged into devel since the last release.
|
- No significant new features have been merged into devel since the last release.
|
||||||
@@ -126,16 +144,19 @@ This workflow will take the generated images and promote them to quay.io.
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Notify the AWX mailing list
|
## Send notifications
|
||||||
Send an email to the [AWX Mailing List](mailto:awx-project@googlegroups.com) with a message format of type "AWX Release" from the [mailing list triage standard replies](../.github/triage_replies.md#awx-release)
|
Send notifications to the following groups:
|
||||||
|
* AWX Mailing List
|
||||||
|
* #social:ansible.com IRC (@newsbot for inclusion in bullhorn)
|
||||||
|
* #awx:ansible.com (no @newsbot in this room)
|
||||||
|
* #ansible-controller slack channel
|
||||||
|
|
||||||
## Send an IRC message over matrix to #social:ansible.com for bullhorn:
|
These messages are templated out for you in the output of `get_next_release.yml`.
|
||||||
|
|
||||||
@newsbot
|
Note: the slack message is the same as the IRC message.
|
||||||
We're happy to announce that [AWX version 21.1.0](https://github.com/ansible/awx/releases/tag/21.1.0) is now available!
|
|
||||||
We're happy to announce that [AWX Operator version 0.22.0](https://github.com/ansible/awx-operator/releases/tag/0.22.0) is now available!
|
|
||||||
|
|
||||||
## Send the same IRC message (less the @newsbot) to #awx:ansible.com
|
## Create operator hub PRs.
|
||||||
|
Operator hub PRs are generated via an Ansible Playbook. See someone on the AWX team for the location of the playbooks and instructions on how to run them.
|
||||||
|
|
||||||
## Revert a Release
|
## Revert a Release
|
||||||
|
|
||||||
|
|||||||
257
tools/scripts/get_next_release.py
Executable file
257
tools/scripts/get_next_release.py
Executable file
@@ -0,0 +1,257 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
missing_modules = []
|
||||||
|
try:
|
||||||
|
import requests
|
||||||
|
except:
|
||||||
|
missing_modules.append('requests')
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
|
||||||
|
try:
|
||||||
|
import semantic_version
|
||||||
|
except:
|
||||||
|
missing_modules.append('semantic_version')
|
||||||
|
|
||||||
|
if len(missing_modules) > 0:
|
||||||
|
print("This requires python libraries to work; try:")
|
||||||
|
for a_module in missing_modules:
|
||||||
|
print(" pip install {}".format(a_module))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
def getCurrentVersions():
|
||||||
|
print("Getting current versions")
|
||||||
|
for repo in product_repos:
|
||||||
|
response = session.get('https://api.github.com/repos/ansible/{}/releases'.format(repo))
|
||||||
|
if 'X-RateLimit-Limit' in response.headers and int(response.headers['X-RateLimit-Limit']) <= 60:
|
||||||
|
print("Your key in .github_creds did not work right and you are using unauthenticated requests")
|
||||||
|
print("This script would likely overrun your available requests, exiting")
|
||||||
|
sys.exit(3)
|
||||||
|
versions['current'][repo] = response.json()[0]['tag_name']
|
||||||
|
print(" {}: {}".format(repo, versions['current'][repo]))
|
||||||
|
|
||||||
|
|
||||||
|
def getNextReleases():
|
||||||
|
#
|
||||||
|
# This loads the commits since the last release and gets their associated PRs and scans those for release_type: [xyz]
|
||||||
|
# Any X or Y changes also get captured for bullhorn release notes
|
||||||
|
#
|
||||||
|
for repo in product_repos:
|
||||||
|
response = session.get('https://api.github.com/repos/ansible/{}/compare/{}...devel'.format(repo, versions['current'][repo]))
|
||||||
|
commit_data = response.json()
|
||||||
|
pr_votes = {}
|
||||||
|
suggested_release_type = None
|
||||||
|
prs_missing_relese_type = 0
|
||||||
|
versions['release_notes'][repo] = []
|
||||||
|
for commit in commit_data['commits']:
|
||||||
|
response = session.get('https://api.github.com/repos/ansible/{}/commits/{}/pulls'.format(repo, commit['sha']))
|
||||||
|
prs = response.json()
|
||||||
|
for a_pr in prs:
|
||||||
|
# If we've already seen this PR we don't need to check again
|
||||||
|
try:
|
||||||
|
if a_pr['html_url'] in pr_votes:
|
||||||
|
continue
|
||||||
|
except:
|
||||||
|
print("Unable to check on PR")
|
||||||
|
print(json.dumps(a_pr, indent=4))
|
||||||
|
sys.exit(255)
|
||||||
|
append_title = False
|
||||||
|
pr_release = 'is non voting'
|
||||||
|
if a_pr and a_pr.get('body', None):
|
||||||
|
if 'Breaking Change' in a_pr['body']:
|
||||||
|
suggested_release_type = 'x'
|
||||||
|
pr_release = 'votes x'
|
||||||
|
append_title = True
|
||||||
|
elif 'New or Enhanced Feature' in a_pr['body']:
|
||||||
|
if suggested_release_type != 'x':
|
||||||
|
suggested_release_type = 'y'
|
||||||
|
pr_release = 'votes y'
|
||||||
|
append_title = True
|
||||||
|
elif 'Bug, Docs Fix or other nominal change' in a_pr['body']:
|
||||||
|
if suggested_release_type == None:
|
||||||
|
suggested_release_type = 'z'
|
||||||
|
pr_release = 'votes z'
|
||||||
|
# This was a format along the way
|
||||||
|
elif 'Bug or Docs Fix' in a_pr['body']:
|
||||||
|
if suggested_release_type == None:
|
||||||
|
suggested_release_type = 'z'
|
||||||
|
pr_release = 'votes z'
|
||||||
|
# Old PR format
|
||||||
|
elif (
|
||||||
|
'- Bug Report' in a_pr['body']
|
||||||
|
or '- Bug Fix' in a_pr['body']
|
||||||
|
or '- Bugfix Pull Request' in a_pr['body']
|
||||||
|
or '- Documentation' in a_pr['body']
|
||||||
|
or '- Docs Pull Request' in a_pr['body']
|
||||||
|
):
|
||||||
|
if suggested_release_type == None:
|
||||||
|
suggested_release_type = 'z'
|
||||||
|
pr_release = 'votes z (from old PR body)'
|
||||||
|
elif '- Feature Idea' in a_pr['body'] or '- Feature Pull Request' in a_pr['body']:
|
||||||
|
if suggested_release_type != 'x':
|
||||||
|
suggested_release_type = 'y'
|
||||||
|
pr_release = 'votes y (from old PR body)'
|
||||||
|
append_title = True
|
||||||
|
else:
|
||||||
|
prs_missing_relese_type += 1
|
||||||
|
else:
|
||||||
|
prs_missing_relese_type += 1
|
||||||
|
|
||||||
|
if append_title:
|
||||||
|
versions['release_notes'][repo].append("* {}".format(a_pr['title']))
|
||||||
|
print("PR {} {}".format(a_pr['html_url'], pr_release))
|
||||||
|
pr_votes[a_pr['html_url']] = pr_release
|
||||||
|
|
||||||
|
print("https://github.com/ansible/{}/compare/{}...devel".format(repo, versions['current'][repo]))
|
||||||
|
print("{} devel is {} commit(s) ahead of release {}".format(repo, commit_data['total_commits'], versions['current'][repo]))
|
||||||
|
if prs_missing_relese_type == 0:
|
||||||
|
print("\nAll commits voted, the release type suggestion is {}".format(suggested_release_type))
|
||||||
|
else:
|
||||||
|
total_prs = len(pr_votes)
|
||||||
|
voted_prs = total_prs - prs_missing_relese_type
|
||||||
|
print("From {} commits, {} of {} PRs voted".format(commit_data['total_commits'], voted_prs, total_prs))
|
||||||
|
if suggested_release_type:
|
||||||
|
print("\nOf commits with release type, the suggestion is {}".format(suggested_release_type))
|
||||||
|
else:
|
||||||
|
print("\nNone of the commits had the release type indicated")
|
||||||
|
print()
|
||||||
|
|
||||||
|
current_version = semantic_version.Version(versions['current'][repo])
|
||||||
|
if suggested_release_type.lower() == 'x':
|
||||||
|
versions['next'][repo] = current_version.next_major()
|
||||||
|
elif suggested_release_type.lower() == 'y':
|
||||||
|
versions['next'][repo] = current_version.next_minor()
|
||||||
|
else:
|
||||||
|
versions['next'][repo] = current_version.next_patch()
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Load the users session information
|
||||||
|
#
|
||||||
|
session = requests.Session()
|
||||||
|
try:
|
||||||
|
print("Loading credentials")
|
||||||
|
with open(".github_creds", "r") as f:
|
||||||
|
password = f.read().strip()
|
||||||
|
session.headers.update({'Authorization': 'bearer {}'.format(password), 'Accept': 'application/vnd.github.v3+json'})
|
||||||
|
except Exception:
|
||||||
|
print("Failed to load credentials from ./.github_creds")
|
||||||
|
sys.exit(255)
|
||||||
|
|
||||||
|
versions = {
|
||||||
|
'current': {},
|
||||||
|
'next': {},
|
||||||
|
'release_notes': {},
|
||||||
|
}
|
||||||
|
|
||||||
|
product_repos = ['awx', 'awx-operator']
|
||||||
|
|
||||||
|
#
|
||||||
|
# Get latest release version from releases page
|
||||||
|
#
|
||||||
|
getCurrentVersions()
|
||||||
|
|
||||||
|
#
|
||||||
|
# Scan PRs for release types
|
||||||
|
#
|
||||||
|
getNextReleases()
|
||||||
|
|
||||||
|
#
|
||||||
|
# Confirm the release number with the human
|
||||||
|
#
|
||||||
|
print(
|
||||||
|
'''
|
||||||
|
|
||||||
|
Next recommended releases:
|
||||||
|
AWX: {0}
|
||||||
|
Operator: {1}
|
||||||
|
|
||||||
|
'''.format(
|
||||||
|
versions['next']['awx'],
|
||||||
|
versions['next']['awx-operator'],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
for product in product_repos:
|
||||||
|
version_override = input("Enter the next {} release number ({}): ".format(product, versions['next'][product]))
|
||||||
|
if version_override != '':
|
||||||
|
versions['next'][product] = version_override
|
||||||
|
|
||||||
|
#
|
||||||
|
# Generate IRC and Mailing list messages
|
||||||
|
#
|
||||||
|
print("Enter any known issues (one per line, empty line to end)")
|
||||||
|
known_issues = []
|
||||||
|
keep_getting_issues = True
|
||||||
|
while keep_getting_issues:
|
||||||
|
issue = input()
|
||||||
|
if issue == '':
|
||||||
|
keep_getting_issues = False
|
||||||
|
else:
|
||||||
|
known_issues.append(issue)
|
||||||
|
|
||||||
|
display_known_issues = ''
|
||||||
|
if len(known_issues) > 0:
|
||||||
|
display_known_issues = "\n".join(['Known Issues:'] + ['* {}'.format(item) for item in known_issues])
|
||||||
|
|
||||||
|
print(
|
||||||
|
'''
|
||||||
|
Bullhorn/irc list message:
|
||||||
|
|
||||||
|
@newsbot We're happy to announce that the next release of AWX, version {0} is now available!
|
||||||
|
Some notable features include:
|
||||||
|
{2}
|
||||||
|
|
||||||
|
In addition AWX Operator version {1} has also been released!
|
||||||
|
Some notable features include:
|
||||||
|
{3}
|
||||||
|
|
||||||
|
Please see the releases pages for more details:
|
||||||
|
AWX: [https://github.com/ansible/awx/releases/tag/{0}](https://github.com/ansible/awx/releases/tag/{0})
|
||||||
|
Operator: [https://github.com/ansible/awx-operator/releases/tag/{1}](https://github.com/ansible/awx-operator/releases/tag/{1})
|
||||||
|
|
||||||
|
{4}
|
||||||
|
'''.format(
|
||||||
|
versions['next']['awx'],
|
||||||
|
versions['next']['awx-operator'],
|
||||||
|
'\n'.join(versions['release_notes']['awx']),
|
||||||
|
'\n'.join(versions['release_notes']['awx-operator']),
|
||||||
|
display_known_issues,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
print(
|
||||||
|
'''
|
||||||
|
Mailing list message:
|
||||||
|
|
||||||
|
Subject: Announcing AWX {0} and AWX-Operator {1}
|
||||||
|
Body:
|
||||||
|
Hi all,
|
||||||
|
|
||||||
|
We're happy to announce that the next release of AWX, version {0} is now available!
|
||||||
|
Some notable features include:
|
||||||
|
{2}
|
||||||
|
|
||||||
|
In addition AWX Operator version {1} has also been released!
|
||||||
|
Some notable features include:
|
||||||
|
{3}
|
||||||
|
|
||||||
|
Please see the releases pages for more details:
|
||||||
|
AWX: https://github.com/ansible/awx/releases/tag/{0}
|
||||||
|
Operator: https://github.com/ansible/awx-operator/releases/tag/{1}
|
||||||
|
|
||||||
|
{4}
|
||||||
|
|
||||||
|
-The AWX team.
|
||||||
|
'''.format(
|
||||||
|
versions['next']['awx'],
|
||||||
|
versions['next']['awx-operator'],
|
||||||
|
'\n'.join(versions['release_notes']['awx']),
|
||||||
|
'\n'.join(versions['release_notes']['awx-operator']),
|
||||||
|
display_known_issues,
|
||||||
|
)
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user