Skip to content
Latchkey

Issue title lint workflow (bdfinst/agentic-dev-team)

The Issue title lint workflow from bdfinst/agentic-dev-team, explained and optimized by Latchkey.

C

CI health: C - fair

Point runs-on at Latchkey and get caching, job timeouts, self-healing for flaky steps, and up to 58% lower cost, applied automatically.

Grade your own workflow free or run it on Latchkey →
Source: bdfinst/agentic-dev-team.github/workflows/issue-title-lint.ymlLicense MITView source

What it does

This is the Issue title lint workflow from the bdfinst/agentic-dev-team repository, a real project running GitHub Actions. It is shown here with attribution under its MIT license.

Below, Latchkey shows a faster, safer version produced by its optimization engine.

The workflow

workflow (.yml)
name: Issue title lint

# Specs become epic issues and plan slices become sub-issues; downstream those
# titles seed branch names, PR titles, and (via the landed commits) release
# versions. So issue titles must follow the SAME Conventional Commits ruleset as
# commits (commitlint.config.js). GitHub has no "required check" for issues, so
# this is a visible backstop: it labels a non-conforming title and comments the
# fix once, then clears the label when the title is corrected. The primary,
# proactive enforcement is in the issue-creating skills (issues-from-plan,
# issues-from-assessment), which lint titles before `gh issue create`.

on:
  issues:
    types: [opened, edited]

permissions:
  contents: read
  issues: write

concurrency:
  group: issue-title-lint-${{ github.event.issue.number }}
  cancel-in-progress: true

jobs:
  lint-issue-title:
    name: Issue title lint
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - uses: actions/setup-node@v6
        with:
          # Single source of truth for the Node version - read from .nvmrc.
          node-version-file: .nvmrc
      - run: npm ci
        env:
          HUSKY: 0
      - name: Lint issue title against commitlint.config.js
        id: lint
        env:
          # Pass via env, never interpolate untrusted issue input into the shell.
          ISSUE_TITLE: ${{ github.event.issue.title }}
        run: |
          set +e
          report="$(printf '%s' "$ISSUE_TITLE" | npx commitlint --verbose 2>&1)"
          rc=$?
          printf '%s\n' "$report"
          {
            echo "rc=$rc"
            echo "report<<COMMITLINT_EOF"
            printf '%s\n' "$report"
            echo "COMMITLINT_EOF"
          } >> "$GITHUB_OUTPUT"
          exit 0
      - name: Flag or clear the issue based on the result
        env:
          GH_TOKEN: ${{ github.token }}
          NUM: ${{ github.event.issue.number }}
          RC: ${{ steps.lint.outputs.rc }}
          REPORT: ${{ steps.lint.outputs.report }}
        run: |
          label="needs-conventional-title"
          # Ensure the label exists (idempotent); ignore "already exists".
          gh label create "$label" --color FBCA04 \
            --description "Issue title does not follow Conventional Commits" --force >/dev/null 2>&1 || true

          if [ "$RC" = "0" ]; then
            # Passing: clear the flag if it was set. No comment on success.
            gh issue edit "$NUM" --remove-label "$label" >/dev/null 2>&1 || true
            exit 0
          fi

          # Failing: comment only on the first detection (label not already
          # present) so successive bad edits don't spam the thread. Build the
          # body with tilde code fences (not backticks) so the shell never reads
          # the markdown as command substitution.
          had_label="$(gh issue view "$NUM" --json labels --jq '.labels[].name' 2>/dev/null | grep -Fxq "$label" && echo yes || echo no)"
          gh issue edit "$NUM" --add-label "$label" >/dev/null 2>&1 || true
          if [ "$had_label" = "no" ]; then
            {
              echo "⚠️ **This issue title is not a Conventional Commit.**"
              echo
              echo "Specs become epics and plan slices become sub-issues, and these titles seed branch names, PR titles, and release versions - so they must follow the same commitlint ruleset as commits (for example: feat:, fix:, docs:, chore:)."
              echo
              echo "~~~"
              printf '%s\n' "$REPORT"
              echo "~~~"
              echo
              echo "Edit the title to fix; this check re-runs on every edit and clears the label once it passes."
            } > issue-title-comment.md
            gh issue comment "$NUM" --body-file issue-title-comment.md
          fi

The same workflow, on Latchkey

Estimated ~20% faster on cache hits, plus fewer wasted runs and a safer supply chain. Added and changed lines are highlighted.

name: Issue title lint
 
# Specs become epic issues and plan slices become sub-issues; downstream those
# titles seed branch names, PR titles, and (via the landed commits) release
# versions. So issue titles must follow the SAME Conventional Commits ruleset as
# commits (commitlint.config.js). GitHub has no "required check" for issues, so
# this is a visible backstop: it labels a non-conforming title and comments the
# fix once, then clears the label when the title is corrected. The primary,
# proactive enforcement is in the issue-creating skills (issues-from-plan,
# issues-from-assessment), which lint titles before `gh issue create`.
 
on:
  issues:
    types: [opened, edited]
 
permissions:
  contents: read
  issues: write
 
concurrency:
  group: issue-title-lint-${{ github.event.issue.number }}
  cancel-in-progress: true
 
jobs:
  lint-issue-title:
    timeout-minutes: 30
    name: Issue title lint
    runs-on: latchkey-small
    steps:
      - uses: actions/checkout@v7
      - uses: actions/setup-node@v6
        with:
          cache: 'npm'
          # Single source of truth for the Node version - read from .nvmrc.
          node-version-file: .nvmrc
      - run: npm ci
        env:
          HUSKY: 0
      - name: Lint issue title against commitlint.config.js
        id: lint
        env:
          # Pass via env, never interpolate untrusted issue input into the shell.
          ISSUE_TITLE: ${{ github.event.issue.title }}
        run: |
          set +e
          report="$(printf '%s' "$ISSUE_TITLE" | npx commitlint --verbose 2>&1)"
          rc=$?
          printf '%s\n' "$report"
          {
            echo "rc=$rc"
            echo "report<<COMMITLINT_EOF"
            printf '%s\n' "$report"
            echo "COMMITLINT_EOF"
          } >> "$GITHUB_OUTPUT"
          exit 0
      - name: Flag or clear the issue based on the result
        env:
          GH_TOKEN: ${{ github.token }}
          NUM: ${{ github.event.issue.number }}
          RC: ${{ steps.lint.outputs.rc }}
          REPORT: ${{ steps.lint.outputs.report }}
        run: |
          label="needs-conventional-title"
          # Ensure the label exists (idempotent); ignore "already exists".
          gh label create "$label" --color FBCA04 \
            --description "Issue title does not follow Conventional Commits" --force >/dev/null 2>&1 || true
 
          if [ "$RC" = "0" ]; then
            # Passing: clear the flag if it was set. No comment on success.
            gh issue edit "$NUM" --remove-label "$label" >/dev/null 2>&1 || true
            exit 0
          fi
 
          # Failing: comment only on the first detection (label not already
          # present) so successive bad edits don't spam the thread. Build the
          # body with tilde code fences (not backticks) so the shell never reads
          # the markdown as command substitution.
          had_label="$(gh issue view "$NUM" --json labels --jq '.labels[].name' 2>/dev/null | grep -Fxq "$label" && echo yes || echo no)"
          gh issue edit "$NUM" --add-label "$label" >/dev/null 2>&1 || true
          if [ "$had_label" = "no" ]; then
            {
              echo "⚠️ **This issue title is not a Conventional Commit.**"
              echo
              echo "Specs become epics and plan slices become sub-issues, and these titles seed branch names, PR titles, and release versions - so they must follow the same commitlint ruleset as commits (for example: feat:, fix:, docs:, chore:)."
              echo
              echo "~~~"
              printf '%s\n' "$REPORT"
              echo "~~~"
              echo
              echo "Edit the title to fix; this check re-runs on every edit and clears the label once it passes."
            } > issue-title-comment.md
            gh issue comment "$NUM" --body-file issue-title-comment.md
          fi
 

What changed

What Latchkey heals here

This workflow has steps that commonly fail on transient issues (network, registries, flaky browsers). On Latchkey managed runners they are detected, retried, and self-healed instead of failing your build:

This workflow runs 1 job per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.

Actions used in this workflow