|
| 1 | +# Contributing to the DevOps Error Library |
| 2 | + |
| 3 | +Thank you for helping build the open-source encyclopedia of real DevOps, Cloud, Kubernetes, Docker, Terraform and OpenStack errors. Every accurate page you add saves another engineer a bad night. This guide explains the quality bar, how to add and update errors, the validation/CI rules, and the PR process. |
| 4 | + |
| 5 | +> **TL;DR** |
| 6 | +> ```bash |
| 7 | +> errlib new "Terraform State Lock" --tech terraform --severity high |
| 8 | +> # fill in every section with real logs + read-only diagnostics |
| 9 | +> errlib validate # must pass |
| 10 | +> # commit, push, open a PR using the checklist below |
| 11 | +> ``` |
| 12 | +
|
| 13 | +--- |
| 14 | +
|
| 15 | +## π― The quality bar |
| 16 | +
|
| 17 | +This is a curated reference, not a link dump. Hold every contribution to **senior DevOps / SRE level**: |
| 18 | +
|
| 19 | +- **Accuracy over quantity.** One correct, complete page beats ten thin ones. We would rather merge slowly than merge wrong. |
| 20 | +- **No fabricated logs.** Error messages must be **verbatim** strings you have actually seen, reproduced, or sourced from official docs/issues. Do not invent plausible-looking output. If you only have a paraphrase, say so or don't include it. |
| 21 | +- **Read-only diagnostics only.** Everything in *Diagnostic Commands* must be safe to run on a live system: `describe`, `get`, `logs`, `status`, `journalctl`, `show`, `inspect`, `EXPLAIN`, etc. Never put a destructive or state-changing command in that section β those belong in *Resolution*, clearly flagged as risky. |
| 22 | +- **Explain the mechanism.** The *Root Cause Analysis* must connect the log line to *why* the system produced it, not just restate the symptom. |
| 23 | +- **Write for the reader at 3 a.m.** Precise, concrete, skimmable. Assume competence; don't pad. |
| 24 | +
|
| 25 | +No AI slop. Pages generated wholesale by an LLM without verification will be closed. Using AI to draft is fine β verifying every log line and command is mandatory. |
| 26 | +
|
| 27 | +--- |
| 28 | +
|
| 29 | +## β Adding a new error |
| 30 | +
|
| 31 | +### 1. Scaffold the page |
| 32 | +
|
| 33 | +```bash |
| 34 | +errlib new "<Human Error Title>" --tech <technology> [--severity <level>] [--tags t1,t2] [--subdir <service>] |
| 35 | +``` |
| 36 | +
|
| 37 | +Examples: |
| 38 | + |
| 39 | +```bash |
| 40 | +errlib new "Kubernetes Evicted Pod" --tech kubernetes --severity high |
| 41 | +errlib new "Nova No Valid Host" --tech openstack --subdir nova --severity high |
| 42 | +``` |
| 43 | + |
| 44 | +- `--tech` picks the `errors/<technology>/` folder and is **required**. |
| 45 | +- `--subdir` nests the file one level deeper β **use it for OpenStack services** (`nova`, `cinder`, `neutron`, `glance`, `keystone`, `heat`, `horizon`, `swift`, `placement`, `ironic`). |
| 46 | +- `--severity` is one of `info | low | medium | high | critical` (defaults to `medium`). |
| 47 | +- `--tags` is a comma-separated list. |
| 48 | + |
| 49 | +The title becomes a **kebab-case slug**, and the **slug must equal the filename** (without `.md`). `errlib new` handles this for you β don't rename the file afterwards without updating the `slug:` field to match. |
| 50 | + |
| 51 | +### 2. Fill in every section |
| 52 | + |
| 53 | +Open the generated file and complete **all 14 sections** β none may be empty. Use [`ERROR_TEMPLATE.md`](./ERROR_TEMPLATE.md) as the canonical reference and [`errors/kubernetes/kubernetes-crashloopbackoff.md`](./errors/kubernetes/kubernetes-crashloopbackoff.md) as a worked example. |
| 54 | + |
| 55 | +Section-by-section expectations: |
| 56 | + |
| 57 | +| Section | What good looks like | |
| 58 | +| --- | --- | |
| 59 | +| **Error Message** | Verbatim string(s) in a fenced block. Include 1β2 realistic variants people paste into search. | |
| 60 | +| **Description** | 1β2 paragraphs: what it means, which component emits it, when. | |
| 61 | +| **Technologies** | The technology + the component/subsystem. | |
| 62 | +| **Severity** | The level **and** the operational impact (degraded / partial / full outage / data-loss risk). | |
| 63 | +| **Common Causes** | Ordered by real-world frequency, stated concretely. | |
| 64 | +| **Root Cause Analysis** | The mechanism β how each cause produces this exact error. | |
| 65 | +| **Diagnostic Commands** | Real, **read-only** commands with a comment on what each reveals. | |
| 66 | +| **Expected Results** | What the output looks like when broken vs. healthy. | |
| 67 | +| **Resolution** | Numbered, actionable steps. Flag any risky/destructive step. | |
| 68 | +| **Validation** | The command + output that proves the error is resolved. | |
| 69 | +| **Prevention** | Concrete guardrails / CI checks to stop recurrence. | |
| 70 | +| **Related Errors** | Relative links to neighbouring pages. | |
| 71 | +| **References** | Official docs first; deeper guides may link to https://devopsaitoolkit.com/blog. | |
| 72 | +| **Tags** | The same tags as the front matter, as `` `code` `` separated by `Β·`. | |
| 73 | + |
| 74 | +### 3. Get the front matter right |
| 75 | + |
| 76 | +```yaml |
| 77 | +--- |
| 78 | +title: "Kubernetes CrashLoopBackOff" # human title, quoted |
| 79 | +slug: kubernetes-crashloopbackoff # MUST match the filename (kebab-case) |
| 80 | +technologies: [kubernetes] # one or more |
| 81 | +severity: high # info | low | medium | high | critical |
| 82 | +tags: [kubernetes, pod, scheduling, crashloopbackoff, production] |
| 83 | +related: [kubernetes-imagepullbackoff, kubernetes-oomkilled] # slugs of related pages |
| 84 | +last_reviewed: 2026-06-27 # YYYY-MM-DD, the date you verified it |
| 85 | +--- |
| 86 | +``` |
| 87 | + |
| 88 | +- **`slug` must equal the filename.** This is checked in CI. |
| 89 | +- **`severity`** must be one of the five allowed values. |
| 90 | +- **`related`** lists *slugs* (not paths); the body's *Related Errors* section links to them with relative paths. |
| 91 | +- **`tags`** should include the technology, the area, the symptom, and `production` where relevant β they power `errlib search --tag`. |
| 92 | +- **`last_reviewed`** is the date a human verified the content. |
| 93 | + |
| 94 | +### 4. Validate locally |
| 95 | + |
| 96 | +```bash |
| 97 | +errlib validate # front matter + sections + slugs; exits non-zero on any issue |
| 98 | +errlib index # rebuild the JSON index (optional locally; CI does it) |
| 99 | +errlib search "<a phrase from your page>" # sanity-check it's findable |
| 100 | +``` |
| 101 | + |
| 102 | +`errlib validate` must print `OK β N error document(s) valid.` before you open a PR. |
| 103 | + |
| 104 | +--- |
| 105 | + |
| 106 | +## βοΈ Updating or verifying existing errors |
| 107 | + |
| 108 | +- Found something inaccurate or outdated? Fix it and bump `last_reviewed` to today's date. |
| 109 | +- Re-running the diagnostic commands on a current version of the technology and confirming the output still matches counts as a real, valuable contribution β bump `last_reviewed`. |
| 110 | +- If a tool's output format changed across versions, note the affected versions in *Description* or *Expected Results* rather than overwriting; keep the page useful for people on older releases. |
| 111 | +- Keep edits scoped: one logical change per PR makes review fast. |
| 112 | + |
| 113 | +--- |
| 114 | + |
| 115 | +## β
Validation & CI rules |
| 116 | + |
| 117 | +Every pull request runs CI, which: |
| 118 | + |
| 119 | +1. Runs **`errlib validate`** β fails on missing/empty sections, malformed or missing front-matter keys, an invalid `severity`, or a `slug` that doesn't match the filename. |
| 120 | +2. Rebuilds the **JSON search index** (`errlib index`) to confirm the corpus compiles. |
| 121 | +3. Regenerates the category indexes (`scripts/gen_indexes.py`) β these are navigation aids and are excluded from validation and the search index, so you don't have to hand-edit them. |
| 122 | +4. Runs the **test suite** (`pytest`). |
| 123 | + |
| 124 | +If `errlib validate` fails locally, it will fail in CI β fix it before pushing. |
| 125 | + |
| 126 | +--- |
| 127 | + |
| 128 | +## π Pull request process |
| 129 | + |
| 130 | +1. Fork the repo and create a branch: `git checkout -b add/<tech>-<slug>`. |
| 131 | +2. Add or edit error pages; run `errlib validate` until it passes. |
| 132 | +3. Commit with a clear message, e.g. `Add: Terraform State Lock error`. |
| 133 | +4. Open a PR against `main` and fill in the checklist below. |
| 134 | +5. A maintainer reviews for accuracy and the quality bar; address feedback; we merge. |
| 135 | + |
| 136 | +### PR checklist |
| 137 | + |
| 138 | +- [ ] Created the page with `errlib new` (correct `--tech` / `--subdir`). |
| 139 | +- [ ] All **14 sections** filled in β none empty. |
| 140 | +- [ ] Error Message is **verbatim**; no fabricated logs. |
| 141 | +- [ ] Diagnostic Commands are **read-only** and safe to run live. |
| 142 | +- [ ] Front matter complete: valid `severity`, `slug` == filename, useful `tags`, `related` slugs, `last_reviewed` set. |
| 143 | +- [ ] `errlib validate` passes locally (`OK β N error document(s) valid.`). |
| 144 | +- [ ] Related links and references resolve. |
| 145 | +- [ ] One logical change per PR. |
| 146 | + |
| 147 | +--- |
| 148 | + |
| 149 | +## π¦ Claiming & coordinating large batches |
| 150 | + |
| 151 | +Adding 20+ errors for a technology? Help us avoid duplicate work: |
| 152 | + |
| 153 | +1. Open a tracking issue titled e.g. `Batch: 30 PostgreSQL errors` listing the titles/slugs you plan to add. |
| 154 | +2. A maintainer will confirm there's no overlap and effectively "assign" the batch to you. |
| 155 | +3. Submit in **reviewable chunks** (roughly 5β10 errors per PR) rather than one giant PR β it's faster to review and less likely to bit-rot. |
| 156 | +4. Check the per-technology targets in [`ROADMAP.md`](./ROADMAP.md) so your batch moves a real goal forward. |
| 157 | + |
| 158 | +--- |
| 159 | + |
| 160 | +## π¨ Style & structure conventions |
| 161 | + |
| 162 | +- **One error per file.** Never combine multiple distinct errors in a page. |
| 163 | +- **Folder = technology.** `errors/<technology>/`. OpenStack is split by **service** subfolder. |
| 164 | +- **Filename = slug**, kebab-case, prefixed with the technology where natural (`kubernetes-crashloopbackoff.md`, `nova-no-valid-host.md`). |
| 165 | +- **Severity scale:** `info` (informational) β `low` β `medium` β `high` β `critical` (data loss / full outage). Choose by operational impact, not by how scary the message looks. |
| 166 | +- **Voice:** senior engineer, concrete, no filler. Prefer imperative steps in *Resolution*. |
| 167 | +- **Code blocks:** use ```text for logs/output, ```bash for commands, ```yaml for manifests. |
| 168 | +- **Links:** relative paths between error pages; absolute URLs for external references. |
| 169 | + |
| 170 | +--- |
| 171 | + |
| 172 | +## π Licensing of contributions |
| 173 | + |
| 174 | +By contributing, you agree that: |
| 175 | + |
| 176 | +- **Error content** (anything under `errors/`) is licensed **CC BY 4.0**. |
| 177 | +- **Code** (`errlib/`, `scripts/`) is licensed **MIT**. |
| 178 | + |
| 179 | +Only submit content you have the right to share. Thanks for making DevOps troubleshooting better for everyone. π |
0 commit comments