# Semantic Versioning: Setting Up a Semantic Release Pipeline

Semantic Versioning is essential for managing releases in software development, ensuring that versions are clearly defined and reflect the nature of changes made. In this blog, we’ll explore how to set up a Semantic Release pipeline using GitHub Actions.

[https://github.com/muhammadhassanb111/semantic-release.git](https://github.com/muhammadhassanb111/semantic-release.git)

## 1\. Install Locally and Push to Git

Before setting up the CI/CD pipeline, it’s crucial to install Semantic Release locally. This allows you to manage dependencies and ensure that your `package.json` file is updated with the necessary packages. Use the following command to install Semantic Release and its plugins:

```plaintext
npm install semantic-release @semantic-release/git @semantic-release/github -D
```

Installing locally helps maintain a consistent environment across different development setups and simplifies version management.

## 2\. GitHub Actions Workflow

Next, we’ll configure the GitHub Actions workflow that will trigger Semantic Release. Here’s a sample configuration:

```plaintext
on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main
jobs:
  release:
    permissions:
      contents: write
      issues: write
      pull-requests: write
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
      
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 20
      
      - name: Install dependencies
        run: npm i
      
      - name: Run semantic release
        env:
          GITHUB_TOKEN: ${{ secrets.G_TOKEN }}
        run: npx semantic-release
```

### Adding the GitHub Token

To allow Semantic Release to publish releases and tags to your GitHub repository, you need to create a GitHub token. Follow these steps:

1. Go to your GitHub repository.
    
2. Navigate to **Settings** &gt; **Secrets and variables** &gt; **Actions**.
    
3. Click on **New repository secret**.
    
4. Name your secret `G_TOKEN` and paste your personal access token.
    

This token enables secure access for publishing without exposing your credentials in the code.

## 3\. Configuration for Semantic Release

Now, let’s define the configuration for Semantic Release. Create a `.releaserc.yml` file in your project root with the following content:

```plaintext
branches:
  - main
repositoryUrl: https://github.com/muhammadhassanb111/semantic-release.git
plugins:
  - '@semantic-release/commit-analyzer'
  - '@semantic-release/release-notes-generator'
  - - '@semantic-release/git'
    - assets:
        - 'dist/*.js'
        - 'dist/*.js.map'
      message: "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
  - '@semantic-release/github'
```

### Configuration File

Semantic Release’s options, mode, and plugins can be set via either:

* A `.releaserc` file, written in YAML or JSON, with optional extensions: `.yaml`, `.yml`, `.json`, `.js`, `.cjs`, `.mjs`.
    
* A `release.config.(js|cjs|.mjs)` file that exports an object.
    
* A `release` key in the project's `package.json` file.
    

Alternatively, some options can be set via CLI arguments. Here are examples:

* Via `release` key in the project's `package.json` file:
    

```plaintext
{
  "release": {
    "branches": ["master", "next"]
  }
}
```

* Via `.releaserc` file:
    

```plaintext
{
  "branches": ["master", "next"]
}
```

* Via `release.config.cjs` file:
    

```plaintext
/**
 * @type {import('semantic-release').GlobalConfig}
 */
module.exports = {
  branches: ["master", "next"],
};
```

* Via `release.config.mjs` file:
    

```plaintext
/**
 * @type {import('semantic-release').GlobalConfig}
 */
export default {
  branches: ["master", "next"],
};
```

* Via CLI argument:
    

```plaintext
$ semantic-release --branches next
```

## 4\. Commit Messages and Their Types

To leverage Semantic Release effectively, it’s crucial to use proper commit messages. Here’s a brief guide on the types of commits:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1721209796050/a71aec2a-b961-44ff-a693-0362f92c7dd9.png align="center")

* **fix**: A bug fix (e.g., `fix(pencil): stop graphite breaking when too much pressure applied` → Patch Release).
    
* **feat**: A new feature (e.g., `feat(pencil): add 'graphiteWidth' option` → Minor Release).
    
* **perf**: A performance improvement (e.g., `perf(pencil): remove graphiteWidth option` → Major Release).
    

### Important Note on Breaking Changes

For breaking changes, you must add the `BREAKING CHANGE:` footer in the commit message. This signals that the change may affect the functionality and compatibility of the software. For example:

```plaintext
perf(pencil): remove graphiteWidth option

BREAKING CHANGE: The graphiteWidth option has been removed. The default graphite width of 10mm is always used for performance reasons.
```

The `fix:` and `feat:` types can be used independently without requiring the `BREAKING CHANGE:` notice. However, any changes marked as breaking must follow the specified format to ensure proper versioning.
