diff --git a/.env b/.env index 5b3b9730a..3d04820b8 100644 --- a/.env +++ b/.env @@ -1,4 +1,4 @@ -FAABRIC_VERSION=0.3.0 -FAABRIC_CLI_IMAGE=faasm/faabric:0.3.0 +FAABRIC_VERSION=0.3.1 +FAABRIC_CLI_IMAGE=faasm/faabric:0.3.1 COMPOSE_PROJECT_NAME=faabric-dev CONAN_CACHE_MOUNT_SOURCE=./conan-cache/ diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index df810a415..0462e2c9d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -16,7 +16,7 @@ jobs: if: github.event.pull_request.draft == false runs-on: ubuntu-latest container: - image: faasm/faabric:0.3.0 + image: faasm/faabric:0.3.1 defaults: run: working-directory: /code/faabric @@ -31,7 +31,7 @@ jobs: if: github.event.pull_request.draft == false runs-on: ubuntu-latest container: - image: faasm/faabric:0.3.0 + image: faasm/faabric:0.3.1 defaults: run: working-directory: /code/faabric @@ -47,7 +47,7 @@ jobs: if: github.event.pull_request.draft == false runs-on: ubuntu-latest container: - image: faasm/faabric:0.3.0 + image: faasm/faabric:0.3.1 defaults: run: working-directory: /code/faabric @@ -81,7 +81,7 @@ jobs: TSAN_OPTIONS: "verbosity=1:halt_on_error=1:suppressions=/code/faabric/thread-sanitizer-ignorelist.txt:history_size=7" UBSAN_OPTIONS: "print_stacktrace=1:halt_on_error=1" container: - image: faasm/faabric:0.3.0 + image: faasm/faabric:0.3.1 defaults: run: working-directory: /code/faabric @@ -130,7 +130,7 @@ jobs: REDIS_QUEUE_HOST: redis REDIS_STATE_HOST: redis container: - image: faasm/faabric:0.3.0 + image: faasm/faabric:0.3.1 defaults: run: working-directory: /code/faabric diff --git a/.gitignore b/.gitignore index 3fdf4508e..4d1d564ba 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,9 @@ conan-cache/ .clangd compile_commands.json +# Faabric config file +faabric.ini + # Ansible *.retry diff --git a/VERSION b/VERSION index 0d91a54c7..9e11b32fc 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.3.0 +0.3.1 diff --git a/cliff.toml b/cliff.toml new file mode 100644 index 000000000..e02d9752b --- /dev/null +++ b/cliff.toml @@ -0,0 +1,57 @@ +# configuration file for git-cliff (0.1.0) + +[changelog] +# changelog header +header = """ +Here is what has changed since last release: + +""" +# template for the changelog body +# https://tera.netlify.app/docs/#introduction +body = """ +{% if version %}\ + ## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }} +{% else %}\ + ## [unreleased] +{% endif %}\ +{% for commit in commits %} * {{ commit.message | upper_first | split(pat="\n") | first }} +{% endfor %} + +""" +# remove the leading and trailing whitespace from the template +trim = true +# changelog footer +footer = """ + +""" + +[git] +# parse the commits based on https://www.conventionalcommits.org +conventional_commits = false +# filter out the commits that are not conventional +filter_unconventional = false +# regex for parsing and grouping commits +commit_parsers = [ + { message = "^feat", group = "Features"}, + { message = "^fix", group = "Bug Fixes"}, + { message = "^doc", group = "Documentation"}, + { message = "^perf", group = "Performance"}, + { message = "^refactor", group = "Refactor"}, + { message = "^style", group = "Styling"}, + { message = "^test", group = "Testing"}, + { message = "^chore\\(release\\): prepare for", skip = true}, + { message = "^chore", group = "Miscellaneous Tasks"}, + { body = ".*security", group = "Security"}, +] +# filter out the commits that are not matched by commit parsers +filter_commits = false +# glob pattern for matching git tags +tag_pattern = "v[0-9]*" +# regex for skipping tags +skip_tags = "v0.1.0-beta.1" +# regex for ignoring tags +ignore_tags = "" +# sort the tags chronologically +date_order = true +# sort the commits inside sections by oldest/newest order +sort_commits = "newest" diff --git a/docs/source/development.md b/docs/source/development.md index 2c7e08d96..819784f38 100644 --- a/docs/source/development.md +++ b/docs/source/development.md @@ -127,7 +127,7 @@ docker-compose stop ./dist-test/run.sh ``` -## Releasing +## Creating a new tag Create a new branch, then find and replace the current version with the relevant bumped version. It should appear in: @@ -154,10 +154,17 @@ If you want to overwrite a tag, you can run: inv git.tag --force ``` +After the new tag has been merged in, and in order to keep a clean commit +history, you may re-tag the code again: + +```bash +inv git.tag --force +``` + ### Building images manually -Containers are built with Github Actions, so you should only need to build them -yourself when diagnosing issues. +Containers are built with Github Actions, when a new tag is pushed, so you +should only need to build them yourself when diagnosing issues. To build the main container, run: @@ -174,3 +181,35 @@ inv container.push inv container.build --push ``` +## Publishing a release + +To publish a release in Github, make sure you are in the main branch, and have +just tagged the code (see previous section). + +Then, you can create a release on [Github](https://github.com/faasm/faabric/releases) +and publish it from the command line. If it is the first time you are creating +a release you will have to configure a Github access token (see below). + +First, generate a draft release: + +```bash +inv git.release_create +``` + +Then, after verifying that the release looks fine, you may publish it: + +```bash +inv git.release_publish +``` + +### Configuring a Github access token + +Follow the instructions on [how to create a personal access token]( +https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token). +Then, create a config file for faabric in the main directory named +`faabric.ini` with the following contents: + +```toml +[Github] +access_token = +``` diff --git a/mpi-native/mpi-native.env b/mpi-native/mpi-native.env index 93415f3ea..6f29fbd17 100644 --- a/mpi-native/mpi-native.env +++ b/mpi-native/mpi-native.env @@ -1,4 +1,4 @@ -FAABRIC_VERSION=0.3.0 +FAABRIC_VERSION=0.3.1 FAABRIC_MPI_NATIVE_IMAGE=faasm/faabric-mpi-native:0.0.18 COMPOSE_PROJECT_NAME=faabric-mpi diff --git a/requirements.txt b/requirements.txt index 9f520d22a..ae4c99491 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,5 +5,6 @@ flake8==4.0.1 invoke==1.6.0 myst-parser==0.16.1 numpy==1.21.5 +PyGithub==1.55 redis==4.1.0 sphinx-rtd-theme==1.0.0 diff --git a/tasks/git.py b/tasks/git.py index 254082322..3f2eed174 100644 --- a/tasks/git.py +++ b/tasks/git.py @@ -1,8 +1,11 @@ +from github import Github from invoke import task +from tasks.util.env import get_faabric_config, get_version, PROJ_ROOT +from subprocess import run, PIPE, STDOUT -from tasks.util.env import get_version, PROJ_ROOT -from subprocess import run +def get_tag_name(version): + return "v{}".format(version) @task @@ -10,7 +13,7 @@ def tag(ctx, force=False): """ Creates git tag from the current tree """ - git_tag = "v{}".format(get_version()) + git_tag = get_tag_name(get_version()) run( "git tag {} {}".format("--force" if force else "", git_tag), shell=True, @@ -24,3 +27,96 @@ def tag(ctx, force=False): check=True, cwd=PROJ_ROOT, ) + + +def is_git_submodule(): + git_cmd = "git rev-parse --show-superproject-working-tree" + result = run(git_cmd, shell=True, stdout=PIPE, stderr=STDOUT) + return result.stdout.decode("utf-8") != "" + + +def get_github_instance(): + conf = get_faabric_config() + + if not conf.has_section("Github") or not conf.has_option( + "Github", "access_token" + ): + print("Must set up Github config with access token") + + token = conf["Github"]["access_token"] + g = Github(token) + return g + + +def get_repo(): + g = get_github_instance() + return g.get_repo("faasm/faabric") + + +def get_release(): + r = get_repo() + rels = r.get_releases() + + return rels[0] + + +def get_release_body(): + """ + Generate body for release with detailed changelog + """ + if is_git_submodule(): + docker_cmd = [ + "docker run -t -v", + "{}/..:/app/".format(PROJ_ROOT), + "orhunp/git-cliff:latest", + "--config ./faabric/cliff.toml", + "--repository ./faabric", + "{}..v{}".format(get_release().tag_name, get_version()), + ] + else: + docker_cmd = [ + "docker run -t -v", + "{}:/app/".format(PROJ_ROOT), + "orhunp/git-cliff:latest", + "--config cliff.toml", + "--repository .", + "{}..v{}".format(get_release().tag_name, get_version()), + ] + + cmd = " ".join(docker_cmd) + print("Generating release body...") + print(cmd) + result = run(cmd, shell=True, stdout=PIPE, stderr=PIPE) + + return result.stdout.decode("utf-8") + + +@task +def release_create(ctx): + """ + Create a draft release on Github + """ + # Work out the tag + faabric_ver = get_version() + tag_name = get_tag_name(faabric_ver) + + # Create a release in github from this tag + r = get_repo() + r.create_git_release( + tag_name, + "Faabric {}".format(faabric_ver), + get_release_body(), + draft=True, + ) + + print("You may now review the draft release in:") + print("https://github.com/faasm/faabric/releases") + + +@task +def release_publish(ctx): + """ + Publish the draft release + """ + rel = get_release() + rel.update_release(rel.title, rel.raw_data["body"], draft=False) diff --git a/tasks/util/env.py b/tasks/util/env.py index 34f96c33d..d1ef86a66 100644 --- a/tasks/util/env.py +++ b/tasks/util/env.py @@ -1,5 +1,6 @@ from os import environ -from os.path import dirname, realpath, join, expanduser +from os.path import dirname, exists, realpath, join, expanduser +import configparser HOME_DIR = expanduser("~") PROJ_ROOT = dirname(dirname(dirname(realpath(__file__)))) @@ -11,6 +12,8 @@ FAABRIC_INSTALL_PREFIX = join(_FAABRIC_BUILD_DIR, "install") +FAABRIC_CONFIG_FILE = join(PROJ_ROOT, "faabric.ini") + def get_version(): ver_file = join(PROJ_ROOT, "VERSION") @@ -20,3 +23,16 @@ def get_version(): version = version.strip() return version + + +def get_faabric_config(): + config = configparser.ConfigParser() + if not exists(FAABRIC_CONFIG_FILE): + print("Creating config file at {}".format(FAABRIC_CONFIG_FILE)) + + with open(FAABRIC_CONFIG_FILE, "w") as fh: + config.write(fh) + else: + config.read(FAABRIC_CONFIG_FILE) + + return config