Conventional Changelog support
Tags: devops, git, gitlab
Published: 2020-08-31 12:43:09

> Photo by [Daniel McCullough](https://unsplash.com/@d_mccullough) on [Unsplash](https://unsplash.com/)

# Introduction
This post takes place in a series aiming to show how to build an Angular application from scratch.

We will see how to scaffold an enterprise-scale angular application with all the assets needed to easily develop and maintain it.


> This post will show you how to add support for conventional changelog generation for [your application on Gitlab](https://dev.to/fairen/create-your-repository-48p7) and add it to [your CI tool chain](https://dev.to/fairen/setup-a-basic-ci-40m6).

Our goal will be to automate changelog generation on the master branch and generate a tag with the changelog updated : 
* **[Manual]** Merge `develop` to `master` (by Pull Request). 
* **[Manual]** Tag `master` with `prerelease-X.Y.Z` (on Gitlab or with git cli).
* **[Automatic]** CI triggered to update `CHANGELOG.md` and `package.json` + remove `prerelease-X.Y.Z` tag. 
* **[Automatic]** Push to `master` and add tag `X.Y.Z`, release ready.

# Git Workflow
<img src="https://dev-to-uploads.s3.amazonaws.com/i/zay232wfs4ayyf57gy9h.png" width="125px"> 

```Bash
git checkout develop
git pull
# Retrieve the last develop version

git checkout -b feature/changelog
# Feature Branch creation 
```

# Make your repository Comitizen friendly
<img src="https://dev-to-uploads.s3.amazonaws.com/i/yb26ylgja4gm56z1emh2.png" width="125px">


First, install the Commitizen cli tools:
```Bash
npm install commitizen --save --save-exact --save-dev 
```
Next, initialize your project to use the `cz-conventional-changelog` adapter by typing:
```Bash
commitizen init cz-conventional-changelog --save-dev --save-exact
```
The above command does three things for you.
* Installs the `cz-conventional-changelog` adapter npm module.
* Saves it to `package.json`'s dependencies or `devDependencies`.
* Adds the `config.commitizen` key to the root of your `package.json` as shown here:
```json
...
    "devDependencies": {
        ....
        "cz-conventional-changelog": "^3.1.0",
    }
...
    "config": {
        "commitizen": {
            "path": "./node_modules/cz-conventional-changelog"
        }
    }
... 
```
This just tells Commitizen which adapter we actually want our contributors to use when they try to commit to this repo.

# Use Comitizen
<img src="https://dev-to-uploads.s3.amazonaws.com/i/yb26ylgja4gm56z1emh2.png" width="125px">


Add comitizen script to your `package.json`.

```json
    "scripts": {
        ...
        "commit": "git-cz"
        ...
    },
```
Use npm `run commit` instead of git commit to enjoy! 

> When you're working in a Commitizen friendly repository, you'll be prompted to fill in any required fields and your commit messages will be formatted according to the standards you defined above.

# Use Conventional Changelog
<img src="https://dev-to-uploads.s3.amazonaws.com/i/yb26ylgja4gm56z1emh2.png" width="125px">


Install the Conventional Changelog CLI : 
```bash
npm install conventional-changelog-cli --save --save-exact --save-dev 
```
Update your package.json to include the followings script :
```json
"scripts": {
    ...
    "init-changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0",
    "version": "conventional-changelog -p angular -i CHANGELOG.md -s && git add CHANGELOG.md"
    ...
}
```
Initialise the Changelog :
```bash
npm run init-changelog
```

# Update your Node configuration
<img src="https://dev-to-uploads.s3.amazonaws.com/i/yb26ylgja4gm56z1emh2.png" width="125px">


With the new npm script `version`, we will add some logic to the npm versionlife-cyle. The `.npmrc` file helps us to define some variables used when `npm version` is called.  

Update your `.npmrc` file or create one with :
```
tag-version-prefix=""
message="chore(release): Version %s"
```

> For more informations about the npm versionlife-cycle, refer to :
https://docs.npmjs.com/cli/version

# Update your CI
<img src="https://dev-to-uploads.s3.amazonaws.com/i/x21k2lgakrz15jk58aer.png" width="125px"> 

## Generate your GitLab access token
Go to your Gitlab, [User Settings > Access Token](https://gitlab.com/profile/personal_access_tokens) and create a new token named `GIT_ACCESS_TOKEN` with the `api` scope checked. 
Your new personal access token will be prompt, save it :

![Token](https://dev-to-uploads.s3.amazonaws.com/i/a8jiw3o5d5i69adesd7p.png)

Now, go to your project Settings > CI/CD panel

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/v017o9tbobve8snivg2w.png)

Expand the **Variable** panel and click on **Add Variable**.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/fex9vqxee696nz4wgm9x.png)

Name the variable `GIT_ACCESS_TOKEN` and past the personal access token saved from before, make sure `protected` and `masked` are unchecked. 

> The variable `$GIT_ACCESS_TOKEN` can now be accessed from your CI jobs and enable credential to write/read your git repository.

## Update your CI jobs

Update your `.gitlab-ci.yml` to add a `publish-version` step.
This step will be triggered when [tagging](https://git-scm.com/book/en/v2/Git-Basics-Tagging) your code with `prerelease-X.Y.Z` tags (ie. `prerelease-1.0.0`). 

It will : 
* Retrieve the current `prerelease-X.Y.Z` tag.
* Update your application version (in `package.json`, `package-lock.json` and `npm-shrinkwrap.json`) to the `X.Y.Z` value.
* Run the `npm version` command and commit and tag in git. 
* Under the hood, run the `version` script defined above to update the `CHANGELOG.md` and add it to the commit.
* Remove the `prerelease-X.Y.Z` tag from your repository.
* Add the updated file to git and push the modifications to the `master` branch and tag it as `X.Y.Z`.

```yaml
image: node:latest

stages:
  - CodeQuality
  - Release
  
test:
  stage: CodeQuality
  script: 
    - npm ci
    - npm run ci:test

lint:
  stage: CodeQuality
  script:
    - npm ci
    - npm run ci:lint
    
publish-version:
  image: node:12.16.1
  stage: Release
  rules:
     - if: '$CI_COMMIT_TAG =~ /^prerelease-\d+.\d+.\d+/'
  before_script:
    - npm ci
    - npm config set unsafe-perm true
  script:
    - TAG_VERSION=`echo $CI_COMMIT_TAG | sed "s/.*prerelease-\([^ ]*\).*/\1/"`
    - git config --global user.name "$GITLAB_USER_NAME"
    - git config --global user.email "$GITLAB_USER_EMAIL"
    - git remote set-url origin "https://gitlab-ci-token:$GIT_ACCESS_TOKEN@$CI_SERVER_HOST/$CI_PROJECT_PATH.git"
    - git tag -d $CI_COMMIT_TAG
    - git push origin --delete $CI_COMMIT_TAG
    - npm version $TAG_VERSION
    - git push origin HEAD:master --tags
```

# Push your modifications.

<img src="https://dev-to-uploads.s3.amazonaws.com/i/zay232wfs4ayyf57gy9h.png" width="125px"> 

```Bash
git add package.json package-lock.json .gitlab-ci.yml CHANGELOG.md .npmrc

# Use the magic !!
npm run commit

git push -u origin feature/changelog
```

> Each time you tag your master branch with a tag `prerelease-X.Y.Z`, the CI will take care of updating your application version and generating the corresponding Changelog.