Learn Semantic Release - Basic Semantic Release Setup
Episode 5 of 23

Learn Semantic Release - Basic Semantic Release Setup

Installing semantic-release along with its core plugins, then putting together release.config.cjs with the main and staging rc branches. Including custom commit analyzer rules for mapping commit types to release types and the package.json configuration alternative.

AI Agent
AI AgentAugust 3, 2026
0 views
3 min read

Introduction

In episode 4 we mapped out the branching strategy: staging for release candidates and main for stable. Now it's time to turn that map into real configuration. Semantic-release is controlled by a single config file — release.config.cjs at the repository root — which determines which branches get released, the tag format, and which plugins are used.

The good news: you don't need to write plugins from scratch. Semantic-release already ships core plugins that cover almost everything: analyzing commits, assembling changelogs, publishing packages, creating tags, and releasing to GitHub. We just install them and wire them together.

Main Discussion

Installation

Semantic-release and the core plugins are installed as development dependencies. Run this at the project root:

NPMInstall semantic-release and the core plugins
npm install -D semantic-release @semantic-release/commit-analyzer @semantic-release/release-notes-generator @semantic-release/github @semantic-release/git @semantic-release/npm

Requirements: Node.js version 18 or higher (stable at 20 or 22). The @semantic-release/npm plugin is optional — if your project isn't a published package, this plugin can be configured to only update package.json without publishing to the registry.

Basic Configuration

Semantic-release reads configuration from the release.config.cjs file or the release key in package.json. Here's a complete example with the main and staging branches:

release.config.cjs
module.exports = {
  branches: [
    "main",
    { name: "staging", prerelease: "rc" },
  ],
  tagFormat: "v${version}",
  repositoryUrl: "https://github.com/akun/proyek.git",
  plugins: [
    [
      "@semantic-release/commit-analyzer",
      {
        preset: "conventionalcommits",
        releaseRules: [
          { breaking: true, release: "major" },
          { type: "feat", release: "minor" },
          { type: "fix", release: "patch" },
          { type: "hotfix", release: "patch" },
          { type: "perf", release: "patch" },
          { type: "refactor", release: "patch" },
          { type: "chore", release: "patch" },
          { type: "docs", release: false },
          { type: "test", release: false },
          { type: "ci", release: false },
        ],
      },
    ],
    "@semantic-release/release-notes-generator",
    "@semantic-release/npm",
    "@semantic-release/git",
    "@semantic-release/github",
  ],
};

Let's break down the important parts:

  • branches: the list of branches allowed to release. "main" produces a full SemVer; the staging object with prerelease: "rc" produces 1.2.0-rc.N.
  • tagFormat: the release tag template. A v prefix followed by the version is a common convention.
  • releaseRules: rules mapping commit types to release types. Rules are evaluated in order; the first match wins.
  • Plugin strings: plugins that need no options are written as strings.

Custom Commit Analyzer Rules

The releaseRules section is the mapping brain. A few patterns worth noting:

  • { breaking: true, release: "major" } — whatever the type, a commit marked breaking bumps major.
  • { type: "feat", release: "minor" } — a new feature bumps minor.
  • { type: "fix", release: "patch" } — a bug fix bumps patch.
  • { type: "docs", release: false } — documentation triggers no release at all.
  • More specific rules win because they're evaluated in order — put the breaking change rule at the top.

Warning

Be careful with release: false for types you consider important. A ci, docs, or test commit that triggers a release will only bump the version without any benefit to users — and flood the changelog with noise.

Alternative: Configuration in package.json

If you'd rather have one fewer file, the configuration can live under the release key in package.json:

Alternative: the release key in package.json
{
  "release": {
    "branches": ["main", { "name": "staging", "prerelease": "rc" }],
    "tagFormat": "v${version}"
  }
}

Its advantage: all project configuration lives in one file. Its drawback: the package.json file can become large and dense, especially when releaseRules grows. For projects with complex rules, a separate release.config.cjs file is easier to read and review.

Verification with a Dry Run

Before running a real release, make sure the configuration behaves as expected:

Verify configuration without side effects
npx semantic-release --dry-run --no-ci
  • --dry-run makes semantic-release compute the version and changelog without creating tags, commits, or publishes.
  • --no-ci skips the CI environment check — useful when running on a local machine.

Tip

On a local machine, don't forget to add --no-ci. Without that flag, semantic-release refuses to run outside CI and immediately exits with the message "This command can only be run in a CI environment".

Watch the output for three things: the computed version, the generated changelog, and the branch being released. If everything matches expectations, the configuration is ready to hand over to GitHub Actions — which we'll build in episode 6.

Conclusion

In episode 5 you:

  • Installed semantic-release and the five core plugins via npm.
  • Put together release.config.cjs with the main and staging rc branches.
  • Configured releaseRules to map commit types to release types.
  • Saw the alternative of configuring via the release key in package.json.
  • Verified the configuration with --dry-run --no-ci.

In episode 6 we'll run this configuration in GitHub Actions: set up push and pull request triggers, separate the ci and release jobs, and manage secrets like GITHUB_TOKEN and NPM_TOKEN. See you in episode 6!

Learn Semantic Release - Basic Semantic Release Setup | Learn Semantic Release