agentleFS
cnoe-iocnoe-io/ai-platform-engineering/.claude/skills/release-docs/SKILL.md

release-docs

Skill438 starsChanged 53 days agoApache-2.0View on GitHub

Generate a combined release blog post for ai-platform-engineering. Produces a single docs/releases/YYYY-MM-DD-release-X-Y-Z.md file containing release notes and the upgrade guide (migration guide) inline. Use when cutting a release, when a user asks "what changed in 0.4.x", or when upgrading their values.yaml to a new chart version.

8 other projects use a version of this.

Adopted by

Most recently taken up by

The file

Show its rules and text

We split this skill into the rules it gives an agent

19 rules. 0 are common, 15 are distinctive, and 4 are very specific to this project.

  • 0

    Common

    Most of the 7 edited versions we read keep these.

  • 15

    Distinctive

    This author's own choices. Worth a look.

  • 4

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Ask the user for:

    line 39
  2. Distinctive:

    If from/to are not provided, detect from the repo:

    line 48
  3. Distinctive:

    Run all of the following in parallel where possible.

    line 58
  4. Distinctive:

    Before drafting, make a scratch checklist of every merged PR and human contributor in the release range.

    line 127
  5. Very specific:

    Do not publish the scratch checklist.

    line 134
  6. Distinctive:

    Use the date the tag was pushed (or today's date if cutting now).

    line 145
  7. Very specific:

    After writing the blog post, snapshot the current docs/ tree as the new version and prune old snapshots to stay within the retention policy.

    line 277
  8. Distinctive:

    Run from repo root:

    line 285
  9. Distinctive:

    Commit all release artifacts together:

    line 297
  10. Distinctive:

    Write the smallest accurate release post.

    line 321
  11. Distinctive:

    Use direct sentences with a clear actor.

    line 323
  12. Distinctive:

    Prefer concrete verbs and plain connecting words.

    line 324
  13. Distinctive:

    Do not force groups of three, symmetrical paragraphs, a heading for every paragraph, or a redundant key-takeaways section.

    line 325
  14. Distinctive:

    Read the draft once as if explaining the release to a teammate.

    line 326
  15. Distinctive:

    Keep the upgrade runbook linear — steps should be self-contained

    line 333
  16. Very specific:

    If helm show values is unavailable, ask the user to paste output — never guess

    line 334
  17. Distinctive:

    If there are zero helm value changes, say so explicitly and reassure it is a drop-in upgrade

    line 338
  18. Distinctive:

    Do NOT create separate migration guide files — the upgrade guide lives inside the release post

    line 339
  19. Very specific:

    Do NOT add a "Personal Impact Analysis" heading or a raw "Full Values Diff" dump.

    line 340

“Common” is measured: kept by at least 6 in 10 of the 7 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Release Blog Post Generator

Produce one combined blog post for an ai-platform-engineering release:

docs/releases/YYYY-MM-DD-release-X-Y-Z.md — release notes narrative (highlights, what's new, bug fixes, breaking changes) followed by the full upgrade guide (Helm values diff, step-by-step runbook) as an embedded section.

The file is picked up by the Docusaurus releases blog plugin and published at /blog/releases/release-X.Y.Z.


Execution context

Runs in two modes:

  • Coding agent (Claude Code, Cursor) with shell access — run git and helm commands directly and write the file to disk.
  • Chat-only (CAIPE chat, Slack, web UI) — render output as a fenced markdown block the user can copy; note which commands to run manually.

Detect by whether a Bash/shell tool is available.


Step 1 — Gather inputs

Ask the user for:

InputExampleRequired
To version0.4.9Yes
From version0.4.8Yes (defaults to previous tag)
User's values.yamlpaste or pathNo — lets the runbook call out exactly which of their keys are affected
Environmentdev / preview / prod / vmNo — enables env-specific notes

If from/to are not provided, detect from the repo:

git tag --sort=-version:refname | grep -E '^[0-9]+\.[0-9]+\.[0-9]+$' | head -2

Step 2 — Collect raw data

Run all of the following in parallel where possible.

2a — Git log between versions

git log <from>..<to> --oneline --no-merges

Fetch full PR bodies and authors for every merged PR in the range:

# for each PR number in the log, e.g. (#1324):
gh pr view <number> --json title,body,author,labels,files,mergedAt

List the human commit authors as a cross-check. Merge commits and co-authored work can otherwise hide a contributor:

git log <from>..<to> --format='%aN <%aE>%x09%s'

2b — Helm values diff

CHART=oci://ghcr.io/caipe-io/charts/ai-platform-engineering
helm show values "$CHART" --version <from> > /tmp/values-from.yaml
helm show values "$CHART" --version <to>   > /tmp/values-to.yaml
diff -u /tmp/values-from.yaml /tmp/values-to.yaml

2c — Chart metadata

helm show chart "$CHART" --version <to>

2d — CHANGELOG.md

sed -n '/^## <to>/,/^## <from>/p' CHANGELOG.md

Step 3 — Classify changes

Classify git commits

TypeCriteria
Featurefeat(*) commits
Fixfix(*) commits
Securitycommits touching Dockerfile, securityContext, PSS/PSA
Breakingcommit body contains "BREAKING CHANGE" or PR label breaking-change
Chore / Internalchore, refactor, ci, test — omit from user-facing notes

Classify Helm values diff lines

CategoryCriteria
BreakingKey renamed, removed, or type changed
New requiredNew key with no default
New optionalNew key with working default
DeprecatedKey still works but will be removed
Default changedSame key, different default value

Account for contributors

Before drafting, make a scratch checklist of every merged PR and human contributor in the release range. For each PR, record one of two outcomes:

  • included in the release post, with its PR link and distinct user or operator impact;
  • omitted because it is release automation, internal cleanup, tests, or another change with no user-visible or upgrade impact.

Do not publish the scratch checklist. Use it to catch missing work, then add every human whose included work shipped in the release to the frontmatter authors list. Verify each author key exists in docs/releases/authors.yml and keep bots out of the byline.

Related PRs can share a section, but do not compress separate outcomes so far that a meaningful contribution disappears.


Step 4 — Write docs/releases/YYYY-MM-DD-release-X-Y-Z.md

Use the date the tag was pushed (or today's date if cutting now).

---
slug: release-<to>
title: "Release <to>: <short subtitle capturing the biggest change>"
date: <YYYY-MM-DD>
authors: [<verified human contributor keys>]
tags: [release]
---

## Highlights

<1-3 sentence narrative of the most significant changes in plain English.
Focus on operator/user impact, not internal implementation details.>

<!-- truncate -->

## What's New

### <Feature area, when grouping helps>

- **<Title>** — <one-line description linking to PR #NNNN>

## Bug Fixes

- **<scope>**: <description> ([#NNNN](https://github.com/caipe-io/ai-platform-engineering/pull/NNNN))

## Security

<Any security-context, PSS, or CVE-related changes. Omit section if none.>

## Breaking Changes

<If none:>
No breaking changes. Drop-in upgrade from <from>.

## Known Issues

<If none:>
None known at this time.

---

## Upgrade Guide: <from> → <to>

### Overview

<One paragraph: overall theme, e.g. "Drop-in upgrade — no values.yaml edits required.">

### Helm Values Changes

<If no diff:>
No Helm values changes between <from> and <to>. Drop-in upgrade.

<If diff exists, use these subsections:>

#### Breaking Changes

**Affected key**: `global.foo.bar`

**Before (<from>)**:

```yaml
global:
  foo:
    bar: "old-value"
```

**After (<to>)**:

```yaml
global:
  foo:
    bar: "new-value"
```

**Action**: Update your `values.yaml`. If left unchanged, <consequence>.

#### New Optional Fields

| Env Var / Key     | Default        | Description                  |
| ----------------- | -------------- | ---------------------------- |
| `TOOL_CALL_LIMIT` | `0` (disabled) | Max tool invocations per run |

#### Deprecated / Removed Keys

| Key            | Removed in | Replacement     |
| -------------- | ---------- | --------------- |
| `tags.old-key` | <to>       | `global.newKey` |

### Upgrade Runbook

#### 1. Update chart version

```bash
helm upgrade ai-platform-engineering \
  oci://ghcr.io/caipe-io/charts/ai-platform-engineering \
  --version <to> \
  -f your-values.yaml
```

#### 2. Apply values.yaml changes

<Paste exact diffs for each breaking change. If the user supplied their `values.yaml`, call
out exactly which of their keys are affected by each breaking/deprecated change, or state
that none of their keys are affected. If there are no breaking changes, state that no
values.yaml edits are required.>

#### 3. Verify

```bash
kubectl get pods -n <namespace>
```

Step 5 — Write file to disk (coding agent)

mkdir -p docs/releases

cat > docs/releases/<YYYY-MM-DD>-release-<X-Y-Z>.md << 'EOF'
<generated content>
EOF

Step 6 — Snapshot and prune Docusaurus versions (coding agent)

After writing the blog post, snapshot the current docs/ tree as the new version and prune old snapshots to stay within the retention policy.

Retention policy:

  • Latest 5 releases from the current minor series (e.g. 0.4.7–0.4.11)
  • Highest release from each previous minor series (e.g. 0.3.11, 0.2.x)

Run from repo root:

NEW_VERSION=<to> node docs/scripts/snapshot-and-prune-versions.js

This script:

  1. Runs docusaurus docs:version <to> — snapshots docs/ into versioned_docs/version-<to>/
  2. Prunes versioned_docs/, versioned_sidebars/, and versions.json to the retention policy
  3. Updates docs/versions-config.json — sets lastVersion, marks <to> as (Latest), removes pruned entries

Commit all release artifacts together:

git add docs/releases/<YYYY-MM-DD>-release-<X-Y-Z>.md
git add docs/versioned_docs/ docs/versioned_sidebars/
git add docs/versions.json docs/versions-config.json
git commit -s -m "docs: release <to> — blog post, docs snapshot, version prune"

Guidelines

Voice and audience

  • Write for end users, not operators or engineers. The release notes section (Highlights, What's New, Bug Fixes) is read by people deciding whether to upgrade and by users discovering new capabilities. The Upgrade Guide section is the only place technical operator details belong.
  • Describe what users can do or what changed for them — not how it was implemented. "Team members can now connect their own Slack channels" is good. "Non-admin users can self-serve integration_panel_modes" is not.
  • Describe bug fixes by the symptom users experienced, not the root cause. "Users were randomly logged out in multi-replica deployments" is good. "Per-pod in-memory token Map replaced with MongoDB-backed L1+L2 store" is not.
  • No internal identifiers in release notes — no API route paths, env var names, function names, internal module names, Helm key paths, or code-level details. Those belong only in the Upgrade Guide if they are operator-actionable.
  • Keep feature bullets short and outcome-focused. One sentence: what you can do now that you couldn't before, or what problem went away.
  • Treat corrected install and upgrade documentation as user-facing. Include it when the old instructions would lead users to the wrong registry, values, credentials, or deployment result.

Natural writing

  • Write the smallest accurate release post. One meaningful change is enough; do not add weak bullets or extra sections to make the post look fuller.
  • Open with what changed and who it affects. Skip throat-clearing, broad claims about the industry, and a closing paragraph that repeats the highlights.
  • Use direct sentences with a clear actor. Prefer "The chart keeps custom resources stable across upgrades" over "Improved stability is provided for custom resources."
  • Prefer concrete verbs and plain connecting words. Avoid filler such as "leverage," "robust," "seamless," "holistic," "comprehensive," and "transformative" when a specific description is available.
  • Do not force groups of three, symmetrical paragraphs, a heading for every paragraph, or a redundant key-takeaways section.
  • Read the draft once as if explaining the release to a teammate. Remove any sentence that does not change an upgrade decision or explain a user-visible result.

Structure and formatting

  • <!-- truncate --> goes immediately after the Highlights section so the blog list shows just the intro paragraph
  • Show concrete before/after YAML for every breaking change in the Upgrade Guide — never prose-only
  • For breaking changes, state the consequence of not updating
  • Keep the upgrade runbook linear — steps should be self-contained
  • If helm show values is unavailable, ask the user to paste output — never guess
  • Highlight environment-specific notes (VM kind clusters use standard storageClass; EKS uses gp2/gp3)
  • For ExternalSecret additions, list the exact Vault path and key the chart now expects
  • Omit chore, ci, test, and refactor commits from user-facing notes
  • If there are zero helm value changes, say so explicitly and reassure it is a drop-in upgrade
  • Do NOT create separate migration guide files — the upgrade guide lives inside the release post
  • Do NOT add a "Personal Impact Analysis" heading or a raw "Full Values Diff" dump. Any values.yaml-specific guidance belongs in the runbook's "Apply values.yaml changes" step; the categorized tables (Breaking/New Optional/Deprecated) already document the diff, so don't also paste the raw diff

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.