semrel plugins are standalone executables. The core semrel binary discovers a plugin binary, starts it as a subprocess, and passes release context through environment variables.
- Use SemRels/plugin-template as the starting point for a new plugin.
- See the standalone plugin repositories under SemRels for reference implementations.
- Plugins can be written in any language that can read environment variables and exit with the correct status code.
A config entry such as:
plugins:
- uses: githubresolves to a binary named semrel-plugin-github.
semrel resolves plugin binaries in this order:
path:from.semrel.yaml~/.semrel/plugins/semrel-plugin-<name>semrel-plugin-<name>in$PATH
When a plugin is invoked, semrel:
- Creates a child process for the plugin binary
- Passes release context as environment variables
- Adds plugin-specific config from
args:asSEMREL_PLUGIN_<KEY>variables - Treats exit code
0as success and any non-zero exit code as failure
| Variable | Description |
|---|---|
SEMREL_VERSION |
New version string (e.g. 1.2.3) |
SEMREL_NEXT_VERSION |
Same as SEMREL_VERSION (alias) |
SEMREL_TAG_NAME |
Full tag name including prefix (e.g. v1.2.3) |
SEMREL_CURRENT_VERSION |
Previous version before this release |
SEMREL_BUMP |
Bump type: major, minor, or patch |
SEMREL_BRANCH |
Current branch name |
SEMREL_TAG_PREFIX |
Tag prefix configured in .semrel.yaml |
SEMREL_CHANGELOG |
Generated release changelog |
SEMREL_DRY_RUN |
true or false |
Each key in the plugin's args: block becomes SEMREL_PLUGIN_<KEY>.
plugins:
- uses: docker
args:
image: myorg/myapp
registry-url: ghcr.ioThe plugin process receives:
SEMREL_PLUGIN_IMAGE=myorg/myappSEMREL_PLUGIN_REGISTRY_URL=ghcr.io
Key normalization rules:
- Convert to uppercase
- Replace
-with_ - Replace
.with_ - Replace spaces with
_
Your plugin binary should:
- Read the required
SEMREL_*environment variables - Perform its work
- Exit with
0on success - Exit with a non-zero code on failure
A typical flow is:
read env vars -> validate config -> respect dry-run -> perform action -> exit 0
This shell-style pseudocode shows the contract:
#!/usr/bin/env bash
set -euo pipefail
version="${SEMREL_VERSION}"
tag="${SEMREL_TAG_NAME}"
dry_run="${SEMREL_DRY_RUN}"
image="${SEMREL_PLUGIN_IMAGE:-}"
if [ -z "$image" ]; then
echo "SEMREL_PLUGIN_IMAGE is required" >&2
exit 1
fi
if [ "$dry_run" = "true" ]; then
echo "[dry-run] would publish $image:$version"
exit 0
fi
# perform the real publish step here
echo "published $image:$tag"
exit 0Build your plugin binary locally and point path: at it while iterating:
plugins:
- path: ./bin/semrel-plugin-demo
args:
endpoint: https://staging.example.comYou can also install it into the standard location:
semrel plugin install demoor manually place the binary in:
- Unix/macOS:
~/.semrel/plugins/semrel-plugin-demo - Windows:
~/.semrel/plugins/semrel-plugin-demo.exeor.cmd
The standalone SemRels plugin repositories are the reference implementation for the current architecture, including providers, updaters, and hooks.
Examples:
- SemRels/provider-github
- SemRels/provider-gitlab
- SemRels/updater-npm
- SemRels/updater-docker
- SemRels/hook-slack
- SemRels/hook-jira
| Guideline | Why it matters |
|---|---|
Respect SEMREL_DRY_RUN |
Dry-run must not have side effects |
| Fail fast for missing required config | Misconfiguration should be obvious |
| Keep logs human-readable | Plugin output is streamed directly to the user |
Treat args: as plugin-owned config |
Keeps the core binary generic |
| Publish from a standalone repo | Lets plugins version and release independently |
- Architecture Overview — plugin execution flow and protocol
- Configuration Reference —
plugins:config section - SemRels/plugin-template — recommended starting point