# 🔮 Projects - Commit Semantics

<p align="center">
  <a href="https://www.npmjs.com/package/@crystal-ball/commit-semantics">
    <img src="https://img.shields.io/npm/v/@crystal-ball/commit-semantics.svg?style=flat-square" alt="NPM">
  </a>
  <a href="https://github.com/crystal-ball/commit-semantics/actions?workflow=CI%2FCD">
    <img src="https://github.com/crystal-ball/commit-semantics/workflows/CI%2FCD/badge.svg" alt="Build status" />
  </a>
  <a href="https://renovatebot.com/" target="_blank" rel="noopener noreferrer">
    <img src="https://img.shields.io/badge/Renovate-enabled-32c3c2.svg" alt="Renvoate" />
  </a>
  <a href="https://github.com/crystal-ball/commit-semantics#zenhub" target="_blank" rel="noopener noreferrer">
    <img src="https://img.shields.io/badge/shipping_faster_with-ZenHub-5e60ba.svg?style=flat-square" alt="ZenHub" />
  </a>
  <a href="https://prettier.io/" target="_blank" rel="noopener noreferrer">
    <img src="https://img.shields.io/badge/styled_with-prettier-ff69b4.svg" alt="Prettier">
  </a>
  <a href="https://semantic-release.gitbook.io" target="_blank" rel="noopener noreferrer">
    <img src="https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic_release-e10079.svg" alt="Semantic Release">
  </a>
  <br />
  <a href="https://github.com/crystal-ball" target="_blank" rel="noopener noreferrer">
    <img
      src="https://img.shields.io/badge/%F0%9F%94%AE%E2%9C%A8-contains_magic-D831D7.svg"
      alt="Contains magic"
    />
  </a>
  <a href="https://github.com/crystal-ball/crystal-ball.github.io" target="_blank" rel="noopener noreferrer">
    <img
      src="https://img.shields.io/badge/%F0%9F%92%96%F0%9F%8C%88-full_of_love-F5499E.svg"
      alt="Full of love"
    />
  </a>
</p>

<p align="center">
  <em>Fully automated commit and release workflows with Commitizen and Semantic Release</em>
</p>

This package is a batteries included manager for setting up standardized commit
messages with [Commitizen][] and automated CI/CD releases with [Semantic
Release].

- Standardized commit messages are constructed using an interactive prompt with
  options for long descriptions, emojis, breaking change notes and release
  notes.
- Fully automated releases include package version and changelog updates, npm
  publishing, and Github release comments and labels.

---

## ⚙️ Setup

_1. Install_

```sh
npm i -D @crystal-ball/commit-semantics husky
```

_2. Configure `package.json`_

```json
{
  "config": {
    "commitizen": {
      "path": "@crystal-ball/commitizen-adapter"
    }
  },
  "husky": {
    "hooks": {
      "prepare-commit-msg": "exec < /dev/tty && git cz --hook"
    }
  },
  "release": {
    "extends": ["@crystal-ball/semantic-release-base"]
  }
}
```

_3. Configure `.github/workflows/ci-cd.yml`_

```yml
# Release with Semantic after tests pass on master
jobs:
  ci-cd:
    runs-on: ubuntu-latest
    steps:
      - name: Release
        if: success() && github.ref == 'refs/heads/master'
        run: npx semantic-release
        env:
          GH_TOKEN: ${{ secrets.SEMANTIC_GH_TOKEN }}
          NPM_TOKEN: ${{ secrets.SEMANTIC_NPM_TOKEN }}
```

This configuration will run `semantic-release` on any change to the master
branch. Commit types of `New`, `Update` and `Fix`, or any commit containing a
`BREAKING CHANGES` footer will trigger a release.

_4. Configure Secret_

`SEMANTIC_GH_TOKEN` and `SEMANTIC_NPM_TOKEN` access tokens for npm and Github
should be added to the secrets in the repo settings.

![Navigate to Secrets in settings and add the release tokens](./assets/configure-secrets.png)

## 🔖 Commit standards

Fully automated releases are only possible by following a standard commit
message format that can be parsed when the release job is run. The ESLint format
is used and must follow the pattern:

```
<tag>: <message>
```

The Husky `prepare-commit-msg` hook will execute the Commitizen prompt on each
commit and using the prompts will ensure the commit is valid.

> ℹ️ It is possible to skip the interactive prompts with `ctrl+c` as well as
> changing the commit after construction, but neither is recommended.

_Configuration of the commitizen adapter is managed in the
[`@crystal-ball/commitizen-adapter`][] package._

## 🚀 Release tasks

On change to master Semantic Release is run and will manage:

1. Analyze commits made since the last release to determine if a release should
   occur and what the version should be.
2. Parse commits to generate a set of formatted release notes.
3. Append release notes to the top of the project Changelog.
4. Push a release commit and tag to Github
5. Publish the release to NPM
6. Publish a Github release and add comments and labels to all issues and PRs
   included in the release.

## 🔋 Included packages

- [`commitizen`][commitizen]
- [`@crystal-ball/commitizen-adapter`][]
- [`semantic-release`][semantic release]
- [`@crystal-ball/semantic-release-base`][]
- [`@semantic-release/commit-analyzer`][]
- [`@semantic-release/release-notes-generator`][]
- [`@semantic-release/changelog`][]
- [`@semantic-release/git`][]
- [`@semantic-release/npm`][]
- [`@semantic-release/github`][]

<!-- Links -->

<!-- prettier-ignore-start -->
[commitizen]:https://commitizen.github.io/cz-cli/
[semantic release]:https://semantic-release.gitbook.io/semantic-release/
[`@crystal-ball/commitizen-adapter`]:https://github.com/crystal-ball/commitizen-adapter
[`@crystal-ball/semantic-release-base`]:https://github.com/crystal-ball/semantic-release-base
[`@semantic-release/commit-analyzer`]:https://github.com/semantic-release/commit-analyzer
[`@semantic-release/release-notes-generator`]:https://github.com/semantic-release/release-notes-generator
[`@semantic-release/changelog`]: https://github.com/semantic-release/changelog
[`@semantic-release/git`]: https://github.com/semantic-release/git
[`@semantic-release/github`]: https://github.com/semantic-release/github
[`@semantic-release/npm`]: https://github.com/semantic-release/npm
<!-- prettier-ignore-end -->
