Plugin: hook-exec
Runs user-defined shell commands in any external plugin phase supported by SemRel: condition, generator, pre-tag, and release. Use it to call build scripts, custom validations, or deployment commands without writing a dedicated plugin.
Installation
Section titled “Installation”Binary
Section titled “Binary”semrel plugin install @semrel/hook-execsemrel plugin install downloads the binary to .semrel/plugins/ and updates .semrel.lock. Commit .semrel.lock to pin the version for your team.
Docker
Section titled “Docker”Pre-built, signed multi-platform images (linux/amd64, linux/arm64) are published on every release:
docker pull ghcr.io/semrels/hook-exec:latestVerify the image signature with cosign:
cosign verify ghcr.io/semrels/hook-exec:latest \ --certificate-identity-regexp 'https://github.com/SemRels/hook-exec/.github/workflows/release.yml.*' \ --certificate-oidc-issuer https://token.actions.githubusercontent.comConfiguration
Section titled “Configuration”version: 1plugins: - uses: @semrel/hook-exec phase: pre-tag args: cmd: ./scripts/build.sh timeout: 10m env: | BUILD_MODE: releaseSemRel maps every args value to a single environment variable, so structured values such as env must be passed as a YAML or JSON string.
Environment Variables
Section titled “Environment Variables”| Name | Required | Default | Description |
|---|---|---|---|
SEMREL_PLUGIN_CMD | no | — | Command to run in the configured phase. Required unless a lifecycle-keyed command is set. |
SEMREL_PLUGIN_SHELL | no | sh | Shell executable. Defaults to cmd on Windows. |
SEMREL_PLUGIN_CWD | no | repository root | Working directory of the child process. |
SEMREL_PLUGIN_ENV | no | — | YAML or JSON string map merged into the child environment. |
SEMREL_PLUGIN_TIMEOUT | no | 5m | Go duration such as 30s or 10m. |
SEMREL_PLUGIN_RUN_IN_DRY_RUN | no | false | Execute the command even when SEMREL_DRY_RUN=true. |
SEMREL_PLUGIN_PHASE | no | inferred | Explicit phase for lifecycle-keyed commands. |
Lifecycle-keyed commands
Section titled “Lifecycle-keyed commands”For compatibility with @semantic-release/exec terminology, these keys can replace cmd:
| Argument | SemRel phase | Behavior |
|---|---|---|
verifyConditionsCmd | condition | Gates the release. |
generateNotesCmd | generator | Stdout becomes SEMREL_CHANGELOG; diagnostics belong on stderr. |
verifyReleaseCmd | pre-tag | Runs before prepareCmd. |
prepareCmd | pre-tag | Prepares build output or generated files. |
publishCmd | release | Runs before successCmd. |
successCmd | release | Post-publish success action. |
Set phase when the configuration contains commands for more than one phase. If exactly one phase group is present, hook-exec infers it. SemRel has no external analyzer phase and does not invoke plugins after a failed pipeline, so analyzeCommitsCmd and failCmd are rejected with an explicit error instead of being silently ignored.
Release Context Variables
Section titled “Release Context Variables”SEMREL_VERSIONSEMREL_CURRENT_VERSIONSEMREL_TAG_NAMESEMREL_BRANCHSEMREL_BUMPSEMREL_CHANGELOGSEMREL_DRY_RUN
Commands also support standalone ${nextRelease.version}, ${lastRelease.version}, ${gitTag}, ${tag}, ${channel}, ${branch}, and ${date} placeholders. Inserted values are shell-quoted, so do not wrap a placeholder in additional quotes.
Behavior
Section titled “Behavior”POSIX shells are invoked with -c, PowerShell with -NoProfile -NonInteractive -Command, and cmd.exe with /D /S /C. Non-zero exit codes and timeouts fail the plugin; on Unix a timeout terminates the whole shell process group. When SEMREL_DRY_RUN=true, commands are logged and skipped unless runInDryRun is enabled.
Security
Section titled “Security”hook-exec intentionally executes trusted repository configuration with the permissions of the SemRel process. Review command changes as carefully as CI workflow changes.
- Never concatenate commit messages, changelog content, contributor data, or branch names into a command.
- Consume release context through quoted environment variables inside a script.
- Keep secrets out of
.semrel.yamland provide them through the CI environment. - Use a minimal shell, an explicit working directory, and a finite timeout.