From 37d46d83c2e0a303c5ed1874713596c0c5e1d982 Mon Sep 17 00:00:00 2001 From: Christian Hoffmann Date: Tue, 8 Mar 2022 00:38:48 +0100 Subject: [PATCH 1/4] Autobuild: Refactor and clean up analyze_git_references.py --- .../actions_scripts/analyse_git_reference.py | 145 ++++++++---------- 1 file changed, 67 insertions(+), 78 deletions(-) diff --git a/.github/actions_scripts/analyse_git_reference.py b/.github/actions_scripts/analyse_git_reference.py index 5ea17c3c62..fd8f8cd1e9 100755 --- a/.github/actions_scripts/analyse_git_reference.py +++ b/.github/actions_scripts/analyse_git_reference.py @@ -1,112 +1,101 @@ #!/usr/bin/python3 +# This script is trigged from the Github Autobuild workflow. +# It analyzes Jamulus.pro and git push details (tag vs. branch, etc.) to decide +# - whether a release should be created, +# - whether it is a pre-release, and +# - what its title should be. -# -# on a triggered github workflow, this file does the decisions and variagles like -# - shall the build be released (otherwise just run builds to check if there are errors) -# - is it a prerelease -# - title, tag etc of release_tag -# -# see the last lines of the file to see what variables are set -# - - -import sys import os import re import subprocess -# get the jamulus version from the .pro file -def get_jamulus_version(repo_path_on_disk): - jamulus_version = "" - with open (repo_path_on_disk + '/Jamulus.pro','r') as f: +REPO_PATH = os.path.join(os.path.dirname(__file__), '..', '..') + + +def get_version_from_jamulus_pro(): + with open(REPO_PATH + '/Jamulus.pro', 'r') as f: pro_content = f.read() - pro_content = pro_content.replace('\r','') - pro_lines = pro_content.split('\n') - for line in pro_lines: - line = line.strip() - VERSION_LINE_STARTSWITH = 'VERSION = ' - if line.startswith(VERSION_LINE_STARTSWITH): - jamulus_version = line[len(VERSION_LINE_STARTSWITH):] - return jamulus_version - return "UNKNOWN_VERSION" + m = re.search(r'^VERSION\s*=\s*(\S+)$', pro_content, re.MULTILINE) + if not m: + raise Exception("Unable to determine Jamulus.pro VERSION") + return m.group(1) + def get_git_hash(): - return subprocess.check_output(['git', 'describe', '--match=xxxxxxxxxxxxxxxxxxxx', '--always', '--abbrev', '--dirty']).decode('ascii').strip() - #return subprocess.check_output(['git', 'rev-parse', 'HEAD']) - #return subprocess.check_output(['git', 'rev-parse', '--short', 'HEAD']) + return subprocess.check_output([ + 'git', + 'describe', + '--match=xxxxxxxxxxxxxxxxxxxx', + '--always', + '--abbrev', + '--dirty' + ]).decode('ascii').strip() + + +def write_changelog(version): + changelog = subprocess.check_output([ + 'perl', + f'{REPO_PATH}/.github/actions_scripts/getChangelog.pl', + f'{REPO_PATH}/ChangeLog', + version, + ]) + with open(f'{REPO_PATH}/autoLatestChangelog.md', 'wb') as f: + f.write(changelog) + + +def get_release_version_name(jamulus_pro_version): + if "dev" in jamulus_pro_version: + name = "{}-{}".format(jamulus_pro_version, get_git_hash()) + print("building an intermediate version: ", name) + return name + + name = jamulus_pro_version + print("building a release version: ", name) + return name + + +def set_github_variable(varname, varval): + print("{}='{}'".format(varname, varval)) # console output + print("::set-output name={}::{}".format(varname, varval)) -if len(sys.argv) == 1: - pass -else: - print('wrong number of arguments') - print('Number of arguments:', len(sys.argv), 'arguments.') - print('Argument List:', str(sys.argv)) - raise Exception("wrong agruments") - -# derive workspace-path -repo_path_on_disk = os.environ['GITHUB_WORKSPACE'] - -# derive git related variables -version_from_changelog = get_jamulus_version(repo_path_on_disk) -if "dev" in version_from_changelog: - release_version_name = "{}-{}".format(version_from_changelog, get_git_hash()) - print("building an intermediate version: ", release_version_name) -else: - release_version_name = version_from_changelog - print("building a release version: ", release_version_name) +jamulus_pro_version = get_version_from_jamulus_pro() +write_changelog(jamulus_pro_version) +release_version_name = get_release_version_name(jamulus_pro_version) -fullref=os.environ['GITHUB_REF'] +fullref = os.environ['GITHUB_REF'] reflist = fullref.split("/", 2) pushed_name = reflist[2] - -# run Changelog-script -os.system('perl "{}"/.github/actions_scripts/getChangelog.pl "{}"/ChangeLog "{}" > "{}"/autoLatestChangelog.md'.format( - os.environ['GITHUB_WORKSPACE'], - os.environ['GITHUB_WORKSPACE'], - version_from_changelog, - os.environ['GITHUB_WORKSPACE'] -)) - -# decisions about release, prerelease, title and tag +# decisions about release, prerelease, title and tag: +publish_to_release = False +is_prerelease = True if fullref.startswith("refs/tags/"): print('this reference is a Tag') - release_tag = pushed_name # tag already exists - release_title="Release {} ({})".format(release_version_name, pushed_name) + release_tag = pushed_name # tag already exists + release_title = "Release {} ({})".format(release_version_name, pushed_name) if pushed_name.startswith("r"): + publish_to_release = True if re.match(r'^r\d+_\d+_\d+$', pushed_name): print('this reference is a Release-Tag') - publish_to_release = True is_prerelease = False else: print('this reference is a Non-Release-Tag') - publish_to_release = True - is_prerelease = True else: print('this reference is a Non-Release-Tag') - publish_to_release = False - is_prerelease = True # just in case + elif fullref.startswith("refs/heads/"): print('this reference is a Head/Branch') - publish_to_release = False - is_prerelease = True - release_title='Pre-Release of "{}"'.format(pushed_name) - release_tag = "releasetag/"+pushed_name #better not use pure pushed name, creates a tag with the name of the branch, leads to ambiguous references => can not push to this branch easily + release_title = 'Pre-Release of "{}"'.format(pushed_name) + release_tag = "releasetag/" + pushed_name # better not use pure pushed name, creates a tag with the name of the branch, leads to ambiguous references => can not push to this branch easily + else: print('unknown git-reference type: ' + fullref) - publish_to_release = False - is_prerelease = True - release_title='Pre-Release of "{}"'.format(pushed_name) - release_tag = "releasetag/"+pushed_name #avoid ambiguity in references in all cases - -#helper function: set github variable and print it to console -def set_github_variable(varname, varval): - print("{}='{}'".format(varname, varval)) #console output - print("::set-output name={}::{}".format(varname, varval)) + release_title = 'Pre-Release of "{}"'.format(pushed_name) + release_tag = "releasetag/" + pushed_name # avoid ambiguity in references in all cases -#set github-available variables +# set github-available variables set_github_variable("PUBLISH_TO_RELEASE", str(publish_to_release).lower()) set_github_variable("IS_PRERELEASE", str(is_prerelease).lower()) set_github_variable("RELEASE_TITLE", release_title) From aab078f938208c9a100ccd7c978c4b65f0cacecf Mon Sep 17 00:00:00 2001 From: Christian Hoffmann Date: Tue, 8 Mar 2022 00:59:29 +0100 Subject: [PATCH 2/4] Autobuild: Simplify variable outputs in analyze_git_references.py The following variable is not referenced in the Autobuild workflow at all and can therefore be safely dropped from the script output: PUSHED_NAME The following variables are referenced in the Autobuild workflow and are declared as outputs, but those outputs are not referred to anywhere. Therefore, they can safely be dropped: - PUSHED_NAME - X_GITHUB_WORKSPACE The following variables are only relevant for releases (PUBLISH_TO_RELEASE=true): - RELEASE_TITLE - RELEASE_TAG - IS_PRERELEASE Therefore, we only need to calculate their value for actual releases. This vastly simplifies the script logic. --- .../actions_scripts/analyse_git_reference.py | 59 +++++++------------ .github/workflows/autobuild.yml | 3 - 2 files changed, 20 insertions(+), 42 deletions(-) diff --git a/.github/actions_scripts/analyse_git_reference.py b/.github/actions_scripts/analyse_git_reference.py index fd8f8cd1e9..405321d295 100755 --- a/.github/actions_scripts/analyse_git_reference.py +++ b/.github/actions_scripts/analyse_git_reference.py @@ -64,43 +64,24 @@ def set_github_variable(varname, varval): release_version_name = get_release_version_name(jamulus_pro_version) fullref = os.environ['GITHUB_REF'] -reflist = fullref.split("/", 2) -pushed_name = reflist[2] - -# decisions about release, prerelease, title and tag: -publish_to_release = False -is_prerelease = True -if fullref.startswith("refs/tags/"): - print('this reference is a Tag') - release_tag = pushed_name # tag already exists - release_title = "Release {} ({})".format(release_version_name, pushed_name) - - if pushed_name.startswith("r"): - publish_to_release = True - if re.match(r'^r\d+_\d+_\d+$', pushed_name): - print('this reference is a Release-Tag') - is_prerelease = False - else: - print('this reference is a Non-Release-Tag') - else: - print('this reference is a Non-Release-Tag') - -elif fullref.startswith("refs/heads/"): - print('this reference is a Head/Branch') - release_title = 'Pre-Release of "{}"'.format(pushed_name) - release_tag = "releasetag/" + pushed_name # better not use pure pushed name, creates a tag with the name of the branch, leads to ambiguous references => can not push to this branch easily - -else: - print('unknown git-reference type: ' + fullref) - release_title = 'Pre-Release of "{}"'.format(pushed_name) - release_tag = "releasetag/" + pushed_name # avoid ambiguity in references in all cases - -# set github-available variables -set_github_variable("PUBLISH_TO_RELEASE", str(publish_to_release).lower()) -set_github_variable("IS_PRERELEASE", str(is_prerelease).lower()) -set_github_variable("RELEASE_TITLE", release_title) -set_github_variable("RELEASE_TAG", release_tag) -set_github_variable("PUSHED_NAME", pushed_name) -set_github_variable("JAMULUS_VERSION", release_version_name) +publish_to_release = fullref.startswith('refs/tags/r') + +# RELEASE_VERSION_NAME is required for all builds including branch pushes +# and PRs: set_github_variable("RELEASE_VERSION_NAME", release_version_name) -set_github_variable("X_GITHUB_WORKSPACE", os.environ['GITHUB_WORKSPACE']) + +# PUBLISH_TO_RELEASE is always required as the workflow decides about further +# steps based on this. It will only be true for tag pushes with a tag +# starting with "r". +set_github_variable("PUBLISH_TO_RELEASE", str(publish_to_release).lower()) + +if publish_to_release: + reflist = fullref.split("/", 2) + release_tag = reflist[2] + release_title = f"Release {release_version_name} ({release_tag})" + is_prerelease = not re.match(r'^r\d+_\d+_\d+$', release_tag) + + # Those variables are only used when a release is created at all: + set_github_variable("IS_PRERELEASE", str(is_prerelease).lower()) + set_github_variable("RELEASE_TITLE", release_title) + set_github_variable("RELEASE_TAG", release_tag) diff --git a/.github/workflows/autobuild.yml b/.github/workflows/autobuild.yml index 692c770949..c88b65b709 100644 --- a/.github/workflows/autobuild.yml +++ b/.github/workflows/autobuild.yml @@ -39,10 +39,7 @@ jobs: outputs: publish_to_release: ${{ steps.jamulus-build-vars.outputs.PUBLISH_TO_RELEASE }} upload_url: ${{ steps.create_release_step.outputs.upload_url }} - version: ${{ steps.jamulus-build-vars.outputs.JAMULUS_VERSION }} version_name: ${{ steps.jamulus-build-vars.outputs.RELEASE_VERSION_NAME }} - x_github_workspace: ${{ steps.jamulus-build-vars.outputs.X_GITHUB_WORKSPACE }} #needed, because matrix can not directly access ${{ github.workspace }} aparrently - steps: # Checkout code From 128f3132328e03beadeab74fc743dedfeb2284ee Mon Sep 17 00:00:00 2001 From: Christian Hoffmann Date: Wed, 9 Mar 2022 11:03:34 +0100 Subject: [PATCH 3/4] Autobuild: Handle non-version tag pushes consistently Previously, a push to `rExample` would create a release (due to the tag starting with `r`) while a push to `Example` would not. We should only create (pre-)releases on pushes to `r`. This commit ensures that. --- .github/actions_scripts/analyse_git_reference.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions_scripts/analyse_git_reference.py b/.github/actions_scripts/analyse_git_reference.py index 405321d295..e5cc53bfaa 100755 --- a/.github/actions_scripts/analyse_git_reference.py +++ b/.github/actions_scripts/analyse_git_reference.py @@ -64,7 +64,7 @@ def set_github_variable(varname, varval): release_version_name = get_release_version_name(jamulus_pro_version) fullref = os.environ['GITHUB_REF'] -publish_to_release = fullref.startswith('refs/tags/r') +publish_to_release = bool(re.match(r'^refs/tags/r\d+_\d+_\d+\S*$', fullref)) # RELEASE_VERSION_NAME is required for all builds including branch pushes # and PRs: From 24db7f5a4e0984269bba9debb389429725a0ebe7 Mon Sep 17 00:00:00 2001 From: Christian Hoffmann Date: Wed, 9 Mar 2022 11:13:18 +0100 Subject: [PATCH 4/4] Autobuild: Error out if release tag pushes don't match Jamulus.pro VERSION --- .github/actions_scripts/analyse_git_reference.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/actions_scripts/analyse_git_reference.py b/.github/actions_scripts/analyse_git_reference.py index e5cc53bfaa..f2f5cc4990 100755 --- a/.github/actions_scripts/analyse_git_reference.py +++ b/.github/actions_scripts/analyse_git_reference.py @@ -80,6 +80,8 @@ def set_github_variable(varname, varval): release_tag = reflist[2] release_title = f"Release {release_version_name} ({release_tag})" is_prerelease = not re.match(r'^r\d+_\d+_\d+$', release_tag) + if not is_prerelease and release_version_name != release_tag[1:].replace('_', '.'): + raise Exception(f"non-pre-release tag {release_tag} doesn't match Jamulus.pro VERSION = {release_version_name}") # Those variables are only used when a release is created at all: set_github_variable("IS_PRERELEASE", str(is_prerelease).lower())