mirror of
https://github.com/ansible/awx.git
synced 2026-01-11 01:57:35 -03:30
Refined release documentation (#14221)
This commit is contained in:
parent
cb5a8aa194
commit
07e30a3d5f
@ -1,9 +1,27 @@
|
||||
# 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.
|
||||
## 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).
|
||||
|
||||
@ -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.
|
||||
|
||||
#### Select the next release version
|
||||
|
||||
Indicators of a Z-stream 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 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
|
||||
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
|
||||
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!
|
||||
Note: the slack message is the same as the IRC message.
|
||||
|
||||
## 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
|
||||
|
||||
@ -165,4 +186,4 @@ Here are the steps needed to revert an AWX and an AWX-Operator release. Dependin
|
||||
|
||||
7. Navigate to the [PyPi](https://pypi.org/project/awxkit/#history) and delete the bad AWX tag and release that got published.
|
||||
|
||||
8. [Restart the Release Process](#releasing-awx-and-awx-operator)
|
||||
8. [Restart the Release Process](#releasing-awx-and-awx-operator)
|
||||
|
||||
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,
|
||||
)
|
||||
)
|
||||
Loading…
x
Reference in New Issue
Block a user