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 7 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
18 changes: 17 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,22 @@ If the current latest normal version is not the current year and month, then the
year and month digits will be
set to the current year and month, and the release digit will be reset to 1.

### Conventional Commits (semver with smarts) 💡

If you choose the conventional commits scheme, the action will parse the last commit message _(usually the merge commit)_ to determine
the increment type for a `semver` version.

The following increment types by keyword are supported:
- patch: build, chore, ci, docs, fix, perf, refactor, revert, style, test
- minor: feat
- major: any of the above keywords followed by a '!' character, or 'BREAKING CHANGE:' in commit body

If none of the keywords are detected, then the increment specified by the `increment` input will be used (defaults to patch).

> [!TIP]
> You might like to _enforce_ conventional commits in the title of your pull requests to ensure that the merge commit has the correct
> information. Something like this action might be handy: https://github.com/marketplace/actions/conventional-commit-in-pull-requests

### Default branch vs. any other branch 🎋

**Default branch**
Expand Down Expand Up @@ -107,7 +123,7 @@ Examples:

| name | description | required | default |
| :--- | :--- | :--- | :--- |
| scheme | The versioning scheme in-use, either `semver` or `calver` | No | `semver` |
| scheme | The versioning scheme in-use, either `semver`, `calver` or `conventional_commits` | No | `semver` |
| pep440 | Set to `true` for PEP440 compatibility of _pre-release_ versions by making use of the build metadata segment of semver, which maps to local version identifier in PEP440 | No | `false` |
| increment | The digit to increment, either `major`, `minor` or `patch`, ignored if `scheme` == `calver` | No | `patch` |
| release_branch | Specify a non-default branch to use for the release tag (the one without -pre) | No | |
Expand Down
16 changes: 13 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 (e.g. the merge commit) to
determine the increment type, and supports the following increment types by keyword:
- patch (build, chore, ci, docs, fix, perf, refactor, revert, style, test)
- minor (feat)
- major (any of the above keywords followed by a '!' character, or 'BREAKING CHANGE:' in commit body)
required: false
default: 'semver'
pep440:
Expand All @@ -19,6 +26,9 @@ inputs:
description: |
Field to increment - major, minor, or, patch (defaults to patch)

If using the `conventional_commits` scheme, this is the default increment if the parsing of the merge commit fails to
find conventional commits information

Not applicable to `calver` scheme
required: false
default: 'patch'
Expand All @@ -36,14 +46,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"* ]]
}
30 changes: 28 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,40 @@ 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 [[ "${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