Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .agents/skills/changelog/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: changelog
description: Maintain and update CHANGELOG.md using Keep a Changelog 1.1.0 conventions with SemVer-friendly release sections, Unreleased workflow, and consistent change categorization.
description: Maintain and update CHANGELOG.md using Keep a Changelog 1.1.0 conventions with CalVer release sections, Unreleased workflow, and consistent change categorization.
metadata:
short-description: Keep a Changelog workflow
---
Expand All @@ -16,7 +16,7 @@ Use this skill when the user asks to create, update, normalize, or release `CHAN
- Use reverse chronological order.
- Keep an `[Unreleased]` section at the top.
- Use ISO dates: `YYYY-MM-DD`.
- Follow SemVer version headers: `## [x.y.z] - YYYY-MM-DD`.
- Follow this repository's CalVer version headers: `## [YYYY.M.PATCH] - YYYY-MM-DD`.

## Allowed Change Types

Expand Down Expand Up @@ -68,14 +68,14 @@ Use these sections when needed (omit empty ones):
All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
and this project uses [Calendar Versioning](https://calver.org/) with the `YYYY.M.PATCH` scheme for new releases.

## [Unreleased]

### Added
- ...

## [1.2.3] - 2026-04-26
## [2026.5.1] - 2026-04-26

### Fixed
- ...
Expand Down
149 changes: 149 additions & 0 deletions .agents/skills/save-it-release/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
---
name: save-it-release
description: Prepare, verify, and publish `save_it` releases by updating `CHANGELOG.md` and `mix.exs`, creating the release commit and tag, and publishing a GitHub release with notes extracted from the changelog. Use when the user asks to cut a stable release, prepare a prerelease, or verify release readiness for this repository. This repository uses CalVer `YYYY.M.PATCH` and prerelease tags such as `YYYY.M.PATCH-rc.N`.
---

# Save It Release

Use this skill when the task is specifically about the `save_it` release flow.

This repository uses:
- `CHANGELOG.md` as the source of release notes
- `mix.exs` `version` as the application version
- CalVer `YYYY.M.PATCH` for stable versions, for example `2026.5.1`
- git tags that match the version string directly, for example `2026.5.1`
- GitHub Release publication to trigger `.github/workflows/release.yml`
- `.github/workflows/release-manual.yml` for manual prereleases such as `2026.5.2-rc.1`

## Workflow

1. Read the current release state.
2. Decide whether this is release preparation, stable release publication, or manual prerelease publication.
3. Align `CHANGELOG.md` and `mix.exs`.
4. Verify release notes and git state.
5. Execute the matching release path.
6. Report the exact tag, commit, release URL, and workflow status.

## Preflight

Run:

```bash
git fetch --tags --prune
git status --short --branch
git tag --sort=-version:refname | sed -n '1,20p'
```

Rules:
- Prefer cutting stable releases from `main`.
- If the tree is dirty, stop and surface the changed files before continuing.
- Check whether the target stable tag or GitHub release already exists before creating anything.

Use the helper script for a quick snapshot:

```bash
.agents/skills/save-it-release/scripts/check_release_state.sh YYYY.M.PATCH
```

## Release Preparation

When the user asks to prepare a release but not publish it yet:

1. Update `CHANGELOG.md`.
- Keep `[Unreleased]` at the top.
- Move shipped items into `## [YYYY.M.PATCH] - YYYY-MM-DD`.
- Add the compare link for the new version.
- Keep entries user-facing and in English.
2. Update `mix.exs`:

```elixir
version: "YYYY.M.PATCH"
```

3. Show the diff for `CHANGELOG.md` and `mix.exs`.
4. Do not tag or publish unless the user explicitly asks to release.

If changelog drafting is still needed, also use `.agents/skills/changelog/SKILL.md`.

## Stable Release Publication

When the user asks to publish a stable release:

1. Confirm the released version exists in both `CHANGELOG.md` and `mix.exs`.
2. Extract release notes with:

```bash
.agents/skills/save-it-release/scripts/extract_release_notes.sh YYYY.M.PATCH
```

3. Commit release metadata changes using the repository convention:

```bash
git add CHANGELOG.md mix.exs
git commit -m "chore(release): bump version to YYYY.M.PATCH"
```

4. Create and push the stable tag:

```bash
git tag -a YYYY.M.PATCH -m "YYYY.M.PATCH"
git push origin main
git push origin refs/tags/YYYY.M.PATCH
```

5. Publish the GitHub release from the extracted notes:

```bash
tmpfile="$(mktemp)"
.agents/skills/save-it-release/scripts/extract_release_notes.sh YYYY.M.PATCH > "$tmpfile"
gh release create YYYY.M.PATCH \
--verify-tag \
--title "save_it YYYY.M.PATCH" \
--notes-file "$tmpfile"
rm -f "$tmpfile"
```

6. Check whether the `Release` workflow was triggered:

```bash
gh run list --limit 5
```

If the user wants more confidence before release, run the acceptance flow from `.agents/skills/acceptance-testing/SKILL.md`.

## Manual Prerelease Publication

When the user asks for a prerelease:

1. Keep the version in the repository's CalVer prerelease form, for example `2026.5.2-rc.1`.
2. Prefer the existing GitHub Actions workflow instead of manually crafting a prerelease:

```bash
gh workflow run "Release (manual)" -f tag=YYYY.M.PATCH-rc.N
```

3. This workflow publishes a GitHub prerelease and triggers Docker publish with prerelease semantics.

## Guardrails

- Never publish a stable release from a dirty working tree.
- Never create a stable release if `mix.exs` and `CHANGELOG.md` disagree on the version.
- Never use a non-CalVer stable version format in this repository unless the project convention is explicitly changed again.
- Never add a `v` prefix to new release tags in this repository.
- Never invent release notes from raw commit history when the matching changelog section is missing.
- Never recreate an existing tag or GitHub release.
- Never use the manual prerelease workflow for a normal stable release when direct GitHub release publication is intended.

## Related Files

- `CHANGELOG.md`
- `mix.exs`
- `.github/workflows/release.yml`
- `.github/workflows/release-manual.yml`
- `.agents/skills/changelog/SKILL.md`
- `.agents/skills/acceptance-testing/SKILL.md`

## Resources

- `scripts/extract_release_notes.sh`
- `scripts/check_release_state.sh`
4 changes: 4 additions & 0 deletions .agents/skills/save-it-release/agents/openai.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
interface:
display_name: "Save It Release"
short_description: "Prepare and publish save_it releases"
default_prompt: "Use this skill to prepare and publish a save_it release safely."
40 changes: 40 additions & 0 deletions .agents/skills/save-it-release/scripts/check_release_state.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/usr/bin/env bash

set -euo pipefail

if [ "$#" -ne 1 ]; then
echo "usage: $0 <version>" >&2
exit 1
fi

version="$1"
tag="${version}"
branch="$(git branch --show-current)"

echo "branch=${branch}"
echo "tag=${tag}"
echo "head=$(git rev-parse --short HEAD)"

echo
echo "[git status]"
git status --short --branch

echo
echo "[mix.exs version]"
rg -n "version:\\s*\"${version}\"" mix.exs || true

echo
echo "[changelog section]"
rg -n "^## \\[${version}\\] - " CHANGELOG.md || true

echo
echo "[local tag]"
git rev-parse --verify "${tag}" >/dev/null 2>&1 && echo "exists" || echo "missing"

echo
echo "[remote tag]"
git ls-remote --tags origin "refs/tags/${tag}" | sed '/^$/d' || true

echo
echo "[github release]"
gh release view "${tag}" --json url,isDraft,isPrerelease,publishedAt --jq '{url, isDraft, isPrerelease, publishedAt}' 2>/dev/null || echo "missing"
16 changes: 16 additions & 0 deletions .agents/skills/save-it-release/scripts/extract_release_notes.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/usr/bin/env bash

set -euo pipefail

if [ "$#" -ne 1 ]; then
echo "usage: $0 <version>" >&2
exit 1
fi

version="$1"

awk -v version="$version" '
$0 ~ "^## \\[" version "\\]" { in_section=1; next }
in_section && /^## \[/ { exit }
in_section { print }
' CHANGELOG.md
10 changes: 6 additions & 4 deletions .github/workflows/release-manual.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ on:
workflow_dispatch:
inputs:
tag:
description: "Release tag to create (for example: v0.4.1)"
description: "Release tag to create (for example: 2026.5.1 or 2026.5.2-rc.1)"
required: true
type: string

Expand All @@ -18,6 +18,7 @@ concurrency:

jobs:
release:
name: release (${{ inputs.tag }})
runs-on: ubuntu-latest
outputs:
version: ${{ steps.prepare.outputs.version }}
Expand All @@ -31,7 +32,7 @@ jobs:
env:
INPUT_TAG: ${{ inputs.tag }}
run: |
echo "version=${INPUT_TAG#v}" >> "$GITHUB_OUTPUT"
echo "version=${INPUT_TAG}" >> "$GITHUB_OUTPUT"

- name: Ensure GitHub CLI
run: gh --version
Expand All @@ -42,7 +43,7 @@ jobs:
RELEASE_BRANCH: ${{ github.ref_name }}
INPUT_TAG: ${{ inputs.tag }}
run: |
version="${INPUT_TAG#v}"
version="${INPUT_TAG}"

awk -v version="$version" '
$0 ~ "^## \\[" version "\\]" { next_section=1; next }
Expand All @@ -56,11 +57,12 @@ jobs:

gh release create "$INPUT_TAG" \
--target "$RELEASE_BRANCH" \
--title "$INPUT_TAG" \
--title "save_it $INPUT_TAG" \
--notes-file release-notes.md \
--prerelease

docker:
name: docker (${{ needs.release.outputs.version }})
needs: release
uses: ./.github/workflows/docker-publish.yml
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
IS_PRERELEASE: ${{ github.event.release.prerelease }}
RELEASE_TAG: ${{ github.event.release.tag_name }}
run: |
version="${RELEASE_TAG#v}"
version="${RELEASE_TAG}"
if [ -z "$version" ]; then
echo "Release tag is empty"
exit 1
Expand Down
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ This file provides guidance to coding agents working in this repository.
- Project: `save_it`
- Stack: Elixir (Telegram bot), Docker, external downloader/search services
- Primary goal: ship practical features quickly with controlled complexity
- Versioning: CalVer `YYYY.M.PATCH` for stable releases, with git tags using the same value without a `v` prefix, and prereleases such as `YYYY.M.PATCH-rc.N`

## Environment and Tooling

Expand Down
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
and this project uses [Calendar Versioning](https://calver.org/) with the `YYYY.M.PATCH` scheme for new releases.

## [Unreleased]

Expand Down
Loading