Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support conventional commits #31

Merged
merged 8 commits into from
Apr 23, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test-and-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ jobs:

- name: Check increment result
shell: bash
run: '[[ "$(date +%Y.%m)" == "$(echo "${{ steps.version-increment.outputs.VERSION }}" | cut -d "." -f 1-2)" ]]'
run: '[[ "$(date +%Y.%-m)" == "$(echo "${{ steps.version-increment.outputs.VERSION }}" | cut -d "." -f 1-2)" ]]'
ps-jay marked this conversation as resolved.
Show resolved Hide resolved

test-action-yml: # integration testing
needs:
Expand Down
1 change: 1 addition & 0 deletions .shellcheckrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
external-sources=true
13 changes: 10 additions & 3 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,14 @@ branding:

inputs:
scheme:
description: 'Versioning scheme - semver, or, calver (defaults to semver)'
description: |
Versioning scheme - semver, calver or conventional_commits (defaults to semver).

`conventional_commits` Will parse the last commit message to determine the increment type.
Supports the following increment types:
- patch (build, chore, ci, docs, fix, perf, refactor, revert, style, test)
- minor (feat)
- Major (any of the above types with an '!' or 'BREAKING CHANGE:' in commit body)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting ... it only parses the last commit 🤔

This means the consumer of this action have to ensure to remember to have to correct keyword in the merge commit (if using merge commits)

I wonder how other tooling does this? e.g. https://semantic-release.gitbook.io/semantic-release

I wonder if this action should parse every commit between "this" commit, and the "current version" tag commit ?

--

I realised the above, because I wanted to rewrite this description to be:

Suggested change
`conventional_commits` Will parse the last commit message to determine the increment type.
Supports the following increment types:
- patch (build, chore, ci, docs, fix, perf, refactor, revert, style, test)
- minor (feat)
- Major (any of the above types with an '!' or 'BREAKING CHANGE:' in commit body)
`conventional_commits` will parse the commit messages to determine the increment digit for a `semver` version (and implies `semver` scheme)
Supports the following increment types:
- patch (build, chore, ci, docs, fix, perf, refactor, revert, style, test)
- minor (feat)
- major (any of the above types with an '!' or 'BREAKING CHANGE:' in commit body)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah... guess this isn't as straight forward 😅

Either this would imply that merge commits would have to follow the same convention to correctly increment the version.

Or like you said, parse every commit since the last version and work out what increment type the version to jump to. That sounds more 'right' to me.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Harder to do in bash though 😞

required: false
default: 'semver'
pep440:
Expand Down Expand Up @@ -36,14 +43,14 @@ outputs:
description: 'Current normal version detected'
value: ${{ steps.version-lookup.outputs.CURRENT_VERSION }}
current-v-version:
description: 'Current normal version detected, prefixed with a `v` charatcter'
description: 'Current normal version detected, prefixed with a `v` character'
value: ${{ steps.version-lookup.outputs.CURRENT_V_VERSION }}
version:
description: 'Incremented version calculated'
value: ${{ steps.version-increment.outputs.VERSION }}
v-version:
description: 'Incremented version calculated, prefixed with a `v` charatcter'
value: ${{ steps.version-increment.outputs.V_VERSION }}
value: ${{ steps.version-increment.outputs.V_VERSION }}
major-version:
description: 'Major number of the incremented version'
value: ${{ steps.version-increment.outputs.MAJOR_VERSION }}
Expand Down
13 changes: 10 additions & 3 deletions shared.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,21 @@ pcre_master_ver='^(?P<major>0|[1-9]\d*)\.(?P<minor>0|[1-9]\d*)\.(?P<patch>0|[1-9
pcre_allow_vprefix="^v{0,1}${pcre_master_ver:1}"
pcre_old_calver='^(?P<major>0|[1-9]\d*)-0{0,1}(?P<minor>0|[0-9]\d*)-R(?P<patch>0|[1-9]\d*)$'

##==----------------------------------------------------------------------------
## Conventional commit regexes
## see: https://www.conventionalcommits.org/en/v1.0.0/

pcre_conventional_commit_patch='^(build|chore|ci|docs|fix|perf|refactor|revert|style|test)(\([a-zA-Z0-9-]+\))?:\s.*'
pcre_conventional_commit_minor='^(feat)(\([a-zA-Z0-9-]+\))?:\s.*'
pcre_conventional_commit_breaking='^(build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test)(\([a-zA-Z0-9-]+\))?!:.*|BREAKING CHANGE:'

##==----------------------------------------------------------------------------
## Input validation

input_errors='false'
scheme="${scheme:-semver}"
if [[ "${scheme}" != 'semver' && "${scheme}" != 'calver' ]] ; then
echo "🛑 Value of 'scheme' is not valid, choose from 'semver' or 'calver'" 1>&2
if [[ "${scheme}" != 'semver' && "${scheme}" != 'calver' && "${scheme}" != 'conventional_commits' ]] ; then
echo "🛑 Value of 'scheme' is not valid, choose from 'semver', 'calver' or 'conventional_commits" 1>&2
input_errors='true'
fi

Expand All @@ -40,7 +48,6 @@ if [[ "${use_api}" == 'true' ]] ; then
fi
fi


##==----------------------------------------------------------------------------
## MacOS compatibility - for local testing

Expand Down
128 changes: 128 additions & 0 deletions tests/test_version-increment.bats
Original file line number Diff line number Diff line change
Expand Up @@ -272,3 +272,131 @@ function init_repo {
[[ "$output" = *"PRE_RELEASE_LABEL=pre.${short_ref}"* ]] &&
[[ "$output" = *"VERSION=$(date +%Y.%-m.1)+pre.${short_ref}"* ]]
}

@test "increments the patch version after a fix commit (conventional commits)" {
init_repo

export current_version=1.2.3
export scheme="conventional_commits"

echo "fix: something" > fix.txt
git add fix.txt
git commit -m "fix: something"

run ../../version-increment.sh

print_run_info
[ "$status" -eq 0 ] &&
[[ "$output" = *"VERSION=1.2.4"* ]]
[[ "$output" != *"No conventional commit found"* ]]
}


@test "increments the patch version after a scoped fix commit (conventional commits)" {
init_repo

export current_version=1.2.3
export scheme="conventional_commits"

echo "fix: something" > fix.txt
git add fix.txt
git commit -m "fix(api): something"

run ../../version-increment.sh

print_run_info
[ "$status" -eq 0 ] &&
[[ "$output" = *"VERSION=1.2.4"* ]]
[[ "$output" != *"No conventional commit found"* ]]
}

@test "increments the major version after a breaking fix commit (conventional commits)" {
init_repo

export current_version=1.2.3
export scheme="conventional_commits"

echo "fix: breaking something" > fix.txt
git add fix.txt
git commit -m "fix!: something"

run ../../version-increment.sh

print_run_info
[ "$status" -eq 0 ] &&
[[ "$output" = *"VERSION=2.0.0"* ]]
[[ "$output" != *"No conventional commit found"* ]]
}

@test "increments the minor version after a feat commit (conventional commits)" {
init_repo

export current_version=1.2.3
export scheme="conventional_commits"

echo "new feature" > feat.txt
git add feat.txt
git commit -m "feat: something"

run ../../version-increment.sh

print_run_info
[ "$status" -eq 0 ] &&
[[ "$output" = *"VERSION=1.3.0"* ]]
[[ "$output" != *"No conventional commit found"* ]]
}

@test "increments the major version after a breaking feat commit (conventional commits)" {
init_repo

export current_version=1.2.3
export scheme="conventional_commits"

echo "breaking new feature" > feat.txt
git add feat.txt
git commit -m "feat!: something"

run ../../version-increment.sh

print_run_info
[ "$status" -eq 0 ] &&
[[ "$output" = *"VERSION=2.0.0"* ]]
[[ "$output" != *"No conventional commit found"* ]]
}

@test "increments the major version after a breaking change in the commit body (conventional commits)" {
init_repo

export current_version=1.2.3
export scheme="conventional_commits"

echo "breaking new fix" > feat.txt
git add feat.txt
git commit -m "Fix: something
BREAKING CHANGE: really important"

run ../../version-increment.sh

print_run_info
[ "$status" -eq 0 ] &&
[[ "$output" = *"VERSION=2.0.0"* ]]
[[ "$output" != *"No conventional commit found"* ]]
}

@test "increments the patch version by default if no conventional commits found and enabled (conventional commits)" {
init_repo

export current_version=1.2.3
export scheme="conventional_commits"

echo "some new change" > feat.txt
git add feat.txt
git commit -m "new change"

run ../../version-increment.sh

print_run_info
[ "$status" -eq 0 ] &&
[[ "$output" = *"VERSION=1.2.4"* ]]
[[ "$output" = *"No conventional commit found"* ]]
}
31 changes: 29 additions & 2 deletions version-increment.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ fi
default_branch='main'
# use release_branch if not empty
if [[ -n "${release_branch:-}" ]] ; then
default_branch="${release_branch}"
default_branch="${release_branch}"
elif [[ -z "${BATS_VERSION:-}" ]] ; then
# if we're _not_ testing, then _actually_ check the origin
if [[ "${use_api:-}" == 'true' ]] ; then
Expand All @@ -48,14 +48,41 @@ elif [[ -z "${BATS_VERSION:-}" ]] ; then
fi

current_ref="${GITHUB_REF:-}"
git_commit_sha=${GITHUB_SHA:-}

if [[ "${use_api:-}" == 'true' ]] ; then
# because we cannot use `rev-parse` with the API, we'll take a punt that 9 characters is enough for uniqueness
# shellcheck disable=SC2001
git_commit="$(echo "${GITHUB_SHA:0:9}" | sed 's/0*//')" # Also, trim leading zeros, because semver doesn't allow that in
else # the 'pre-release version' part, but we can't use the + char
git_commit="$(git rev-parse --short HEAD | sed 's/0*//')" # to make it 'build metadata' as that's not supported in K8s
fi # labels
git_commit_sha="$(git rev-parse --short HEAD)" # labels
fi

##==----------------------------------------------------------------------------
## Conventional commits
# If calver is set, raise a warning
if [[ "${scheme}" == 'conventional_commits' ]] ; then
# Get message from given commit
commit_message=$(git log -1 --pretty=format:%B "${git_commit_sha}")

# Check commit message header
found_match='false'
if [[ -n "$(echo "${commit_message}" | ${grep} -P "${pcre_conventional_commit_breaking}")" ]] ; then
increment='major'
found_match='true'
elif [[ -n "$(echo "${commit_message}" | ${grep} -P "${pcre_conventional_commit_minor}")" ]] ; then
increment='minor'
found_match='true'
elif [[ -n "$(echo "${commit_message}" | ${grep} -P "${pcre_conventional_commit_patch}")" ]] ; then
increment='patch'
found_match='true'
fi

if [[ "${found_match}" == 'false' ]] ; then
echo "⚠️ No conventional commit found, defaulting to ${increment} increment" 1>&2
fi
fi

##==----------------------------------------------------------------------------
## Version increment
Expand Down
2 changes: 1 addition & 1 deletion version-lookup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ if [[ -z "${current_version:-}" ]] ; then
echo "⚠️ No previous release version identified in git tags"
# brand new repo! (probably)
case "${scheme}" in
semver)
semver | conventional_commits)
current_version="0.0.0"
;;
calver)
Expand Down
Loading