github
ProviderPlugin for GitHub. Creates releases, uploads assets, and fetches commit history via the GitHub REST API.
Official plugins live in the GoSemantics/semrel-plugins repository (currently being set up).
github
ProviderPlugin for GitHub. Creates releases, uploads assets, and fetches commit history via the GitHub REST API.
conventional-commits
CommitAnalyzerPlugin that follows the Conventional Commits specification to determine the version bump.
markdown-changelog
ChangelogGeneratorPlugin that renders release notes as a Markdown CHANGELOG.md section.
go-mod-updater
FilesUpdaterPlugin that stamps the next version into Go source files via ldflags-compatible version variables.
A bare-bones commit analyser using go-plugin:
package main
import ( "context" "os" "strings"
hclog "github.com/hashicorp/go-hclog" goplugin "github.com/hashicorp/go-plugin" semrelv1 "github.com/GoSemantics/semrel-plugins/gen/v1")
type analyzer struct{ semrelv1.UnimplementedCommitAnalyzerPluginServer }
func (a *analyzer) AnalyzeCommits( _ context.Context, req *semrelv1.AnalyzeCommitsRequest,) (*semrelv1.AnalyzeCommitsResponse, error) { bump := semrelv1.BumpLevel_BUMP_LEVEL_NONE for _, c := range req.Ctx.Commits { switch { case strings.Contains(c.RawMessage, "BREAKING CHANGE"): return &semrelv1.AnalyzeCommitsResponse{Bump: semrelv1.BumpLevel_BUMP_LEVEL_MAJOR}, nil case strings.HasPrefix(c.RawMessage, "feat"): bump = semrelv1.BumpLevel_BUMP_LEVEL_MINOR case strings.HasPrefix(c.RawMessage, "fix") && bump == semrelv1.BumpLevel_BUMP_LEVEL_NONE: bump = semrelv1.BumpLevel_BUMP_LEVEL_PATCH } } return &semrelv1.AnalyzeCommitsResponse{Bump: bump}, nil}
func main() { // All logs MUST go to stderr. stdout is reserved for the go-plugin handshake. logger := hclog.New(&hclog.LoggerOptions{Name: "my-analyzer", Output: os.Stderr})
goplugin.Serve(&goplugin.ServeConfig{ HandshakeConfig: semrelv1.HandshakeConfig, Plugins: map[string]goplugin.Plugin{ "commit-analyzer": &semrelv1.CommitAnalyzerPlugin{Impl: &analyzer{}}, }, GRPCServer: goplugin.DefaultGRPCServer, Logger: logger, })}A Slack notification hook in Python. Note: Python plugins must use sys.stderr for all output — sys.stdout is reserved for the go-plugin handshake:
import sys, concurrent.futuresimport grpcfrom semrel_v1 import semantic_release_pb2, semantic_release_pb2_grpc
class SlackHook(semantic_release_pb2_grpc.HooksPluginServicer): def OnSuccess(self, request, context): webhook = request.ctx.config.get("webhook_url", "") if webhook: import urllib.request, json data = json.dumps({"text": f"Released {request.ctx.next_version}!"}) urllib.request.urlopen(webhook, data.encode()) return semantic_release_pb2.OnSuccessResponse()
def OnFail(self, request, context): return semantic_release_pb2.OnFailResponse()
if __name__ == "__main__": # go-plugin writes the handshake line to stdout automatically. # Our code must never write to stdout. print("starting", file=sys.stderr) # safe: goes to stderr server = grpc.server(concurrent.futures.ThreadPoolExecutor()) semantic_release_pb2_grpc.add_HooksPluginServicer_to_server(SlackHook(), server) # go-plugin manages the port/socket and writes the handshake line. # Use the go-plugin Python bridge (semrel-plugins/python) for the serve() call. server.wait_for_termination()Community-contributed plugins will be listed in the semrel registry once it launches. To have your plugin listed, open an issue or PR in the main repository.