Skip to content

Commit ab33378

Browse files
committed
chore: release action automatic versioning
After 1.0.0 this will become useful to automate versioning
1 parent 8e97ab8 commit ab33378

5 files changed

Lines changed: 186 additions & 62 deletions

File tree

.github/workflows/body.sh

Lines changed: 0 additions & 34 deletions
This file was deleted.

.github/workflows/release.yml

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,34 @@
11
name: Release
22

33
on:
4-
# push:
5-
# tags:
6-
# - '[0-9]+.[0-9]+.[0-9]+' # no pre-release suffix
7-
# - '[0-9]+.[0-9]+.[0-9]+-[0-9A-Za-z]+' # pre-release suffix, no ID
8-
# - '[0-9]+.[0-9]+.[0-9]+-[0-9A-Za-z]+.[0-9]+' # pre-release suffix
9-
# - '!0[0-9]+*' # MAJOR only absolute integer
10-
# - '!*.0[0-9]+*' # MINOR, PATCH and ID only absolute integer
11-
# - '!*-0[0-9]+' # NAME only absolute integer, no ID
12-
# - '!*-0[0-9]+.*' # NAME only absolute integer
13-
144
workflow_dispatch:
155
inputs:
166
version:
177
description: 'Version'
188
required: true
199
type: string
20-
title:
21-
description: 'Title'
22-
required: true
23-
type: string
2410
draft:
2511
description: 'Draft'
2612
required: true
2713
default: false
2814
type: boolean
15+
fix:
16+
description: 'Fix version'
17+
required: true
18+
default: false
19+
type: boolean
2920

3021
env:
31-
version: ${{ github.event.inputs.version }}
32-
title: ${{ github.event.inputs.title }}
22+
fix: ${{ github.event.inputs.fix }}
3323
regex: ((0|[1-9][0-9]*)\.){2}(0|[1-9][0-9]*)(-(alpha|beta|rc)(\.(0|[1-9][0-9]*))?)?
3424

3525
jobs:
3626

37-
release:
38-
name: Update the docs and release
27+
update:
28+
name: Update files
3929
runs-on: ubuntu-latest
4030

4131
steps:
42-
- name: Verify version
43-
id: verify_version
44-
run: grep -qE "^$regex$" <<< "$version"
45-
4632
- name: Checkout code
4733
id: checkout
4834
uses: actions/checkout@v3
@@ -57,9 +43,24 @@ jobs:
5743
id: fetch_tags
5844
run: git fetch --prune --unshallow --tags
5945

60-
- name: Generate release body
61-
id: make_body
62-
run: .github/workflows/body.sh >> $GITHUB_ENV
46+
- name: Get latest version release tag
47+
run: .github/workflows/release/latest.sh >> $GITHUB_ENV
48+
49+
- name: Generate body
50+
env:
51+
latest: ${{ env.latest }}
52+
run: .github/workflows/release/body.sh >> $GITHUB_ENV
53+
54+
- name: Verify version against regex
55+
run: |
56+
[[ "$version" =~ ^$regex$ ]] || exit 1
57+
58+
- name: Fix version
59+
env:
60+
old: ${{ env.latest }}
61+
new: ${{ env.version }}
62+
run: .github/workflows/release/semver.sh >> $GITHUB_ENV
63+
if: ${{ github.event.inputs.fix }}
6364

6465
- name: Update INSTALLATION.md
6566
id: update_installation_md
@@ -86,15 +87,14 @@ jobs:
8687
run: echo "commitish=$(git rev-parse @)" >> $GITHUB_ENV
8788

8889
- name: Release on GitHub
89-
id: create_release
9090
uses: actions/create-release@v1
9191
env:
9292
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
9393
with:
9494
tag_name: refs/tags/${{ env.version }}
9595
commitish: ${{ env.commitish }}
96-
release_name: ${{ env.title }}
97-
body: ${{ env.body }}
96+
release_name: ${{ env.version }}
97+
body_path: BODY.md
9898
# '-' appears only if the pre-release suffix is present
9999
prerelease: ${{ contains(env.version, '-') }}
100100
draft: ${{ github.event.inputs.draft }}

.github/workflows/release/body.sh

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
#!/bin/bash
2+
3+
group() {
4+
list=$(grep "^$2;" commits | cut -d';' -f2-)
5+
[[ -n "$list" ]] && cat <<EOF
6+
## $1
7+
8+
$list
9+
10+
EOF
11+
}
12+
13+
# types titles
14+
declare -A types=(
15+
[feat]=":rocket: New features"
16+
[fix]=":bug: Fixes"
17+
[docs]=":orange_book: Docs"
18+
[test]=":test_tube: Tests"
19+
[build]=":hammer: Build"
20+
[chore]=":broom: Chore"
21+
[style]=":nail_care: Style"
22+
[refactor]=":face_in_clouds: Refactoring"
23+
[revert]=":leftwards_arrow_with_hook: Reverted commits"
24+
)
25+
26+
level=4
27+
28+
# prepare commits list
29+
IFS=$'\n'
30+
for commit in $(git log "$latest"..@ --pretty=format:"[\`%h\`](../../commit/%H) %s"); do
31+
32+
url="${commit%% *}"
33+
title="${commit#* }"
34+
35+
# split type
36+
type="${title%%: *}"
37+
# ": " delimiter wasn't found?
38+
if [ ${#type} == ${#title} ]; then
39+
echo >&2 "Warning: type ': ' delimiter missing"
40+
continue
41+
fi
42+
43+
# split title
44+
title="${title#*: }"
45+
# empty title
46+
if [ ${#title} == 0 ]; then
47+
echo >&2 "Warning: empty title"
48+
continue
49+
fi
50+
51+
# if commit includes breaking changes
52+
[ "${type: -1}" == "!" ] && level=0
53+
type=${type/%\!/} # trim final !
54+
55+
# type is not valid?
56+
if [ ! -v 'types[$type]' ]; then
57+
echo >&2 "Warning: '$type' is not a valid type"
58+
# it's just a warning... no need to exit
59+
continue
60+
fi
61+
62+
# adjust level based on type "importance"
63+
[ "$type" == "feat" ] && [ $level -gt 1 ] && level=1
64+
[ "$type" == "fix" ] && [ $level -gt 2 ] && level=2
65+
66+
# `${title^}` makes first char capital case: "pretty"
67+
echo "$type; - $url - ${title^}"
68+
69+
done > commits
70+
71+
# is commits file empty?
72+
if [ ! -s commits ]; then
73+
echo >&2 "Error: no new commits since last tag (empty body)!"
74+
exit 1
75+
fi
76+
77+
# output all groups to BODY.md
78+
for type in "${!types[@]}"; do
79+
group "${types[$type]}" "$type"
80+
done > BODY.md
81+
82+
# github env
83+
echo "level=$level"
84+
85+
# clean-up
86+
rm commits
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/bin/bash
2+
3+
# get latest release tag with pre-releases
4+
# see: https://stackoverflow.com/a/52680984/9373031
5+
echo "latest=$(git -c 'versionsort.suffix=-' tag --sort=-v:refname \
6+
| grep -E -o -m 1 "$regex" | head -1)"
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#!/bin/bash
2+
3+
# You should call this script with the following environment variables set:
4+
#
5+
# regex="((0|[1-9][0-9]*)\.){2}(0|[1-9][0-9]*)(-(alpha|beta|rc)(\.(0|[1-9][0-9]*))?)?"
6+
# level= 0 | 1 | 2 | 3 | 4
7+
# old=<major>.<minor>.<patch>[-<name>[.<id>]]
8+
# new=<major>.<minor>.<patch>[-<name>[.<id>]]
9+
10+
[[ ! "$old" =~ ^$regex$ ]] && exit 1
11+
12+
IFS='.-' read -r -a old <<< "$old"
13+
14+
valid=0 # 0 means "not valid", other values are for "reason" debugging
15+
declare -a ver
16+
if [[ "$new" =~ ^$regex$ ]]; then
17+
18+
IFS='.-' read -r -a ver <<< "$new"
19+
for i in $(seq 0 $level); do
20+
if [ $i == 3 ]; then
21+
# same pre-release
22+
if [ "${ver[3]}" == "${old[3]}" ]; then
23+
continue
24+
# left pre-release stage
25+
elif [ ${#ver[3]} == 0 ]; then
26+
valid=1
27+
break
28+
# entered pre-release stage (ko because we know the first part is equal -> check for if!)
29+
elif [ ${#ver[3]} == 0 ]; then
30+
break
31+
# a "grater" pre-release: "a(alpha)" > "b(eta)" > "r(c)"?
32+
elif [[ "${ver[3]}" > "${old[3]}" ]]; then
33+
valid=2
34+
break
35+
fi
36+
elif [[ ${ver[$i]} -gt ${old[$i]} ]]; then
37+
valid=2
38+
break
39+
elif [[ ${ver[$i]} -lt ${old[$i]} ]]; then
40+
break
41+
fi
42+
done
43+
44+
fi
45+
46+
# if ver should should be generated
47+
if [ $valid == 0 ]; then
48+
ver=(${old[@]})
49+
if [[ $level == 4 ]]; then
50+
ver[$level]=$(( ${ver[$level]}+1 ))
51+
elif [[ $level == 3 ]]; then
52+
if [ "${ver[3]}" == "alpha" ]; then
53+
ver[3]="beta"
54+
elif [ "${ver[3]}" == "beta" ]; then
55+
ver[3]="rc"
56+
elif [ "${ver[3]}" == "rc" ]; then
57+
ver=(${ver[@]::3}) # leave pre-release stage
58+
ver[2]=$(( ${ver[2]}+1 ))
59+
fi
60+
else
61+
ver=(${ver[@]::3}) # leave pre-release stage
62+
ver[$level]=$(( ${ver[$level]}+1 ))
63+
fi
64+
fi
65+
66+
echo "version=${ver[0]}.${ver[1]}.${ver[2]}${ver[3]:+-${ver[3]}}${ver[4]:+.${ver[4]}}"

0 commit comments

Comments
 (0)