Skip to content

Commit

Permalink
Improve checklists and tooling for releases
Browse files Browse the repository at this point in the history
* Adds release_new_version ISSUE_TEMPLATE
* Adds create-translation-issues.sh helper script
* Updates get_release_contributors.py to support Co-authored-by lines (fixes #1599)

Co-authored-by: Jonathan <[email protected]>
Co-authored-by: Peter L Jones <[email protected]>
Co-authored-by: ann0see <[email protected]>
  • Loading branch information
4 people committed Jun 6, 2021
1 parent 2512a85 commit 36224e8
Show file tree
Hide file tree
Showing 3 changed files with 327 additions and 8 deletions.
76 changes: 76 additions & 0 deletions .github/ISSUE_TEMPLATE/release_new_version.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
---
name: 'For maintainers: Release a new version'
about: This is the Developer-only template which we use for tracking the process of future releases.
title: 'Prepare Release 3.y.z'
labels: release
assignees: ''
---

**Target timeline**
Scheduled feature freeze / Start of translation process: <!-- Add a date, usually about 6-8 weeks from the last release, e.g. 2021-04-20 -->
Targeted translation completion date: <!-- E.g. two weeks after feature freeze, e.g. 2021-05-04 -->
Approximate release date: <!-- E.g. one week after targeted translation completion date to have time for late translations, reviews, RC, e.g. 2021-05-11 -->
Current state: <!-- Planning|Translations (beta)|Code freeze (rc)|Released -->

**Checklist**
- [ ] Assign this issue to the release shepherd who is in charge of managing this checklist
- [ ] Pin this issue
- [ ] Create a milestone and add all relevant issues
- [ ] Ensure that all issues/PR targeted for this release are done by checking the Project board with an appropriate filter (e.g. [`milestone:"Release 3.8.0"`](https://github.com/orgs/jamulussoftware/projects/2?card_filter_query=milestone%3A"release+3.8.0")). Reminder main developers to review entries in *Waiting on team* state. De-tag unfinished Issues/PRs.
- [ ] Declare a freeze for code website by updating this Issue and adding a comment. PRs can still be worked on and may get reviewed, but must not be merged unless agreed explicitly.
- [ ] Check ./Jamulus -h output against the en-Command-Line-Options.md wiki page and update if necessary.
- [ ] Write the Changelog based on the list of merged PRs ([example for 3.8.0](https://github.com/jamulussoftware/jamulus/pulls?q=is%3Amerged+milestone%3A"Release+3.8.0"))
- [ ] Start Website translations
- [ ] Check for broken links with a link checker locally
- [ ] Create new branch `translate3_y_z` based on branch `release`
- [ ] Squash-merge `changes` into `translate3_y_z`
- [ ] Check if the list of translators in `tools/create-translation-issues.sh` is up-to-date
- [ ] Create a translation Issue for each language, e.g. `../jamulus/tools/create-translation-issues.sh 3.8.0 2021-05-15 web 'Note: The term "Central server" has been replaced with "Directory server"'` (Last argument is optional and should be skipped if there is nothing to add)
- [ ] Start App translations
- [ ] Generate `.ts` files in master via `lupdate`
- [ ] Check if the list of translators in `tools/create-translation-issues.sh` is up-to-date
- [ ] Create a translation Issue for each language, e.g. `./tools/create-translation-issues.sh 3.8.0 2021-05-15 'Note: The term "Central server" has been replaced with "Directory server"'` (Last argument is optional and should be skipped if there is nothing to add)
- [ ] [Tag a beta release](https://github.com/jamulussoftware/jamulus/blob/master/RELEASE-PROCESS.md#steps-for-a-specific-release)
- [ ] Announce the beta release on Github Discussions. Pin the thread.
- [ ] Get feedback on the stability and resource usage (memleaks?) of the beta release
- [ ] Finish Website translations
- [ ] Wait for all PRs to be merged
- [ ] Check for broken links with a link checker locally
- [ ] Decide what to do about missing translations. Depending on the missing changes, consider keeping the old state (if it is still valid) or temporary backing out the relevant file(s) if they would become wrong.
- [ ] Finish App translations
- [ ] Review PRs <details><summary>Checklist for the PRs</summary> <!-- FIXME: This should be moved to the admin wiki and linked here -->
```
- [ ] Translator listed in the `src/util.cpp` **optionally add link to PR or code**
- [ ] Punctuation and spacing consistent
- [ ] Signal words consistent ("ASIO", "Buffer")
- [ ] App translations: No untranslated strings (`grep unfinished -5 src/res/translation/translation_$TRANSLATION*.ts`)
- [ ] App translations: Only a single `.ts` file checked in (`.qm` in addition is also OK)
- [ ] Installer translations: Passes `tools/check-wininstaller-translations.sh`
```
</details>
- [ ] Wait for all PRs to be merged. If translations are missing after the targeted translation completion date, this is ok. They can be updated with the next release again.
- [ ] Check for conflicting accelerator keys (see `tools/checkkeys.pl`)
- [ ] Generate `.qm` files via `lrelease Jamulus.pro`
- [ ] [Tag a release candidate](https://github.com/jamulussoftware/jamulus/blob/master/RELEASE-PROCESS.md#steps-for-a-specific-release)
- [ ] Announce the release candidate on Github Discussions. Pin the thread. Unpin and lock the beta thread.
- [ ] Draft an announcement, include all contributors via `tools/get_release_contributors.py`
- [ ] [Update the version number in `Jamulus.pro` and add the release date to the Changelog header and commit](https://github.com/jamulussoftware/jamulus/blob/master/RELEASE-PROCESS.md#steps-for-a-specific-release)
- [ ] Tag this commit as `r3_y_z`
- [ ] Wait for the build to complete
- [ ] Do a smoke test for Windows/Mac/Linux -- Do the binaries start/connect properly? Can earlier Jamulus versions properly connect to a server based on the new release?
- [ ] [Force tag that tag as `latest` and push.](https://github.com/jamulussoftware/jamulus/blob/master/RELEASE-PROCESS.md#if-this-is-a-proper-release-move-the-latest-tag)
- [ ] Upload the artifacts to SourceForge and link latest (see #1814 for docs)
- [ ] [Prepare `Jamulus.pro` (`dev` suffix) and ChangeLog (add a header) for the next release](https://github.com/jamulussoftware/jamulus/blob/master/RELEASE-PROCESS.md#make-the-master-branch-ready-for-post-release-development)
- [ ] Trigger the update notification by updating both Update Check Servers with the new version (@pljones for update02, email corrados for update01)
- [ ] Announce the new release with a summary of changes (+ link to the changelog for details) and a link to the download page
- [ ] On Github Discussions in the Announcements section. Lock the announcement thread. Pin the thread. Unpin and lock release candidate thread.
- [ ] On Facebook in the group "Jamulus (official group)". Turn off replies.
- [ ] Update download links on the website by editing `config.yml`
- [ ] Publish Website release by merging `translate3_y_z` into `release`
- [ ] Delete the `translate3_y_z` branch from the Website repo
- [ ] Check that all Issues and PRs tagged for this release are in Done/Closed state.
- [ ] Close the release milestone in both jamulus and jamuluswebsite repos
- [ ] Create a milestone for the next minor release in jamulus and jamuluswebsite repos
- [ ] Update [this checklist](https://github.com/jamulussoftware/jamulus/blob/master/.github/ISSUE_TEMPLATE/release_new_version.md) with any improvements which were found
- [ ] Create a release retrospective Discussion
- [ ] Unpin and close this issue
216 changes: 216 additions & 0 deletions tools/create-translation-issues.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
#!/bin/bash
# This script opens translation issues for all languages via the Github API.
# The script is idempotent and can be run multiple times. It will not create
# multiple issues if milestone and title remain the same. Instead, it will
# update any existing issues with a (potentially) updated body text.
#
# Syntax:
# ./tools/create-translation-issues.sh RELEASE DEADLINE app|web [EXTRA_TEXT]
#
# Requirements:
# - Github CLI tools + valid login
# - jamulus and jamulussoftware git checkouts
#
# Example usage for app translations:
# ./tools/create-translation-issues.sh 3.8.0 2021-05-15 app 'Note: The term "Central server" has been replaced with "Directory server"'
# Example usage for web translations:
# ../jamulus/tools/create-translation-issues.sh 3.8.0 2021-05-15 web 'Note: The term "Central server" has been replaced with "Directory server"'

set -eu

if [[ -z ${1:-} ]] || [[ -z ${2:-} ]] || [[ -z ${3:-} ]] ; then
echo "Syntax: $0 RELEASE DEADLINE app|web [EXTRA_TEXT]"
exit 1
fi

if ! gh auth status &>/dev/null; then
echo "Error: Please ensure that Github CLI is installed and you are logged in" >/dev/stderr
echo "Cannot continue. Exit." >/dev/stderr
exit 1
fi

RELEASE=$1
DEADLINE=$2
TYPE=$3
EXTRA_TEXT=${4:-}
MILESTONE="Release ${RELEASE}"
PROJECT=Tracking

declare -A TRANSLATORS_BY_LANG=(
# Syntax:
# [TYPE_LANG]="github-handle1,github-handle2"
# with TYPE being either app or web and
# with LANG being the language code (different syntax for app and web!)

# App translators:
[app_de_DE]="rolamos"
[app_es_ES]="ignotus666"
[app_fr_FR]="jujudusud"
[app_it_IT]="dzpex"
[app_nl_NL]="henkdegroot,jerogee"
[app_pl_PL]="SeeLook"
[app_pt_BR]="melcon"
[app_pt_PT]="Snayler"
[app_sk_SK]="jose1711"
[app_sv_SE]="genesisproject2020"

# Web translators:
[web_de]="Helondeth,ewarning"
[web_es]="ignotus666"
[web_fr]="jujudusud,trebmuh"
[web_it]="dzpex"
)

BODY_TEMPLATE_APP='Hi ${SPLIT_TRANSLATORS},
We are getting ready for the ${RELEASE} release. No further changes to translatable strings are currently planned for this release.
We would be happy if you updated the Jamulus software translations for **${LANG}** until **${DEADLINE}**.
Please
- Update your fork from `jamulussoftware/jamulus` `master` and create a working branch
- Update translations using Qt Linguist in your fork,
- Commit and push your changes and reference this Issue,
- Open a Pull Request before ${DEADLINE}
Suggested commit and PR message:
```
${TITLE}
Fixes #<Insert this issue'"'"'s number here>
```
${EXTRA_TEXT}${MULTIPLE_TRANSLATORS_TEXT}
Further documentation can be found in [TRANSLATING.md](https://github.com/jamulussoftware/jamulus/blob/master/TRANSLATING.md).
Thanks for contributing to Jamulus!'


BODY_TEMPLATE_WEB='Hi ${SPLIT_TRANSLATORS},
We are getting ready for the ${RELEASE} release and have created the [${TRANSLATE_BRANCH}](https://github.com/jamulussoftware/jamuluswebsite/tree/${TRANSLATE_BRANCH}) branch ([full diff](https://github.com/jamulussoftware/jamuluswebsite/compare/release..${TRANSLATE_BRANCH})).
Because the English is still going through large changes, we are not expecting translations of anything other than the following pages:
- [Home page](https://github.com/jamulussoftware/jamuluswebsite/blob/${TRANSLATE_BRANCH}/1-index.html)
- [Setup](https://github.com/jamulussoftware/jamuluswebsite/blob/${TRANSLATE_BRANCH}/wiki/en/en-Setup.md) (renamed from Getting-Started)
- Installation pages for each supported platform ([Windows](https://github.com/jamulussoftware/jamuluswebsite/blob/${TRANSLATE_BRANCH}/wiki/en/en-Installation-for-Windows.md), [Mac](https://github.com/jamulussoftware/jamuluswebsite/blob/${TRANSLATE_BRANCH}/wiki/en/en-Installation-for-Macintosh.md), [Linux](https://github.com/jamulussoftware/jamuluswebsite/blob/${TRANSLATE_BRANCH}/wiki/en/en-Installation-for-Linux.md))
While you are of course welcome to translate more than this, please be aware that you may have to re-translate for the next release.
We would be happy if you updated the translations for **${LANG}** until **${DEADLINE}**.
Please
- Start your work in your fork on a branch based on jamuluswebsite'"'"'s `${TRANSLATE_BRANCH}` branch.
- Update the language-specific files using your favorite editor (or directly on Github),
- Commit and push your changes to your fork,
- Open a Pull Request with your translations to the **${TRANSLATE_BRANCH}** branch with the subject `${TITLE}`,
- Link your PR(s) to this issue by including `Fixes #<Insert this issue'"'"'s number here>` in the PR content.
${EXTRA_TEXT}${MULTIPLE_TRANSLATORS_TEXT}
Suggested commit and PR message:
```
${TITLE}
Fixes #<Insert this issue'"'"'s number here>
```
Feel free to use this Issue to discuss anything you need prior to making any PR (and in your native language if needed).
Further documentation can be found in [TRANSLATING.md](https://github.com/jamulussoftware/jamuluswebsite/blob/${TRANSLATE_BRANCH}/README.md#translating).
Thanks for contributing to Jamulus!'


get_languages() {
if [[ $TYPE == app ]]; then
if [[ ! -f src/main.cpp ]]; then
echo "Error: Please ensure that you are at the root of a jamulus code checkout" >/dev/stderr
exit 1
fi
for LANG_FILE in src/res/translation/*.ts; do
LANG=${LANG_FILE/*\/translation_}
LANG=${LANG/.ts}
echo "$LANG"
done
elif [[ $TYPE == web ]]; then
if [[ ! -d wiki ]]; then
echo "Error: Please ensure that you are at the root of a jamuluswebsite checkout" >/dev/stderr
exit 1
fi
for LANG in $(cd wiki/ && ls -d *); do
[[ -d wiki/$LANG ]] || continue
[[ $LANG == en ]] && continue # does not have to be translated
echo "$LANG"
done
else
echo "Error: Invalid type. Valid types: app or website" >/dev/stderr
exit 1
fi
}

create_translation_issues() {
echo "Creating ${TYPE} translation issues"

[[ $TYPE == app ]] && GH_REPO=${GH_REPO:-jamulussoftware/jamulus} || GH_REPO=${GH_REPO:-jamulussoftware/jamuluswebsite}
export GH_REPO # This is used by the gh tool

for LANG in $(get_languages); do
create_translation_issue_for_lang "$LANG"
done
}

create_translation_issue_for_lang() {
local lang="$1"

translators=${TRANSLATORS_BY_LANG[${TYPE}_${lang}]-}
if [[ -z $translators ]]; then
echo "Warning: Can't create issue for $lang - who is responsible? Skipping." >/dev/stderr
return
fi

local title="Update ${lang} ${TYPE} translation for ${RELEASE}"
multiple_translators_text=""
[[ $translators == *,* ]] && multiple_translators_text=$'\n\n''This Issue is assigned to multiple people. Please coordinate who will translate what part.'
[[ $TYPE == app ]] && body_template="$BODY_TEMPLATE_APP" || body_template="$BODY_TEMPLATE_WEB"
local body=$(
# Note: Those line continuation backslashes are required for variables
# to be passed through:
DEADLINE="$DEADLINE" \
EXTRA_TEXT="$EXTRA_TEXT" \
LANG="$lang" \
MULTIPLE_TRANSLATORS_TEXT="$multiple_translators_text" \
RELEASE="$RELEASE" \
SPLIT_TRANSLATORS=$(sed -re 's/^/@/; s/,/, @/g' <<<"$translators") \
TITLE="$title" \
TRANSLATE_BRANCH=translate${RELEASE//./_} \
envsubst <<<"$body_template"
)

# Check for an existing issue
local existing_issue=$(gh issue list --milestone "$MILESTONE" --state all --search "$title" --json number --jq '.[0].number' || true)

# If there's no existing issue, create one
if [[ -z $existing_issue ]]; then
echo "Creating Issue to translate $lang for $RELEASE"
URL=$(gh issue create --title "$title" --label translation --project "$PROJECT" --body "$body" --assignee "$translators" --milestone "$MILESTONE")
existing_issue=${URL/*\/}
else
echo "Issue to translate $lang for $RELEASE already exists"
fi

# Compare the (now) existing issue's body with the desired body and
# update the issue if the bodies differ.
# This is used on initial creation to fill in the issue number and it
# can be used to update the body text afterwards.
local online_body=$(gh issue view "$existing_issue" --json body --jq .body)
body=${body//<Insert this issue\'s number here>/${existing_issue}}
if [[ "$online_body" != "$body" ]]; then
echo "Updating Issue to translate $lang for $RELEASE"
gh issue edit "$existing_issue" --body "$body" >/dev/null
fi
}

create_translation_issues
43 changes: 35 additions & 8 deletions tools/get_release_contributors.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import argparse
import logging
import os
import re
import subprocess
import yaml

Expand All @@ -27,7 +28,9 @@ class UnexpectedGithubStatus(RuntimeError):


# List of user names which should be ignored (such as bots):
ignore_list = ['github-actions[bot]']
ignore_list = ['github-actions[bot]', 'imgbot[bot]']

CHARSET = 'utf-8'


class Authors:
Expand Down Expand Up @@ -61,8 +64,11 @@ def get_login(self, key, commit_hash):
Once looked up, the results are cached in a local file.
"""
if key not in self.keys_to_user:
self.keys_to_user[key] = self.get_user_by_commit(commit_hash)
self.save()
if commit_hash:
self.keys_to_user[key] = self.get_user_by_commit(commit_hash)
self.save()
else:
return None
return self.keys_to_user[key]

def get_user_by_commit(self, hash):
Expand All @@ -79,7 +85,7 @@ def get_user_by_commit(self, hash):
if 200 <= r.status_code < 300:
try:
return r.json()['author']['login']
except TypeError:
except (TypeError, KeyError):
logger.warning('%s has not github author, saving as empty', hash)
return ''
if r.status_code == 422:
Expand Down Expand Up @@ -150,12 +156,33 @@ def find_contributors(git_log_selector, from_, to):
`from_` and `to` can be any committish such as a commit hash or a tag.
"""
contributors = set()
commits = subprocess.check_output(['git', 'log', '--format=format:%H %an <%ae>', '%s..%s' % (from_, to), '--'] + git_log_selector)
commits = commits.decode('utf-8')
for commit in commits.split('\n'):
hash, author_key = commit.split(' ', 1)
co_author_keys = set()
commits = subprocess.check_output(['git', 'log', '-z', '--format=format:%H %an <%ae>%n%b', '%s..%s' % (from_, to), '--'] + git_log_selector)
commits = commits.decode(CHARSET)
for commit in commits.split('\0'):
if not commit:
continue
hash, author_key = commit.split('\n', 1)[0].split(' ', 1)
login = authors.get_login(author_key, hash)
contributors.add(login)
co_authors = re.findall('Co-authored-by:\s*(\S.*(<[^ >]+>))\s*\n', commit, re.I)
for co_author_full, co_author_email in co_authors:
login = authors.get_login(co_author_full, None)
if not login:
# try to find a previous commit by this mail address
# and pass this commit id to get_login() to retrieve the
# associated handle from the github API.
commit = subprocess.check_output(['git', 'log', '--format=%H', '--max-count=1', '--author=%s' % re.escape(co_author_email)]).strip().decode(CHARSET)
if commit:
login = authors.get_login(co_author_full, commit)
if login:
contributors.add(login)

# Resolve co-authors last because we have to rely on having seen the
# email-to-login mapping via some other commit.
for co_author in co_author_keys:
login = authors.get_login(co_author, None)
contributors.add(login)
return sorted(contributors, key=str.casefold)


Expand Down

0 comments on commit 36224e8

Please sign in to comment.