Webhook icon
Schedule icon
WorkingDirectory icon
Commands icon
Docker icon
Script icon
Process icon
If icon
Loop icon
Create icon
SlackIncomingWebhook icon

Lint Commit Messages Against Conventional Commits Before Every Release

Lint the last ten commit subjects against Conventional Commits on push, open a GitHub issue with every violation, alert Slack, and expose a versioning verdict.

Categories
Infrastructure

Diagram unavailable

We could not build the topology for this blueprint. The flow itself is valid, use the YAML on the left to run it.

Release tooling that derives versions from history (semantic-release, changesets, commit-and-tag-version) only works when every message follows the Conventional Commits shape. A single subject like fixed stuff silently blocks a release or makes the next tag a patch instead of a feature. This flow checks the last ten subjects on every push, branches on the result, and turns any violation into an issue, a Slack ping and a rewrite list that can be handed back to the author.

How it works

  1. on_push (io.kestra.plugin.core.trigger.Webhook) exposes a keyed URL for your push hook or CI to POST to. daily_recheck (io.kestra.plugin.core.trigger.Schedule) sits disabled as a safety net that would recheck the last day of history each morning.
  2. workspace (io.kestra.plugin.core.flow.WorkingDirectory) opens one shared filesystem, so commits.txt written by the container is visible to the python step and report.txt accumulates across tasks.
  3. collect_commits (io.kestra.plugin.scripts.shell.Commands on the io.kestra.plugin.scripts.runner.docker.Docker runner, image alpine/git:2.47.2) runs git log -n 10 --format='%H %s' best effort with || true, then falls back to a ten subject fixture of six compliant and four non-compliant messages when no checkout is present.
  4. validate_commits (io.kestra.plugin.scripts.python.Script) matches each subject against ^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\([a-z0-9 .-]+\))?!?: .{1,80}$, diagnoses why a subject failed, detects breaking changes through the ! marker or a BREAKING CHANGE mention, and prints one ::{"outputs": ...}:: line carrying violations, valid_count and breaking.
  5. check_violations (io.kestra.plugin.core.flow.If) branches on the violation count.
  6. Inside the branch, write_remediation_report (io.kestra.plugin.core.flow.Loop) appends one line per violation to report.txt, open_violation_issue (io.kestra.plugin.github.issues.Create) files the full list with labels, and alert_slack (io.kestra.plugin.slack.notifications.SlackIncomingWebhook) posts the count. The clean path writes an all-clear line through record_compliant.
  7. The errors block pings Slack when the run itself breaks, because a failed lint looks a lot like a clean one from the outside.

What you get

  • A gate that keeps non-conventional subjects out of the release train instead of discovering them at tag time.
  • Every violation listed with its sha, its subject and the exact reason it failed, filed as a GitHub issue and mirrored into report.txt.
  • A breaking change flag, so a ! or BREAKING CHANGE subject is visible before the next version is cut.
  • Four execution outputs (verdict, violation_count, violations, breaking) that downstream flows or dashboards can read directly.
  • An execution history that doubles as an audit trail of when the repository was last clean.

Who it's for

  • Teams running semantic-release or changesets that need history to stay machine readable.
  • Platform engineers who want the convention checked centrally instead of trusting a client side hook.
  • Maintainers of busy repositories where review pressure lets fixed stuff slip into main.

Why orchestrate this with Kestra

A client side commit hook only protects the machines of people who installed it, and a CI job that simply fails gives the author a red build and nothing else. Kestra supplies the parts that make the check actionable, a webhook for the push event, a containerized git step so the tool version lives in the flow, a branch that separates escalation from the all clear, a loop that produces a per commit remediation file, routing into GitHub and Slack from one declarative file, and an execution record with the verdict as a first class output.

Prerequisites

  • A worker with Docker access for the alpine/git collector and Python 3 available for the validator.
  • A GitHub token that can create issues in the target repository (classic repo scope, or fine grained Issues: write).
  • A Slack incoming webhook for violation and failure alerts.
  • Push events routed to the webhook URL, or the disabled schedule switched on for a daily sweep.

Secrets

  • COMMIT_LINT_WEBHOOK_KEY: key segment guarding the webhook URL, so only your CI can trigger a lint.
  • GITHUB_TOKEN: token used to open the violation issue.
  • SLACK_WEBHOOK_URL: Slack incoming webhook used for violation alerts and failures.

Quick start

  1. Add the three secrets to your Kestra namespace.
  2. Leave repository and branch at their defaults, or point them at the repository you want gated.
  3. Point your push webhook at /api/v1/{tenant}/executions/webhook/{namespace}/conventional-commits-enforcer/{COMMIT_LINT_WEBHOOK_KEY}, or trigger it manually to run against the fixture.
  4. Confirm the run reports NON_COMPLIANT with four violations, then check that an issue opened, Slack was notified, and report.txt holds one line per violation.

How to extend

  • Replace the fixture with a real checkout by adding a io.kestra.plugin.git.Clone task at the top of workspace, so git log reads live history.
  • Pass commit_limit per call to widen the window to the whole day when the disabled schedule is switched on.
  • Turn check_violations into a hard gate with a io.kestra.plugin.core.execution.Fail task, so branch protection blocks the merge.
  • Fan the loop out with concurrencyLimit above one for repositories with long histories.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.