# Advanced example with Semantic versioning, CHangelog auto generation and git commit message syntax enforcement

This example is slightly advanced and includes tools that are still being explored. Use with caution!

### Dockerfile

```Dockerfile
FROM python:3.8

RUN useradd -u 1000 -M -d /tmp/jenkins jenkins && \
    mkdir -p /tmp/jenkins && \
    chown -R jenkins /tmp/jenkins && \
    ln -s /jenkins/.ssh /tmp/jenkins/.ssh

RUN apt-get update && apt-get install -y npm

RUN npm install -g semantic-release \
                   @semantic-release/commit-analyzer \
                   @semantic-release/release-notes-generator \
                   @semantic-release/changelog \
                   @semantic-release/git

RUN pip install commitizen
```

### .releaserc

```json
{
  "branches": ["stable", {"name": "master", "prerelease": true}],
  "plugins": [
    ["@semantic-release/commit-analyzer", {
      "releaseRules": [
        {"type": "docs", "release": "patch"},
        {"type": "style", "release": "patch"},
        {"scope": "no-release", "release": false}
      ],
      "parserOpts": {
        "noteKeywords": ["BREAKING"]
      }
    }],
    ["@semantic-release/release-notes-generator", {
      "preset": "angular",
      "parserOpts": {
        "noteKeywords": ["BREAKING"]
      },
      "writerOpts": {
        "commitsSort": ["subject", "scope"]
      }
    }],
    ["@semantic-release/changelog",
      {
        "changelogFile": "CHANGELOG.md"
      }
    ],
    ["@semantic-release/git", {
      "assets": ["CHANGELOG.md"],
      "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
    }]
  ]
}
```

### .cz.toml

```toml
[tool.commitizen]
name = "cz_customize"

[tool.commitizen.customize]
message_template = "{{change_type}}{% if scope %}({{scope}}){% endif %}: {{message}}{% if ticket_no %} ({{ticket_no}}){% endif %}"
example = "feature(API): Adding a status endpoint for monitoring and service discovery (MDT-3495)"
schema = "<type>: <body>"
schema_pattern = "^(BREAKING|fix|feat|docs|style|refactor|perf|test|build|ci|chore)(\\(\\w+\\))?: [\\w -.]+(\\((MDT|OP)-[0-9]+\\))?(\\[skip ci\\](.|\\n)*)?$"

[[tool.commitizen.customize.questions]]
type = "list"
name = "change_type"
choices = [
    {value = "fix", name = "fix: A bug fix. Correlates with PATCH in SemVer"},
    {value = "feat", name = "feat: A new feature. Correlates with MINOR in SemVer"},
    {value = "docs", name = "docs: Documentation only changes"},
    {value = "style", name = "style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)"},
    {value = "refactor", name = "refactor: A code change that neither fixes a bug nor adds a feature"},
    {value = "chore", name = "chore: updating Makefile receipe or NPM tasks etc; no production related code change"},
    {value = "perf", name = "perf: A code change that improves performance"},
    {value = "test", name = "test: Adding missing or correcting existing tests"},
    {value = "build", name = "build: Changes that affect the build system or external dependencies (example scopes: pip, docker, npm)"},
    {value = "ci", name = "ci: Changes to our CI configuration files and scripts (example scopes: Jenkins, Docker)"},
    {value = "BREAKING", name = "BREAKING: A major change."}]
message = "Select the type of change you are committing"

[[tool.commitizen.customize.questions]]
type = "input"
name = "message"
message = "Commit subject"

[[tool.commitizen.customize.questions]]
type = "input"
name = "scope"
message = "Scope, i.e: API (Keep empty to make global)"

[[tool.commitizen.customize.questions]]
type = "input"
name = "ticket_no"
message = "Ticket number i.e: MDT-1234, OP-321 (Keep empty if no ticket)"

```

### Makefile

```Makefile
.PHONY: check-git release

check-git:
	cz check --rev-range HEAD@{~100}

release:
	semantic-release
```

### Jenkinsfile

```groovy
#!/env/bin/env groovy

@Library("m2aJenkins") _

def builder = null
def suffix = "${env.BRANCH_NAME}".replaceAll(/[^a-zA-Z0-9-]/,"-").toLowerCase()

def isNoCICommit = false

pipeline {
    agent any

    triggers {
        bitbucketPush()
    }

    options {
        disableConcurrentBuilds()
        ansiColor('xterm')
    }

    environment {
        VERSION = "${artifacts.get_semantic_version()}~${currentBuild.number}~${GIT_COMMIT[0..7]}"
    }

    stages {
        stage("Prepare") {
            steps {
                script {
                    utils.build_notify(currentBuild, 'prepare', "Prepare"){
                        currentBuild.displayName = VERSION
                        builder = docker.build("m2a-jenkins-snippet:${suffix}")
                        isNoCICommit = sh(script: "git log --format=format:%s -1", returnStdout: true).trim() ==~ /.+\[skip ci\]$/
                    }
                }
            }
        }
        stage("Check") {
            steps {
                script {
                    builder.inside {
                        utilsLib.build_notify(currentBuild, "checkcommit", "Check commit"){
                            sh "make check-git"
                        }
                    }
                }
            }
        }
        stage("Release") {
            when {
                allOf {
                    anyOf { branch 'master'; branch 'stable' }
                    expression { return !isNoCICommit }
                }
            }
            steps {
                script {
                    builder.inside {
                        utilsLib.build_notify(currentBuild, "release", "Release"){
                            sshagent(['63351679-e80c-4fb8-8ca0-17d764f863d0']) {
                                sh "make release"
                                currentBuild.displayName = "${artifact.get_semantic_version()} - ${currentBuild.number} - ${GIT_COMMIT[0..7]}"
                            }
                            return "Version ${artifact.get_semantic_version()} has been released"
                        }
                    }
                }
            }
        }
    }

    post {
        cleanup {
            cleanWs()
        }
    }
}
```