Skip to content

droidsolutions/semantic-release-update-file

Repository files navigation

semantic-release-update-file

semantic-release plugin to help with updating files during release.

main semantic-release npm (scoped)

This plugin helps you to update files during a release which can be mainly helpful for updating Kubernetes manifests or using Semantic Release for projects with other languages than node such as Dotnet or Flutter.

Step Description
verifyConditions Verifies that the plugin is configured correctly and that the provided files are writable.
prepare Goes through each configured file and updates it.

Install

npm install -D @droidsolutions-oss/semantic-release-update-file

Usage

The plugin can be configured in the semantic-release configuration file:

{
  "release": {
    "plugins": [
      "@semantic-release/commit-analyzer",
      "@semantic-release/changelog",
      "@semantic-release/release-notes-generator",
      "@semantic-release/npm",
      [
        "@droidsolutions-oss/semantic-release-update-file",
        {
          "files": [
            {
              "path": ["k8s/prod/deployment.yaml"],
              "type": "k8s",
              "image": ["my.registry.com/some/image"],
              "branches": "main"
            },
            {
              "path": ["k8s/test/deployment.yaml"],
              "type": "k8s",
              "image": ["my.registry.com/some/image"],
              "branches": ["main", "develop"]
            },
            {
              "path": ["Directory.Build.props"],
              "type": "xml",
              "replacements": [{ "key": "Version", "value": "${nextRelease.version}" }]
            },
            {
              "path": ["Dockerfile"],
              "type": "containerfile",
              "label": "version"
            }
          ]
        }
      ],
      [
        "@semantic-release/git",
        {
          "assets": [
            "package.json",
            "package-lock.json",
            "k8s/prod/deployment.yaml",
            "k8s/test/deployment.yaml",
            "CHANGELOG.md",
            "Directory.Build.props",
            "Dockerfile"
          ],
          "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
        }
      ]
    ]
  }
}

With this example there will be 4 files updated:

  • In the file k8s/prod/deployment.yaml the version of the image my.registry.com/some/image will be updated to the one Semantic Release calculated as the new version. This file will only be updated when the name of branch in which the release runs is main.
  • The same applies to the file k8s/test/deployment.yaml but it will also be updated when the name of branch in which the release runs is develop.
  • In the XML file Directory.Build.props the value of the tag Version will be set to the version Semantic Release calculated as new.
  • In the Dockerfile the value of the label version will be set to the new version.

Also the git plugin config is updated to include the changed files in the commit (so they can be user later).

For each file that should be updated you can specify it in the files property of the plugin. The options are described below.

Configuration Options

path

This is a required field where you specify the path (relative to the root project directory) to the file that should be updated. This can be a string or an array of strings which would lead to all files beeing updated in the same way.

type

One of the supported file types. Currently these are k8s for yaml files, flutter for Dart pubspec.yaml files, xml for XML files like Dotnet project files and containerfile for Dockerfiles.

branches

A filter to allow to change files based on the branch the release is run on. For example you might want to deploy to test from a different branch as to prod. In this case, you could set the files config like this:

{
  "files": [
    {
      "path": ["k8s/prod/deployment.yaml"],
      "type": "k8s",
      "image": ["my.registry.com/some/image"],
      "branches": "main"
    },
    {
      "path": ["k8s/test/deployment.yaml"],
      "type": "k8s",
      "image": ["my.registry.com/some/image"],
      "branches": ["develop"]
    }
  ]
}

Branches can be a string or an array of branches, if you need to update the file in multiple branches (for example for pre-releases from alpha/beta/develop branches).

image

Only required if the type is k8s. Specifies the container image which version should be replaced. For example if you deployment.yaml looks like this:

apiVersion: apps/v1
kind: Deployment
spec:
  template:
    spec:
      containers:
        - image: my.registry.com/some/image:v2.8.2
          name: my-deployment

You should specify my.registry.com/some/image as image in the configuration. After the Semantic Release run finished the version of the image will be the new version.

This is escpecially helpful if you build and publish the container image as part of another Semantic Release plugin and you want to deploy it in a later step of the CI pipeline.

Note: The plugin will update all occurances of the image in the given yaml file.

exactMatch

Only required if the type is k8s. This plugin completely replaces the image tag with the new version. This can be problematic if you have a suffix on the tag like -alpine. For this the exactMatch option exists. If you specify exactMatch: true only the old version string is replaced with the new one.

For example if your last git tag is v1.0.0 the version (without leading v) is replaced with the new version. This way any tag suffixes should remain. For example my.registry.com/some/image:v1.0.0-alpine would become my.registry.com/some/image:v1.1.0-alpine.

Warniing:: For this to work, it is required that the version in the yaml file matches the one Semantic Release determined as the old version which is the Git tag unless it is the first release.

replacements

Only required if type is xml. You can specify an array of key/value pairs that should be updated in the XML file. With this you can for example update the version and commit tags in a C# project file to for NuGet packages. For example consider the following .csproj file:

<Project>
  <PropertyGroup>
    <VersionPrefix>1.0.0</VersionPrefix>
    <Authors>Stefan Ißmer</Authors>
    <Company>DroidSolutions GmbH</Company>
    <Description>Awesome description of awesome NuGet package.</Description>
    <RepositoryUrl>[email protected]</RepositoryUrl>
    <RepositoryBranch>main</RepositoryBranch>
    <RepositoryCommit>2e5a8557392548f0c7463a102efdb0add0ee5aab</RepositoryCommit>
  </PropertyGroup>
</Project>

With the following configuration Semantic Release would update the VersionPrefix and the RepositoryCommit fields:

{
  "files": [
    {
      "path": ["path/to/my.csproj"],
      "type": "xml",
      "replacements": [
        { "key": "VersionPrefix", "value": "${nextRelease.version}" },
        { "key": "RepositoryCommit", "value": "${nextRelease.gitHead}" }
      ]
    }
  ]
}

Now the VersionPrefix is up to date (and you could in a later Semantic Release step create a NuGet package with the version in the file) and the RepositoryCommit points to the commit that triggered the release.

The key must be a valid XML tag in the files you give. If it don't exist an error is logged but the execution of Semantic Release will continue. The value can be a fixed value as well as any object from the Semantic Release context which is extracted via a template function. This includes information about the last and the new release as well as Environment Variables you set yourself. For more information see the documentation.

label

When specifiying a container file (like Dockerfiles) you can specify a label inside the file that should be updated along during Semantic Release. For example if you add a label to your containerfile specifiying the application version you can update it with this plugin.

Development

To get started read the Contribution guidelines first, make sure you have the prerequisites installed and then follow the steps below to set up your environment.

Prerequisites

This project needs NodeJS installed on your machine.

Set up develop environment

  • clone this repo using git
  • run npm install to fetch all dependencies
  • run npx husky install to set up git hooks

Transpile

Since this project is written in TypeScript you will need to transpile it into JavaScript files. This can be done with the npm run build command.

Test

Tests are also written in TypeScript and use Mocha as test runner and the Chai assertion library. If you add new features please also add unit tests that make sure the feature is working properly.