> ## Documentation Index
> Fetch the complete documentation index at: https://dev.haico.gr/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Automations

> The live, always-on GitHub automations: issue forms, the area labeler, Release Drafter, CI/CD, the stale bot, and Dependabot.

# Repository Automations

This document is a functional overview of the **always-on GitHub automations** that run on the HAI-Co² repository: what fires, when, what it does, and where each one is configured. It follows the lifecycle of a change, from filing an issue to deploying a release.

These are the automations that are **live today**. The separate, label-gated **AI-assisted pathway** (an AI agent, Coco, run by `gh-aw` that plans a labelled issue, warns about higher-risk traits, and implements it after a human comments `/approve-plan`) is documented in [ai-pathway.md](/docs/ai-pathway); this document covers the rest.

For the label vocabulary these automations depend on, see [labels-reference.md](/docs/labels-reference). For the day-to-day operational view (what a maintainer watches and tunes), see [maintainers-handbook.md](/docs/maintainers-handbook).

How the live automations chain along the lifecycle of a change:

```mermaid theme={null}
flowchart TD
    A["New issue"] -->|"Issue forms"| B["type:* + needs-triage applied"]
    B --> C["PR opened against develop"]
    C -->|"Branch-name check"| D["Naming convention enforced"]
    C -->|"Area labeler"| E["area:* applied from changed paths"]
    C -->|"CI lint + test"| F["ci-complete gate"]
    F --> G["Squash-merge to develop"]
    G -->|"Release Drafter"| H["dev draft notes rebuilt"]
    H -->|"Push dev-vX.Y.Z / vX.Y.Z tag"| I["CI builds, pushes to GHCR, deploys"]
    J["Weekly schedule"] -->|"Stale bot"| K["Long-idle items marked stale, then closed"]
    J -->|"Dependabot"| L["Grouped dependency-update PRs"]
    L --> C
```

## At a glance

| Trigger                            | Automation        | What happens                                                          | Config                                                                                                                                                                                                       |
| ---------------------------------- | ----------------- | --------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| New issue                          | Issue forms       | Structured form; auto-applies `type:*` + `needs-triage`               | [`.github/ISSUE_TEMPLATE/`](https://github.com/petrosrapto/HAICO/blob/main/.github/ISSUE_TEMPLATE)                                                                                                           |
| PR opened against `main`/`develop` | Branch-name check | Fails the PR if the head branch breaks the naming convention          | [`branch-name.yml`](https://github.com/petrosrapto/HAICO/blob/main/.github/workflows/branch-name.yml)                                                                                                        |
| PR opened/updated                  | Area labeler      | Adds `area:*` labels from the changed paths (add-only)                | [`labeler.yml`](https://github.com/petrosrapto/HAICO/blob/main/.github/workflows/labeler.yml) + [`.github/labeler.yml`](https://github.com/petrosrapto/HAICO/blob/main/.github/labeler.yml)                  |
| Any push or PR                     | CI lint + test    | Frontend build/lint, frontend tests, backend tests, consolidated gate | [`ci.yml`](https://github.com/petrosrapto/HAICO/blob/main/.github/workflows/ci.yml)                                                                                                                          |
| Merge to `develop` / `main`        | Release Drafter   | Rebuilds the running draft release notes for that channel             | [`release-drafter-dev.yml`](https://github.com/petrosrapto/HAICO/blob/main/.github/release-drafter-dev.yml) / [`-prod.yml`](https://github.com/petrosrapto/HAICO/blob/main/.github/release-drafter-prod.yml) |
| Push `dev-vX.Y.Z` / `vX.Y.Z` tag   | Build + deploy    | Builds images, pushes to GHCR, deploys to the dev/prod server         | [`ci.yml`](https://github.com/petrosrapto/HAICO/blob/main/.github/workflows/ci.yml)                                                                                                                          |
| Weekly (Mon 06:00 UTC)             | Stale bot         | Marks long-inactive issues/PRs stale, later closes them               | [`stale.yml`](https://github.com/petrosrapto/HAICO/blob/main/.github/workflows/stale.yml)                                                                                                                    |
| Weekly                             | Dependabot        | Opens grouped dependency-update PRs across all ecosystems             | [`dependabot.yml`](https://github.com/petrosrapto/HAICO/blob/main/.github/dependabot.yml)                                                                                                                    |

***

## 1. Filing an issue: issue forms

**Trigger:** a user clicks **New issue**.

The [issue chooser](https://github.com/petrosrapto/HAICO/blob/main/.github/ISSUE_TEMPLATE/config.yml) offers four structured forms (Bug, Feature, Docs, Refactor) plus contact links that route usage questions and security reports elsewhere. Blank issues are disabled, so every issue starts from a form. Each form auto-applies its `type:*` label and `needs-triage` (the refactor form also pre-applies `path:traditional`).

**Note:** GitHub reads these forms from the **default branch only**, so they appear in the UI once merged there.

**Config:** [`.github/ISSUE_TEMPLATE/`](https://github.com/petrosrapto/HAICO/blob/main/.github/ISSUE_TEMPLATE).

## 2. Opening a PR: branch-name validation

**Trigger:** a PR is opened, edited, reopened, or synchronized against `main` or `develop`.

The workflow checks the PR's head branch against `<type>/<short-kebab-description>` (allowed types: `feature`, `bugfix`, `fix`, `hotfix`, `release`, `chore`, `refactor`, `docs`, `test`, `experiment`). If it doesn't match, the check fails with a message listing the convention. `main`, `develop`, and bot branches (`dependabot/*`, `renovate/*`, `github-actions/*`) are exempt, so release PRs (`develop → main`) and dependency-bump PRs pass.

**Config:** [`branch-name.yml`](https://github.com/petrosrapto/HAICO/blob/main/.github/workflows/branch-name.yml). The same rule is enforced locally (opt-in) by [`.githooks/pre-push`](https://github.com/petrosrapto/HAICO/blob/main/.githooks/pre-push).

## 3. Opening a PR: area labeler

**Trigger:** a PR is opened, reopened, synchronized, or marked ready for review.

`actions/labeler` adds `area:*` labels based on which paths the PR touches (`backend/**` → `area:backend`, `docs/**` and `*.md` → `area:docs`, `.github/**` → `area:ci`, and so on). It is **add-only** (`sync-labels: false`), so a label a triager added by hand is never stripped. It runs as `pull_request_target`, so it also works on fork PRs.

**Config:** [`labeler.yml`](https://github.com/petrosrapto/HAICO/blob/main/.github/workflows/labeler.yml) (workflow) + [`.github/labeler.yml`](https://github.com/petrosrapto/HAICO/blob/main/.github/labeler.yml) (path rules).

## 4. Every push or PR: CI (lint + test)

**Trigger:** any push to any branch, and every pull request.

Three jobs run in parallel: frontend build + lint, frontend tests, and backend tests (with coverage). A consolidated **`ci-complete`** gate then passes only if all three succeeded, which is the single status to mark as a required check in branch protection.

**Config:** [`ci.yml`](https://github.com/petrosrapto/HAICO/blob/main/.github/workflows/ci.yml) (the lint/test jobs and the gate).

## 5. Merges to `develop` / `main`: Release Drafter

**Trigger:** a push (merge) to `develop` or `main`, plus `pull_request_target` open/edit events against those branches.

Release Drafter maintains a **continuously-updated draft GitHub Release**: every merged PR is listed, grouped into categories by its `type:*` label, and the next SemVer version is computed from those labels. You never write release notes by hand. Two channels run independently so they don't pollute each other:

* **dev channel:** watches `develop`, drafts `dev-vX.Y.Z` notes ([`release-drafter-dev.yml`](https://github.com/petrosrapto/HAICO/blob/main/.github/release-drafter-dev.yml)).
* **prod channel:** watches `main`, drafts `vX.Y.Z` notes and lists the published container images ([`release-drafter-prod.yml`](https://github.com/petrosrapto/HAICO/blob/main/.github/release-drafter-prod.yml)).

Three config blocks do the work:

* `categories:` maps each `type:*` label to a notes section (`type:enhancement` → "✨ Features", `type:bug` → "🐞 Bug fixes", …). This mapping is mirrored in the table in [labels-reference.md §2](/docs/labels-reference).
* `version-resolver:` chooses the bump: a `breaking` label → major, `type:enhancement`/`type:refactor` → minor, everything else → patch.
* `autolabeler:` infers the `type:*` label from a Conventional-Commits PR title (`feat:` → `type:enhancement`, `fix:`/`hotfix:` → `type:bug`, …), so even an unlabelled PR is categorised correctly. This is why the PR template asks for a Conventional-Commits title.

Release Drafter only writes the **draft**; it never deploys. Publishing happens in step 6. The workflows run as `pull_request_target` so they read the workflow/config from the base branch, required by Release Drafter, which expects its config file to live on the default branch.

**Config:** the two `release-drafter-*.yml` configs and their workflows. Operational detail (keeping the two `autolabeler` blocks in sync, watching the draft) is in [maintainers-handbook.md](/docs/maintainers-handbook).

## 6. Pushing a tag: build, push, deploy

**Trigger:** pushing a SemVer tag, `dev-vX.Y.Z` or `vX.Y.Z`, after CI is green.

The same [`ci.yml`](https://github.com/petrosrapto/HAICO/blob/main/.github/workflows/ci.yml) pipeline resolves the tag to a channel, then builds and ships:

1. **`resolve-release`** classifies the tag: `dev-vX.Y.Z` → the `dev` GitHub Environment; `vX.Y.Z` → the `prod` GitHub Environment.
2. **`build-and-push`** builds the backend and frontend images and pushes them to GHCR, tagged with both the version and the channel tag (`:dev` or `:latest`).
3. **`deploy`** connects to the target server over VPN + SSH, generates `.env` files from the channel's `.env.example` (filling values from GitHub Environment secrets), ships the compose tree, and runs the deploy script. A required reviewer on the `prod` environment can gate production behind a human.
4. **`release-summary`** writes the published image refs and deploy result to the run summary.

So the full release chain is: **merge PRs (Release Drafter accumulates notes) → push the tag → `ci.yml` builds, pushes, and deploys → the draft becomes the published release notes.**

**Config:** [`ci.yml`](https://github.com/petrosrapto/HAICO/blob/main/.github/workflows/ci.yml). The branching/release procedure is in [CONTRIBUTING.md](https://github.com/petrosrapto/HAICO/blob/main/CONTRIBUTING.md); the two-branch rationale is [ADR-0001](/docs/adr/0001-two-branch-model).

## 7. Weekly: stale bot

**Trigger:** a weekly schedule (Monday 06:00 UTC), or manual dispatch.

Deliberately conservative: an issue/PR with no activity for **180 days** is labelled `status:stale` and warned, then closed after a further **21 days** unless someone comments. It processes at most 30 items per run, and exempts `blocked`, `help wanted`, `good first issue`, high-priority, and `path:ai-automation` items. This avoids the well-known anti-pattern of an aggressive stale bot driving contributors away.

**Config:** [`stale.yml`](https://github.com/petrosrapto/HAICO/blob/main/.github/workflows/stale.yml).

## 8. Weekly: Dependabot

**Trigger:** a weekly schedule, per ecosystem.

Dependabot opens dependency-update PRs across seven streams: `github-actions`, `pip` (backend), `npm` (frontend), and `docker` for `backend`, `frontend`, `deployment/dev`, and `deployment/prod`. Minor and patch updates are **grouped** into single PRs to cut noise, and each PR is labelled `type:chore` plus the relevant `area:*`, so it flows through the labeler/Release Drafter machinery like any other change.

**Config:** [`dependabot.yml`](https://github.com/petrosrapto/HAICO/blob/main/.github/dependabot.yml).

***

## How labels tie it all together

A single `type:*` and `area:*` pair drives most of the chain:

* **Issue forms** apply `type:*` at creation.
* **The labeler** applies `area:*` on the PR from changed paths.
* **Release Drafter** reads `type:*` to place the PR in the right notes section and to compute the version bump, falling back to the PR title via `autolabeler`.
* **The stale bot** reads status/priority labels to decide what to leave alone.

Because of this, the label taxonomy in [`.github/labels.yml`](https://github.com/petrosrapto/HAICO/blob/main/.github/labels.yml) is the connective tissue, and the [`release-drafter-*.yml` categories](https://github.com/petrosrapto/HAICO/blob/main/.github/release-drafter-dev.yml) and [labeler rules](https://github.com/petrosrapto/HAICO/blob/main/.github/labeler.yml) must stay in sync with it. Apply the taxonomy to a repo with [`.github/scripts/init-labels.sh`](https://github.com/petrosrapto/HAICO/blob/main/.github/scripts/init-labels.sh).

## The AI-assisted pathway

A second, opt-in pathway dispatches labelled issues to a **provider-agnostic AI agent** (run by [`gh-aw`](https://github.github.com/gh-aw/) on the repo's own API key), gated by a `path:ai-automation[-<engine>]` label. The engine is chosen by label: the default `path:ai-automation` (Copilot, needs a seat) or explicit `path:ai-automation-copilot`; `path:ai-automation-claude` and `path:ai-automation-codex` are seat-free. Assigning the `HAI-Coco` bot account to an issue automatically adds `path:ai-automation` (via `coco-assign-label.yml`). Adding the label opens a **draft PR with the plan as its first comment**; `/coco <change>` before `/approve-plan` revises the plan (no code written); `/approve-plan` implements the plan; CI runs; `/promote dev` deploys to dev; `/coco X` after approval iterates on the code; marking the PR ready for review runs Coco's automated review; a human approves and merges. The workflows live in [`.github/workflows/`](https://github.com/petrosrapto/HAICO/blob/main/.github/workflows) as `ai-{plan,implement,iterate,review,review-ondemand}-{claude,codex,copilot}.md` (gh-aw sources sharing prompt bodies from [`.github/aw/shared/`](https://github.com/petrosrapto/HAICO/blob/main/.github/aw/shared), compiled to `*.lock.yml`), plus the classic `coco-plan-comment.yml`, `coco-approve-ack.yml`, `coco-assign-label.yml`, `coco-stage-labels.yml`, `promote-dev.yml`, `notify-dev-ready.yml`, and `notify-approved.yml`. A `stage:*` label (managed by `coco-stage-labels.yml`) tracks each AI-pathway issue and PR through the lifecycle, so the Issues and Pull-requests lists show where every item is at a glance. The full how-it-works + setup is in [ai-pathway.md](/docs/ai-pathway); the rationale for having two pathways is [ADR-0002](/docs/adr/0002-dual-development-pathways).

## Where to go deeper

* [labels-reference.md](/docs/labels-reference): the canonical label taxonomy these automations key off.
* [maintainers-handbook.md](/docs/maintainers-handbook): the operational view (release channels, what to watch, what to tune).
* [repository-foundation.md §11](/docs/repository-foundation): how the labeler, Release Drafter, and stale bot are wired (config listings).
* [ai-pathway.md](/docs/ai-pathway): the as-built AI-assisted pathway (gh-aw, provider-agnostic).
* [github-projects-copilot-automation.md](/docs/github-projects-copilot-automation): the original Copilot-based design, kept as background.
