feat: Add Semantic-Release workflow #3
Workflow file for this run
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This workflow check pull-requests commit message validity | |
name: "Check Commit message for Semantic validity" | |
on: | |
# this workflow triggers only on Pull Requests | |
pull_request: | |
types: [ opened, reopened, synchronize, edited ] | |
workflow_call: | |
inputs: | |
COMMITS_HISTORY: | |
description: 'Number of commits to consider, starting with most recent (e.g. 1 = only look at most recent).' | |
# 250 appears to be the limit of `gh api --paginate $COMMITS_URL` | |
default: 250 | |
required: false | |
type: number | |
CHECK_PR_TITLE_OR_ONE_COMMIT: | |
description: 'If there is one commit, only validate its commit message (and not the PR title). Else validate PR title only (and skip commit messages). This takes precedence over COMMITS_HISTORY.' | |
default: false | |
required: false | |
type: boolean | |
env: | |
PR_TITLE: ${{ github.event.pull_request.title }} | |
COMMITS_URL: ${{ github.event.pull_request.commits_url }} | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
SEMANTIC_PATTERN: |- | |
^(Merge .*branch '.+'( of .+)? into|Revert ".+"|(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\([^)]+\))?(\!)?: +[^ ]) | |
jobs: | |
checkCommits: | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
ref: ${{ github.event.pull_request.head.sha }} | |
# single bash script, the exit_code make the workflow failling if != 0 | |
- name: Fetch then Check PR Title and Commit Title(s) | |
shell: bash | |
run: | | |
# expected env vars: SEMANTIC_PATTERN, PR_TITLE, COMMITS_URL | |
exit_code=0 | |
# When running the check against its own repo, the inputs will be blank, so | |
# in this case set them. This will never happen when called as a reusable workflow. | |
commits_history=250 | |
if [[ "" != "${{ inputs.COMMITS_HISTORY }}" ]]; then | |
commits_history=${{ inputs.COMMITS_HISTORY }} | |
fi | |
tg_style=false | |
if [[ "" != "${{ inputs.CHECK_PR_TITLE_OR_ONE_COMMIT }}" ]]; then | |
tg_style=${{ inputs.CHECK_PR_TITLE_OR_ONE_COMMIT }} | |
fi | |
echo "COMMITS_HISTORY = $commits_history" | |
echo "CHECK_PR_TITLE_OR_ONE_COMMIT = $tg_style" | |
json=$( gh api --paginate $COMMITS_URL ) | |
commits_count=$(echo $json | jq --raw-output '.[] | [.sha, (.commit.message | split("\n") | first)] | join(" ")' | wc -l) | |
check_pr_title=true | |
if [[ $tg_style == true ]]; then | |
if (($commits_count == 1 )); then | |
check_pr_title=false | |
commits_to_check=1 | |
else | |
commits_to_check=0 | |
fi | |
else | |
commits_to_check=$commits_history | |
fi | |
echo "Check pr title: $check_pr_title" | |
echo "Total commits count for PR: $commits_count" | |
echo "Commits to validate: $commits_to_check" | |
if [[ $check_pr_title == true ]]; then | |
if [[ ! $PR_TITLE =~ $SEMANTIC_PATTERN ]]; then | |
echo ::error::PR title not semantic: "$PR_TITLE" | |
exit_code=1 | |
else | |
echo PR title OK: "$PR_TITLE" | |
fi | |
fi | |
if [[ 0 != $commits_to_check ]]; then | |
commits=$( echo $json | jq --raw-output '.[] | [.sha, (.commit.message | split("\n") | first)] | join(" ")' | tail -$commits_to_check ) | |
while read -r commit; do | |
commit_title=${commit:41} | |
commit_hash_short=${commit:0:7} | |
if [[ ! $commit_title =~ $SEMANTIC_PATTERN ]]; then | |
echo commit number ::error::$commit_hash_short is not semantic: '"$commit_title"' | |
exit_code=1 | |
else | |
echo $commit_hash_short OK: "$commit_title" | |
fi | |
done <<< $commits | |
fi | |
if [ $exit_code -ne 0 ]; then | |
echo | |
echo "This repository uses semantic commit messages" | |
echo "check out https://www.conventionalcommits.org/ for more information" | |
echo "and rewrite any rejected commit messages to pass CI - thanks!" | |
echo | |
fi | |
exit $exit_code |