Semantic Release for React Projects with Github Actions

If you have a React project and want to automate the release process, you can use semantic-release to do that. This note will show you how to set up semantic-release with Github Actions for your React project which you won't publish to npm registry.

If you don't know what is Semantic Versioning (The core idea for semantic-release), you can check this page.

1. Install semantic-release

I use pnpm as my package manager, so I will install semantic-release with pnpm. You can use npm or yarn if you want.

1pnpm add -D semantic-release

You can also install some plugins.

1pnpm add -D @semantic-release/git @semantic-release/changelog

Note that some plugins are already included in semantic-release package, so you don't need to install them again. Check this page for more information.

2. Configure semantic-release

There are three ways to configure semantic-release: package.json, .releaserc and release.config.cjs. I prefer to use release.config.cjs. Create the following file in the root directory of your project.

release.config.cjs
1/**
2 * @type {import('semantic-release').GlobalConfig}
3 */
4module.exports = {
5 branches: ["main"],
6 plugins: [
7 "@semantic-release/commit-analyzer",
8 "@semantic-release/release-notes-generator",
9 "@semantic-release/changelog",
10 "@semantic-release/npm",
11 [
12 "@semantic-release/git",
13 {
14 assets: ["CHANGELOG.md", "package.json"],
15 message: "chore(release): ${nextRelease.version} [skip ci]",
16 },
17 ],
18 "@semantic-release/github",
19 ],
20};

Also because we don't want to publish to npm registry, we need to add the following line to package.json.

package.json
1{
2 "private": true
3}

3. Configure Github Actions

3.1 Generate GITHUB_TOKEN

We need to generate a Github token for semantic-release to use. I prefer to create a Fine-grained personal access tokens with permission only for the current repository.

You need to assign the following permissions to the token.

Github token permissions

Github token permissions

Then create a secret in your repository settings with the name RELEASE_GITHUB_TOKEN and the value of the token you just created.

3.2 Create Github Actions workflow

Create a file named .github/workflows/release.yml in the root directory of your project.

Your workflow file might not be the exactly same as mine. because you might use npm or yarn instead of pnpm or you need to add test steps to your workflow. Therefore, you only need to focus on the highlight lines and make sure you add them into your code.

.github/workflows/release.yml
1name: Release
2
3on:
4 push:
5 branches:
6 - main # Change this to your desired branch name
7
8jobs:
9 release:
10 permissions:
11 contents: write
12 pull-requests: write
13 issues: write
14 runs-on: ubuntu-latest
15 steps:
16 - name: Checkout repo
17 uses: actions/checkout@v3
18 - name: Setup Node
19 uses: actions/setup-node@v3
20 - name: Install pnpm
21 run: npm install -g pnpm
22 - name: Install dependencies with pnpm
23 run: pnpm i
24 - run: npm run build
25 env:
26 SKIP_ENV_VALIDATION: true
27 - name: Release
28 run: npx semantic-release
29 env:
30 GITHUB_TOKEN: ${{ secrets.RELEASE_GITHUB_TOKEN }}

4. Commit and push

Now you can commit and push your changes to the main branch. If you want to release a new version, you can create a new commit with a commit message like feat: add new feature and push it to the main branch. Then semantic-release will automatically create a new release for you.

5. Bypass rules for protected branches

It is very likely that you have protected your main branch. If you do that, then release will fail because the workflow cannot write CHANGELOG.md or package.json.

Then you need to add the following code to your workflow file.

.github/workflows/release.yml
1name: Release
2
3on:
4 push:
5 branches:
6 - main # Change this to your desired branch name
7
8jobs:
9 release:
10 permissions:
11 contents: write
12 pull-requests: write
13 issues: write
14 runs-on: ubuntu-latest
15 steps:
16 - name: Checkout repo
17 uses: actions/checkout@v3
18 with:
19 fetch-depth: 0
20 persist-credentials: false
21 - name: Setup Node
22 uses: actions/setup-node@v3
23 - name: Install pnpm
24 run: npm install -g pnpm
25 - name: Install dependencies with pnpm
26 run: pnpm i
27 - run: npm run build
28 env:
29 SKIP_ENV_VALIDATION: true
30 - name: Release
31 run: npx semantic-release
32 env:
33 GITHUB_TOKEN: ${{ secrets.RELEASE_GITHUB_TOKEN }}