diff --git a/conventional_commits/.gitlab-ci.yml b/conventional_commits/.gitlab-ci.yml
new file mode 100644
index 0000000..972bd97
--- /dev/null
+++ b/conventional_commits/.gitlab-ci.yml
@@ -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"
diff --git a/conventional_commits/README.md b/conventional_commits/README.md
new file mode 100644
index 0000000..cfc2045
--- /dev/null
+++ b/conventional_commits/README.md
@@ -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.*
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)
diff --git a/conventional_commits/requirements.txt b/conventional_commits/requirements.txt
new file mode 100644
index 0000000..5f8ca6f
--- /dev/null
+++ b/conventional_commits/requirements.txt
@@ -0,0 +1,3 @@
+python-gitlab
+requests
+commitizen
diff --git a/conventional_commits/scripts/commit.py b/conventional_commits/scripts/commit.py
new file mode 100755
index 0000000..1379a5f
--- /dev/null
+++ b/conventional_commits/scripts/commit.py
@@ -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 -o ')
+ 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))
+
diff --git a/conventional_commits/scripts/cz_junit.sh b/conventional_commits/scripts/cz_junit.sh
new file mode 100755
index 0000000..0465fe2
--- /dev/null
+++ b/conventional_commits/scripts/cz_junit.sh
@@ -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
+
+else
+error_count=1
+system_err="ERROR: $cz_command"
+
+
+cat <
+
+
+
+ $cz_command
+
+
+
+
+
+
+
+
+
+
+
+EOF
+
+fi
+
+#echo boo;
+
+#echo "output:[$cz_command]"
+#echo "[DEBUG] cz_exit[$cz_exit]"
+
+
+
+
+exit $cz_exit