GitHub·7 min read·

Automating GitHub Issues: Templates, Labels, and Triage Bots

Standard templates, reusable labels, and a little triage bot turn a noisy public issue queue into an actionable backlog, and nothing real slips through.

NB

Netbay Developer Relations

Netbay Engineering

On this page

Issues are the raw input of almost every repository, yet most projects send them through an unmarked door. A blank textarea collects typos, half-empty bug reports, and feature requests that take three follow-up questions to become actionable. That is precisely what templates, labels, and a lightweight triage bot fix. Templates make the reporter do the minimum useful work at submit time, labels turn the queue into a queryable dataset, and automation takes over the chores you would otherwise do by hand.

Templates and forms

GitHub supports two kinds of issue templates. A classic markdown template is a file of instructions the reporter sees when the field is empty. A form schema, configured in YAML, renders structured fields — checkboxes, dropdowns, and textareas — and marks some of them required. Forms are the better default because they *enforce* structure instead of suggesting it: an empty reproduction box is impossible to submit if you refuse blank rows.

yaml
# .github/ISSUE_TEMPLATE/config.yml
blank_issues_enabled: false

# .github/ISSUE_TEMPLATE/bug.yml
name: Bug report
description: Something is broken
title: "[bug] "
labels: [kind/bug, needs-triage]
body:
  - type: textarea
    id: repro
    attributes:
      label: Steps to reproduce
      placeholder: Exact commands, input, and output
    validations:
      required: true
  - type: textarea
    id: expected
    attributes:
      label: Expected behaviour
    validations:
      required: true
  - type: input
    id: version
    attributes:
      label: Version
      placeholder: e.g. 1.4.2
    validations:
      required: true
  - type: dropdown
    id: severity
    attributes:
      label: Impact
      options: [blocks us, slows us, cosmetic]

Keep one template per issue type and keep them short. Every extra required field is a tax the reporter pays; five questions is a good ceiling. The "labels" key pre-stamps the issue, which is your first automation point — the reporter does the labeling at zero cost to you.

Labels as a vocabulary, not a color picker

Labels are the cheapest database you will ever operate, but only if they form a taxonomy. A pile of hand-decorated colors is noise; a small vocabulary reads like a filter you can teach a new contributor in a minute:

  • **kind/** — bug, feature, question, chore.
  • **area/** — web, api, cli, docs, infra.
  • **priority/** — p0 down to p3; assigned by triage, never by the reporter.
  • **status/** — needs-repro, blocked, doing, review.
  • **flagged/** — security, privacy, licensing.

The discipline matters more than the exact words: every label is a question you can ask the queue later, like "show me everything touching the api marked blocked." If a label never gets queried, it is decoration — delete it.

Triaging with a small workflow

A triage loop has three jobs: stamp every new issue, catch the obvious ones instantly, and leave a predictable trail. A workflow on the issues event does the first two. Notice this is repo operations, not CI — it lives in .github/workflows but it is bookkeeping, and it runs on the issue event rather than a push.

yaml
name: triage
on:
  issues:
    types: [opened]
jobs:
  triage:
    runs-on: ubuntu-latest
    permissions:
      issues: write
    steps:
      - uses: actions/ecosystem/action-add-labels@v1
        with:
          labels: needs-triage
      - name: flag sev1 mentions instantly
        if: contains(github.event.issue.body, 'SEV1')
        uses: actions/ecosystem/action-add-labels@v1
        with:
          labels: priority/p0

The workflow does not close anything and does not assign heroes — it only normalizes input so a human triage pass is fast. Deciding a p0 actually exists is still a human call; the bot just makes sure nothing sits in the default pile unremarked.

issue lifecycle form submit labels stamped kind/area auto-applied triage workflow priority decided backlog bug report repro + version query by label gh issue list closed predictable trail labels are the query vocabulary triage is automation, not a meeting templates decide the quality of your input

Practical: batch maintenance with gh

Once labels exist, the GitHub CLI makes bulk bookkeeping safe and scriptable. A triage sweep stops being hand-clicking and becomes a query:

bash
# what is still untangled, sorted by last touch
gh issue list --label needs-triage --state open   --search 'updated:<2026-03-01' --json number,title,updatedAt

# every security-flagged issue, as a one-shot CSV-ish line
gh issue list --label flagged/security --state open   --json number,title,assignees --jq '.[] | "(.number) (.title) (.assignees | length)"'

Run the first command weekly and the untriaged pile becomes a number you can trend instead of a doomscroll.

Where the automation ends

Triage bots sort; they do not judge. The label p0 says "look now," not "this is panicking." Keep a human pass with a written SLA — untriaged issues reviewed within one working day, p0 within the hour — and let the bot enforce the bookkeeping around that cadence rather than replacing it.

The useful metric to watch is not total issues but time-to-triage: how long between an issue opening and its first label or assignment. When that number falls to minutes for everything the form catches and a working day for the rest, the loop is closed. These are the two signals that tell you the templates and the workflow are actually paying for themselves, rather than just moving the noise around.

Takeaway: forms raise the floor on report quality, a small label taxonomy makes the queue queryable, and a tiny workflow plus gh keep the loop closed without a human babysitting every ticket. If you are building this sort of tooling around your tracker, the bot and the repo mirror can run on a Lucknow DC01 VPS from Netbay — ready in under 60 seconds at netbayhosts.in.

Keep reading

Follow along on a real VPS

Deploy Linux in under 60 seconds

These guides are written against Ubuntu, Debian, and RHEL-family images — the same ones on NetBay.

Deploy an instance