feat(conventional_commits): Added conventional commit job

Migrated conventional commits from:
    url: https://gitlab.com/nofusscomputing/infrastructure/ansible-roles
    commit: 037774e1e44f8e1e065718f805688b8b2f64735f

updated logic so that it works on it's home repo and remote repo including private repositories.

Changes to be committed:
        new file:   conventional_commits/.gitlab-ci.yml
        new file:   conventional_commits/README.md
        new file:   conventional_commits/requirements.txt
        new file:   conventional_commits/scripts/commit.py
        new file:   conventional_commits/scripts/cz_junit.sh

issue #1
This commit is contained in:
2021-08-03 13:26:05 +09:30
parent bd08adf93f
commit 392a200fd4
5 changed files with 328 additions and 0 deletions

View File

@ -0,0 +1,73 @@
.conventional_commit:
variables:
DEFAULT_ROOT_DIR: './gitlab-ci'
image: python:3.6-slim
stage: validation
before_script:
- mkdir -p "$CI_PROJECT_DIR/artifacts/$CI_JOB_STAGE/$CI_JOB_NAME"
- mkdir -p "$CI_PROJECT_DIR/artifacts/$CI_JOB_STAGE/tests"
- if [ "0$MR_ACCESS_TOKEN" == "0" ]; then MR_ACCESS_TOKEN=$CI_JOB_TOKEN; fi
- echo "[DEBUG] MR_ACCESS_TOKEN[$MR_ACCESS_TOKEN]"
- if [ "0$JOB_ROOT_DIR" == "0" ]; then ROOT_DIR=$DEFAULT_ROOT_DIR; else ROOT_DIR=$JOB_ROOT_DIR ; fi
- echo "[DEBUG] ROOT_DIR[$ROOT_DIR]"
- if [ "0$MY_PROJECT_ID" == "0" ]; then PROJECT_ID=$CI_PROJECT_ID; else PROJECT_ID=$MY_PROJECT_ID ; fi
- echo "[DEBUG] PROJECT_ID[$PROJECT_ID]"
- export PYTHON_VERSION=`python -c 'import sys; version=sys.version_info[:3]; print("{0}.{1}.{2}".format(*version))'`
- apt update
- apt install --no-install-recommends -y git
- python3 -m venv env
- . env/bin/activate
- pip install --upgrade pip
- pip install -r $ROOT_DIR/conventional_commits/requirements.txt
- echo "[DEBUG] CI_PROJECT_ID[$CI_PROJECT_ID]"
- echo "[DEBUG] CI_COMMIT_BRANCH[$CI_COMMIT_BRANCH]"
- $ROOT_DIR/conventional_commits/scripts/commit.py --token "$MR_ACCESS_TOKEN" --project $PROJECT_ID --branch $CI_COMMIT_BRANCH --target-branch
- target_branch=$($ROOT_DIR/conventional_commits/scripts/commit.py --token "$MR_ACCESS_TOKEN" --project $PROJECT_ID --branch $CI_COMMIT_BRANCH --target-branch)
- echo "[DEBUG] Target Branch[$target_branch]"
- git clone --depth 150 -b $target_branch $CI_REPOSITORY_URL check
- cd check
- git remote rm origin
- git remote add origin $CI_REPOSITORY_URL
- git fetch --all
- git checkout --track origin/$CI_COMMIT_BRANCH
- git submodule update --init
- if [ -d "gitlab-ci" ]; then ls -la gitlab-ci; fi
- first_sha1=$(git log $target_branch..$CI_COMMIT_BRANCH --format=format:%H | tail -1)
- echo "[DEBUG] First Commit SHA[$first_sha1]"
- echo "[DEBUG] artifacts directory [$CI_PROJECT_DIR/artifacts/$CI_JOB_STAGE/$CI_JOB_NAME]"
after_script:
- ls -lR "$CI_PROJECT_DIR/artifacts/$CI_JOB_STAGE"
- cd ..
- rm -Rf check
artifacts:
expire_in: 3 days
when: always
paths:
- "$CI_PROJECT_DIR/artifacts/*"
reports:
junit:
- "$CI_PROJECT_DIR/artifacts/$CI_JOB_STAGE/tests/*.junit.xml"
rules:
- if: '$CI_COMMIT_BRANCH == "master"'
when: never
- if: '$CI_COMMIT_BRANCH'
when: always
- when: never
MR Title:
extends:
- .conventional_commit
script:
- cz_exit=0 && cz check --message "$($ROOT_DIR/conventional_commits/scripts/commit.py --token "$MR_ACCESS_TOKEN" --project $PROJECT_ID --title --branch $CI_COMMIT_BRANCH)" > "$CI_PROJECT_DIR/artifacts/$CI_JOB_STAGE/$CI_JOB_NAME/cz_output.log" 2>&1 || cz_exit=$?
- . $ROOT_DIR/conventional_commits/scripts/cz_junit.sh > "$CI_PROJECT_DIR/artifacts/$CI_JOB_STAGE/tests/$CI_JOB_NAME-cz.junit.xml"
Commit Messages:
extends:
- .conventional_commit
script:
- cz_exit=0 && cz check --rev-range $first_sha1..HEAD > "$CI_PROJECT_DIR/artifacts/$CI_JOB_STAGE/$CI_JOB_NAME/cz_output.log" 2>&1 || cz_exit=$?
- . $ROOT_DIR/conventional_commits/scripts/cz_junit.sh > "$CI_PROJECT_DIR/artifacts/$CI_JOB_STAGE/tests/$CI_JOB_NAME-cz.junit.xml"

View File

@ -0,0 +1,94 @@
# Conventional Commits User Manual
Commitizen is used to validate the format of commit messages. we use [Conventional Commit Messages](https://www.conventionalcommits.org/en/v1.0.0/) format for our validation jobs.
This repository may have two CI jobs to do with commitizen:
- **MR Title** *Checks the Merge Request Title*
- **Commit Messages** *Checks all commit messages*
These CI Jobs output a test report that can be viewed inside of the merge request and contain the error(s), if any.
To fix an error please refer to the titled sections below.
## MR Title
Ensure that the merge request title is in the [conventional message](https://www.conventionalcommits.org/en/v1.0.0/) format. NOTE: the title is case sensitive.
## Commit Messages
All commit messages that form part of your merge request must be in [conventional message](https://www.conventionalcommits.org/en/v1.0.0/) format.
To fix them go back and edit your commit messages.
### fixing commit messages (suggestion)
If only the last commit is the commit with an error just use `git commit --amend` and edit your commit message to be in the correct format and save. now push your changes.
You will require the following information if the commit message with the error is further down the commit tree:
- Commit message SHA1 of your first commit message to the branch `{original_commit}`
- Commit message SHA1 prior to your first commit `{source_commit}`
Run these commands once you have the information above.
``` bash
git format-patch {original_commit}..HEAD -o diff-patches
git reset {source_commit} --hard
```
Now, navigate to the `diff-patches` folder, open up the offending patch (commit) and edit the `subject` or message body as appropriate and save. Once all the edits have been done, re-apply the patches to your tree with:
``` bash
git am diff-patches/*.patch
```
Now push your changes upstream.
| :notebook_with_decorative_cover: Note |
|:-----:|
| *As you have changed the commit SHA1(s), when you next push your changes upstream, you must force push. `git push --force`* |
| :octagonal_sign: **WARNING** |
|:-----:|
| *Ensure that all of your commits were exported prior to reseting the branch and when re-applying, that all of your commits were applied correctly* |
# Conventional Commits Admin Manual Manual
This job checks commit messages on a branch and the merge request title for validity against the [conventional commit format](https://www.conventionalcommits.org/en/v1.0.0/)
This job provides the following badge:
- None
## Dependencies
- None
## your .gitlab-ci.yml changes
To use this job add the following to your `.gitlab-ci.yml` file
``` yaml
variables:
GIT_SUBMODULE_STRATEGY: recursive
MY_PROJECT_ID: "{yourproject id number}"
stages:
- validation
include:
- remote: https://gitlab.com/nofusscomputing/projects/gitlab-ci/-/raw/development/conventional_commits/.gitlab-ci.yml
```
## CI/CD Variables required
| var name | Description |
|:----:|:----|
| MR_ACCESS_TOKEN | *only required if you are accessing a private repository.* <br>This token is a user access token that as a minimum requires read-only access to the api to fetch the projects merg requests. |
## Job Workflow
## Artifacts
## License
To view the license for this folder and any sub-folders, refer [here](https://gitlab.com/nofusscomputing/projects/gitlab-ci)

View File

@ -0,0 +1,3 @@
python-gitlab
requests
commitizen

View File

@ -0,0 +1,100 @@
#!/usr/bin/env python3
#-*- coding: utf-8 -*-
#import gitlab
import os
import sys
import getopt
import json
import requests
get_first_commit = False
get_mr_title = False
get_target_branch = False
project_id = ''
try:
opts, args = getopt.getopt(sys.argv[1:],"hic:t:ti:p:b:o",["commit","token=", "title", "project=", "branch=", "target-branch"])
except getopt.GetoptError:
print('test.py [-c | --commit] [-t | --token {token}]')
sys.exit(2)
for opt, arg in opts:
#print('[DEBUG] {0} {1}'.format(opt, arg))
if opt == '-h':
print('[commit.py] -i <inputfile> -o <outputfile>')
sys.exit()
elif opt in ("-c", "--commit"):
get_first_commit = True
elif opt in ("-t", "--token"):
ci_job_token = arg
elif opt in ("-ti", "--title"):
get_mr_title = True
elif opt in ("-p", "--project"):
project_id = str(arg)
elif opt in ("-b", "--branch"):
git_branch = arg
elif opt in ("-o", "--target-branch"):
get_target_branch = True
# private token or personal token authentication
#gl = gitlab.Gitlab('https://gitlab.com', private_token=ci_job_token)
url = 'https://gitlab.com/api/v4/projects/' + project_id + '/merge_requests'
headers = {'PRIVATE-TOKEN': ci_job_token}
try:
if os.environ['CI_JOB_TOKEN'] == ci_job_token:
headers = {'JOB_TOKEN': os.environ['CI_JOB_TOKEN']}
except:
pass
#print('[DEBUG] headers[{0}]'.format(headers))
merge_requests = requests.get(url, headers=headers, data='')
merge_requests = merge_requests.json()
#print('\n\nmerge_requests=[-{0}-][]\n\n\n\n\n'.format(merge_requests))
#project_mrs = project.mergerequests.list()
#mrs = gl.mergerequests.list()
mr_title = ''
mr_first_commit = ''
target_branch = ''
for mr in merge_requests:
# print('\n\nMR=[-{0}-]'.format(mr))
if mr['source_branch'] == git_branch and str(mr['target_project_id']) == str(project_id) and str(mr['state']) == 'opened':
mr_title = mr['title']
mr_first_commit = mr['sha']
target_branch = mr['target_branch']
if get_target_branch:
print('{0}'.format(target_branch))
if get_first_commit:
print('{0}'.format(mr_first_commit))
if get_mr_title:
print('{0}'.format(mr_title))

View File

@ -0,0 +1,58 @@
#!/bin/bash
# to use ensure cz_exit=0 is set prior to the cz command so that if the command is successfull, this script works
# this script must be run with '. {script-name}' so that vars set in cli are available
cz_command=$(cat "$CI_PROJECT_DIR/artifacts/$CI_JOB_STAGE/$CI_JOB_NAME/cz_output.log")
if [ "f${cz_exit}" == "f" ]; then
echo "[DEBUG] environmental variable cz_exit must be set"
exit 255
fi
if [ "${cz_exit}" == "0" ]; then
error_count=0
system_err=''
cat <<EOF
<testsuite errors="0" name="Conventional Commits Messages Check" tests="0">
<testcase classname="Conventional Commits" file="CI/commitizen/README.md" name="Using Conventional Commits Message Format"/>
</testsuite>
EOF
else
error_count=1
system_err="ERROR: $cz_command"
cat <<EOF
<testsuites id="Conventional Commits Messages Check" name="CI Validation test" tests="1" errors="$error_count" time="0">
<testsuite id="conventional commit" name="testing" tests="1" failures="$error_count" time="0">
<testcase classname="Conventional Commits" file="CI/commitizen/README.md" line="0" name="Using Conventional Commits Message Format" time="0" timestamp="$(date '+%Y-%m-%d %H:%M:%S')">
<failure message="Conventional commits not used" type="validation">$cz_command
</failure>
<system-out>
<![CDATA[ $cz_command ]]>
</system-out>
<system-err>
<![CDATA[ $system_err ]]>
</system-err>
</testcase>
</testsuite>
</testsuites>
EOF
fi
#echo boo;
#echo "output:[$cz_command]"
#echo "[DEBUG] cz_exit[$cz_exit]"
exit $cz_exit