Skip to content

Commit b11e8ab

Browse files
authored
Add task to generate release body (#233)
* bumping code version for release * ci: add step to generate changelog * ci: generate release body with changelog * ci: add task to generate release body without dependencies * docs: update docs with latest releasing info * cli: support running both as a submodule and as a standalone project * ci: change format of release template so that it only includes the pr title * ci: automate release creation/publishing from tasks
1 parent 88ef806 commit b11e8ab

10 files changed

Lines changed: 228 additions & 16 deletions

File tree

.env

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FAABRIC_VERSION=0.3.0
2-
FAABRIC_CLI_IMAGE=faasm/faabric:0.3.0
1+
FAABRIC_VERSION=0.3.1
2+
FAABRIC_CLI_IMAGE=faasm/faabric:0.3.1
33
COMPOSE_PROJECT_NAME=faabric-dev
44
CONAN_CACHE_MOUNT_SOURCE=./conan-cache/

.github/workflows/tests.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
if: github.event.pull_request.draft == false
1717
runs-on: ubuntu-latest
1818
container:
19-
image: faasm/faabric:0.3.0
19+
image: faasm/faabric:0.3.1
2020
defaults:
2121
run:
2222
working-directory: /code/faabric
@@ -31,7 +31,7 @@ jobs:
3131
if: github.event.pull_request.draft == false
3232
runs-on: ubuntu-latest
3333
container:
34-
image: faasm/faabric:0.3.0
34+
image: faasm/faabric:0.3.1
3535
defaults:
3636
run:
3737
working-directory: /code/faabric
@@ -47,7 +47,7 @@ jobs:
4747
if: github.event.pull_request.draft == false
4848
runs-on: ubuntu-latest
4949
container:
50-
image: faasm/faabric:0.3.0
50+
image: faasm/faabric:0.3.1
5151
defaults:
5252
run:
5353
working-directory: /code/faabric
@@ -81,7 +81,7 @@ jobs:
8181
TSAN_OPTIONS: "verbosity=1:halt_on_error=1:suppressions=/code/faabric/thread-sanitizer-ignorelist.txt:history_size=7"
8282
UBSAN_OPTIONS: "print_stacktrace=1:halt_on_error=1"
8383
container:
84-
image: faasm/faabric:0.3.0
84+
image: faasm/faabric:0.3.1
8585
defaults:
8686
run:
8787
working-directory: /code/faabric
@@ -130,7 +130,7 @@ jobs:
130130
REDIS_QUEUE_HOST: redis
131131
REDIS_STATE_HOST: redis
132132
container:
133-
image: faasm/faabric:0.3.0
133+
image: faasm/faabric:0.3.1
134134
defaults:
135135
run:
136136
working-directory: /code/faabric

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ conan-cache/
55
.clangd
66
compile_commands.json
77

8+
# Faabric config file
9+
faabric.ini
10+
811
# Ansible
912
*.retry
1013

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.3.0
1+
0.3.1

cliff.toml

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# configuration file for git-cliff (0.1.0)
2+
3+
[changelog]
4+
# changelog header
5+
header = """
6+
Here is what has changed since last release:
7+
8+
"""
9+
# template for the changelog body
10+
# https://tera.netlify.app/docs/#introduction
11+
body = """
12+
{% if version %}\
13+
## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }}
14+
{% else %}\
15+
## [unreleased]
16+
{% endif %}\
17+
{% for commit in commits %} * {{ commit.message | upper_first | split(pat="\n") | first }}
18+
{% endfor %}
19+
20+
"""
21+
# remove the leading and trailing whitespace from the template
22+
trim = true
23+
# changelog footer
24+
footer = """
25+
<!-- generated by git-cliff -->
26+
"""
27+
28+
[git]
29+
# parse the commits based on https://www.conventionalcommits.org
30+
conventional_commits = false
31+
# filter out the commits that are not conventional
32+
filter_unconventional = false
33+
# regex for parsing and grouping commits
34+
commit_parsers = [
35+
{ message = "^feat", group = "Features"},
36+
{ message = "^fix", group = "Bug Fixes"},
37+
{ message = "^doc", group = "Documentation"},
38+
{ message = "^perf", group = "Performance"},
39+
{ message = "^refactor", group = "Refactor"},
40+
{ message = "^style", group = "Styling"},
41+
{ message = "^test", group = "Testing"},
42+
{ message = "^chore\\(release\\): prepare for", skip = true},
43+
{ message = "^chore", group = "Miscellaneous Tasks"},
44+
{ body = ".*security", group = "Security"},
45+
]
46+
# filter out the commits that are not matched by commit parsers
47+
filter_commits = false
48+
# glob pattern for matching git tags
49+
tag_pattern = "v[0-9]*"
50+
# regex for skipping tags
51+
skip_tags = "v0.1.0-beta.1"
52+
# regex for ignoring tags
53+
ignore_tags = ""
54+
# sort the tags chronologically
55+
date_order = true
56+
# sort the commits inside sections by oldest/newest order
57+
sort_commits = "newest"

docs/source/development.md

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ docker-compose stop
127127
./dist-test/run.sh
128128
```
129129

130-
## Releasing
130+
## Creating a new tag
131131

132132
Create a new branch, then find and replace the current version with the relevant
133133
bumped version. It should appear in:
@@ -154,10 +154,17 @@ If you want to overwrite a tag, you can run:
154154
inv git.tag --force
155155
```
156156

157+
After the new tag has been merged in, and in order to keep a clean commit
158+
history, you may re-tag the code again:
159+
160+
```bash
161+
inv git.tag --force
162+
```
163+
157164
### Building images manually
158165

159-
Containers are built with Github Actions, so you should only need to build them
160-
yourself when diagnosing issues.
166+
Containers are built with Github Actions, when a new tag is pushed, so you
167+
should only need to build them yourself when diagnosing issues.
161168

162169
To build the main container, run:
163170

@@ -174,3 +181,35 @@ inv container.push
174181
inv container.build --push
175182
```
176183

184+
## Publishing a release
185+
186+
To publish a release in Github, make sure you are in the main branch, and have
187+
just tagged the code (see previous section).
188+
189+
Then, you can create a release on [Github](https://github.com/faasm/faabric/releases)
190+
and publish it from the command line. If it is the first time you are creating
191+
a release you will have to configure a Github access token (see below).
192+
193+
First, generate a draft release:
194+
195+
```bash
196+
inv git.release_create
197+
```
198+
199+
Then, after verifying that the release looks fine, you may publish it:
200+
201+
```bash
202+
inv git.release_publish
203+
```
204+
205+
### Configuring a Github access token
206+
207+
Follow the instructions on [how to create a personal access token](
208+
https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token).
209+
Then, create a config file for faabric in the main directory named
210+
`faabric.ini` with the following contents:
211+
212+
```toml
213+
[Github]
214+
access_token = <paste your personal access token>
215+
```

mpi-native/mpi-native.env

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FAABRIC_VERSION=0.3.0
1+
FAABRIC_VERSION=0.3.1
22
FAABRIC_MPI_NATIVE_IMAGE=faasm/faabric-mpi-native:0.0.18
33
COMPOSE_PROJECT_NAME=faabric-mpi
44

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ flake8==4.0.1
55
invoke==1.6.0
66
myst-parser==0.16.1
77
numpy==1.21.5
8+
PyGithub==1.55
89
redis==4.1.0
910
sphinx-rtd-theme==1.0.0

tasks/git.py

Lines changed: 99 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
1+
from github import Github
12
from invoke import task
3+
from tasks.util.env import get_faabric_config, get_version, PROJ_ROOT
4+
from subprocess import run, PIPE, STDOUT
25

3-
from tasks.util.env import get_version, PROJ_ROOT
46

5-
from subprocess import run
7+
def get_tag_name(version):
8+
return "v{}".format(version)
69

710

811
@task
912
def tag(ctx, force=False):
1013
"""
1114
Creates git tag from the current tree
1215
"""
13-
git_tag = "v{}".format(get_version())
16+
git_tag = get_tag_name(get_version())
1417
run(
1518
"git tag {} {}".format("--force" if force else "", git_tag),
1619
shell=True,
@@ -24,3 +27,96 @@ def tag(ctx, force=False):
2427
check=True,
2528
cwd=PROJ_ROOT,
2629
)
30+
31+
32+
def is_git_submodule():
33+
git_cmd = "git rev-parse --show-superproject-working-tree"
34+
result = run(git_cmd, shell=True, stdout=PIPE, stderr=STDOUT)
35+
return result.stdout.decode("utf-8") != ""
36+
37+
38+
def get_github_instance():
39+
conf = get_faabric_config()
40+
41+
if not conf.has_section("Github") or not conf.has_option(
42+
"Github", "access_token"
43+
):
44+
print("Must set up Github config with access token")
45+
46+
token = conf["Github"]["access_token"]
47+
g = Github(token)
48+
return g
49+
50+
51+
def get_repo():
52+
g = get_github_instance()
53+
return g.get_repo("faasm/faabric")
54+
55+
56+
def get_release():
57+
r = get_repo()
58+
rels = r.get_releases()
59+
60+
return rels[0]
61+
62+
63+
def get_release_body():
64+
"""
65+
Generate body for release with detailed changelog
66+
"""
67+
if is_git_submodule():
68+
docker_cmd = [
69+
"docker run -t -v",
70+
"{}/..:/app/".format(PROJ_ROOT),
71+
"orhunp/git-cliff:latest",
72+
"--config ./faabric/cliff.toml",
73+
"--repository ./faabric",
74+
"{}..v{}".format(get_release().tag_name, get_version()),
75+
]
76+
else:
77+
docker_cmd = [
78+
"docker run -t -v",
79+
"{}:/app/".format(PROJ_ROOT),
80+
"orhunp/git-cliff:latest",
81+
"--config cliff.toml",
82+
"--repository .",
83+
"{}..v{}".format(get_release().tag_name, get_version()),
84+
]
85+
86+
cmd = " ".join(docker_cmd)
87+
print("Generating release body...")
88+
print(cmd)
89+
result = run(cmd, shell=True, stdout=PIPE, stderr=PIPE)
90+
91+
return result.stdout.decode("utf-8")
92+
93+
94+
@task
95+
def release_create(ctx):
96+
"""
97+
Create a draft release on Github
98+
"""
99+
# Work out the tag
100+
faabric_ver = get_version()
101+
tag_name = get_tag_name(faabric_ver)
102+
103+
# Create a release in github from this tag
104+
r = get_repo()
105+
r.create_git_release(
106+
tag_name,
107+
"Faabric {}".format(faabric_ver),
108+
get_release_body(),
109+
draft=True,
110+
)
111+
112+
print("You may now review the draft release in:")
113+
print("https://github.com/faasm/faabric/releases")
114+
115+
116+
@task
117+
def release_publish(ctx):
118+
"""
119+
Publish the draft release
120+
"""
121+
rel = get_release()
122+
rel.update_release(rel.title, rel.raw_data["body"], draft=False)

tasks/util/env.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from os import environ
2-
from os.path import dirname, realpath, join, expanduser
2+
from os.path import dirname, exists, realpath, join, expanduser
3+
import configparser
34

45
HOME_DIR = expanduser("~")
56
PROJ_ROOT = dirname(dirname(dirname(realpath(__file__))))
@@ -11,6 +12,8 @@
1112

1213
FAABRIC_INSTALL_PREFIX = join(_FAABRIC_BUILD_DIR, "install")
1314

15+
FAABRIC_CONFIG_FILE = join(PROJ_ROOT, "faabric.ini")
16+
1417

1518
def get_version():
1619
ver_file = join(PROJ_ROOT, "VERSION")
@@ -20,3 +23,16 @@ def get_version():
2023

2124
version = version.strip()
2225
return version
26+
27+
28+
def get_faabric_config():
29+
config = configparser.ConfigParser()
30+
if not exists(FAABRIC_CONFIG_FILE):
31+
print("Creating config file at {}".format(FAABRIC_CONFIG_FILE))
32+
33+
with open(FAABRIC_CONFIG_FILE, "w") as fh:
34+
config.write(fh)
35+
else:
36+
config.read(FAABRIC_CONFIG_FILE)
37+
38+
return config

0 commit comments

Comments
 (0)