From 60d0e09a4b2fab2b63c4e0a743f620c15b5e0105 Mon Sep 17 00:00:00 2001 From: m3tm3re Date: Mon, 27 Apr 2026 10:30:20 +0200 Subject: [PATCH] feat: changelog skill --- .gitignore | 2 + .pi-lens/cache/jscpd.json | 7 - .pi-lens/cache/jscpd.meta.json | 3 - .pi-lens/cache/knip.json | 9 - .pi-lens/cache/knip.meta.json | 3 - .pi-lens/cache/session-start-guidance.json | 1 - .../cache/session-start-guidance.meta.json | 3 - .pi-lens/cache/todo-baseline.json | 18 - .pi-lens/cache/todo-baseline.meta.json | 3 - .pi-lens/cache/turn-end-findings-last.json | 3 - .../cache/turn-end-findings-last.meta.json | 3 - .pi-lens/cache/turn-end-findings.json | 1 - .pi-lens/cache/turn-end-findings.meta.json | 3 - .pi-lens/turn-state.json | 6 - skills/changelog/SKILL.md | 572 ++++++++++++++++++ 15 files changed, 574 insertions(+), 63 deletions(-) delete mode 100644 .pi-lens/cache/jscpd.json delete mode 100644 .pi-lens/cache/jscpd.meta.json delete mode 100644 .pi-lens/cache/knip.json delete mode 100644 .pi-lens/cache/knip.meta.json delete mode 100644 .pi-lens/cache/session-start-guidance.json delete mode 100644 .pi-lens/cache/session-start-guidance.meta.json delete mode 100644 .pi-lens/cache/todo-baseline.json delete mode 100644 .pi-lens/cache/todo-baseline.meta.json delete mode 100644 .pi-lens/cache/turn-end-findings-last.json delete mode 100644 .pi-lens/cache/turn-end-findings-last.meta.json delete mode 100644 .pi-lens/cache/turn-end-findings.json delete mode 100644 .pi-lens/cache/turn-end-findings.meta.json delete mode 100644 .pi-lens/turn-state.json create mode 100644 skills/changelog/SKILL.md diff --git a/.gitignore b/.gitignore index b62007f..ac20f11 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,5 @@ # Nix / direnv .direnv/ result + +.pi* diff --git a/.pi-lens/cache/jscpd.json b/.pi-lens/cache/jscpd.json deleted file mode 100644 index ee25c61..0000000 --- a/.pi-lens/cache/jscpd.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "success": true, - "clones": [], - "duplicatedLines": 0, - "totalLines": 0, - "percentage": 0 -} \ No newline at end of file diff --git a/.pi-lens/cache/jscpd.meta.json b/.pi-lens/cache/jscpd.meta.json deleted file mode 100644 index 7b8bfc4..0000000 --- a/.pi-lens/cache/jscpd.meta.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "timestamp": "2026-04-24T17:57:06.373Z" -} \ No newline at end of file diff --git a/.pi-lens/cache/knip.json b/.pi-lens/cache/knip.json deleted file mode 100644 index a4147c6..0000000 --- a/.pi-lens/cache/knip.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "success": false, - "issues": [], - "unusedExports": [], - "unusedFiles": [], - "unusedDeps": [], - "unlistedDeps": [], - "summary": "Failed to parse output" -} \ No newline at end of file diff --git a/.pi-lens/cache/knip.meta.json b/.pi-lens/cache/knip.meta.json deleted file mode 100644 index 8c94c14..0000000 --- a/.pi-lens/cache/knip.meta.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "timestamp": "2026-04-24T17:57:13.428Z" -} \ No newline at end of file diff --git a/.pi-lens/cache/session-start-guidance.json b/.pi-lens/cache/session-start-guidance.json deleted file mode 100644 index ec747fa..0000000 --- a/.pi-lens/cache/session-start-guidance.json +++ /dev/null @@ -1 +0,0 @@ -null \ No newline at end of file diff --git a/.pi-lens/cache/session-start-guidance.meta.json b/.pi-lens/cache/session-start-guidance.meta.json deleted file mode 100644 index 682c82c..0000000 --- a/.pi-lens/cache/session-start-guidance.meta.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "timestamp": "2026-04-24T17:41:29.302Z" -} \ No newline at end of file diff --git a/.pi-lens/cache/todo-baseline.json b/.pi-lens/cache/todo-baseline.json deleted file mode 100644 index 50015ca..0000000 --- a/.pi-lens/cache/todo-baseline.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "items": [ - { - "type": "TODO", - "message": "Replace with the first main section based on chosen structure]", - "file": "skills/skill-creator/scripts/init_skill.py", - "line": 58, - "column": 4 - }, - { - "type": "TODO", - "message": "Add actual script logic here", - "file": "skills/skill-creator/scripts/init_skill.py", - "line": 120, - "column": 6 - } - ] -} \ No newline at end of file diff --git a/.pi-lens/cache/todo-baseline.meta.json b/.pi-lens/cache/todo-baseline.meta.json deleted file mode 100644 index 8a0b6fe..0000000 --- a/.pi-lens/cache/todo-baseline.meta.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "timestamp": "2026-04-24T17:39:59.334Z" -} \ No newline at end of file diff --git a/.pi-lens/cache/turn-end-findings-last.json b/.pi-lens/cache/turn-end-findings-last.json deleted file mode 100644 index a92b132..0000000 --- a/.pi-lens/cache/turn-end-findings-last.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "signature": "/home/m3tam3re/p/NIX/nixpkgs/modules/home-manager/coding/agents/claude-code.nix::📐 Cascade errors in 1 other file(s) — fix before finishing turn:\n\n line 205, col 10 code=sema-duplicated-attrname: duplicated attrname `file`\n" -} \ No newline at end of file diff --git a/.pi-lens/cache/turn-end-findings-last.meta.json b/.pi-lens/cache/turn-end-findings-last.meta.json deleted file mode 100644 index f07444c..0000000 --- a/.pi-lens/cache/turn-end-findings-last.meta.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "timestamp": "2026-04-11T03:32:45.214Z" -} \ No newline at end of file diff --git a/.pi-lens/cache/turn-end-findings.json b/.pi-lens/cache/turn-end-findings.json deleted file mode 100644 index ec747fa..0000000 --- a/.pi-lens/cache/turn-end-findings.json +++ /dev/null @@ -1 +0,0 @@ -null \ No newline at end of file diff --git a/.pi-lens/cache/turn-end-findings.meta.json b/.pi-lens/cache/turn-end-findings.meta.json deleted file mode 100644 index 82429b5..0000000 --- a/.pi-lens/cache/turn-end-findings.meta.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "timestamp": "2026-04-11T03:33:08.875Z" -} \ No newline at end of file diff --git a/.pi-lens/turn-state.json b/.pi-lens/turn-state.json deleted file mode 100644 index 351b4ed..0000000 --- a/.pi-lens/turn-state.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "files": {}, - "turnCycles": 0, - "maxCycles": 3, - "lastUpdated": "2026-04-24T17:57:13.429Z" -} \ No newline at end of file diff --git a/skills/changelog/SKILL.md b/skills/changelog/SKILL.md new file mode 100644 index 0000000..23e28ca --- /dev/null +++ b/skills/changelog/SKILL.md @@ -0,0 +1,572 @@ +--- +name: changelog +description: Automate changelog generation from commits, PRs, and releases following Keep a Changelog format. Use when setting up release workflows, generating release notes, or standardizing commit conventions. +--- + +# Changelog Automation + +Patterns and tools for automating changelog generation, release notes, and version management following industry standards. + +## When to Use This Skill + +- Setting up automated changelog generation +- Implementing Conventional Commits +- Creating release note workflows +- Standardizing commit message formats +- Generating GitHub/GitLab release notes +- Managing semantic versioning + +## Core Concepts + +### 1. Keep a Changelog Format + +```markdown +# Changelog + +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). + +## [Unreleased] + +### Added + +- New feature X + +## [1.2.0] - 2024-01-15 + +### Added + +- User profile avatars +- Dark mode support + +### Changed + +- Improved loading performance by 40% + +### Deprecated + +- Old authentication API (use v2) + +### Removed + +- Legacy payment gateway + +### Fixed + +- Login timeout issue (#123) + +### Security + +- Updated dependencies for CVE-2024-1234 + +[Unreleased]: https://github.com/user/repo/compare/v1.2.0...HEAD +[1.2.0]: https://github.com/user/repo/compare/v1.1.0...v1.2.0 +``` + +### 2. Conventional Commits + +``` +[optional scope]: + +[optional body] + +[optional footer(s)] +``` + +| Type | Description | Changelog Section | +| ---------- | ---------------- | ------------------ | +| `feat` | New feature | Added | +| `fix` | Bug fix | Fixed | +| `docs` | Documentation | (usually excluded) | +| `style` | Formatting | (usually excluded) | +| `refactor` | Code restructure | Changed | +| `perf` | Performance | Changed | +| `test` | Tests | (usually excluded) | +| `chore` | Maintenance | (usually excluded) | +| `ci` | CI changes | (usually excluded) | +| `build` | Build system | (usually excluded) | +| `revert` | Revert commit | Removed | + +### 3. Semantic Versioning + +``` +MAJOR.MINOR.PATCH + +MAJOR: Breaking changes (feat! or BREAKING CHANGE) +MINOR: New features (feat) +PATCH: Bug fixes (fix) +``` + +## Implementation + +### Method 1: Conventional Changelog (Node.js) + +```bash +# Install tools +npm install -D @commitlint/cli @commitlint/config-conventional +npm install -D husky +npm install -D standard-version +# or +npm install -D semantic-release + +# Setup commitlint +cat > commitlint.config.js << 'EOF' +module.exports = { + extends: ['@commitlint/config-conventional'], + rules: { + 'type-enum': [ + 2, + 'always', + [ + 'feat', + 'fix', + 'docs', + 'style', + 'refactor', + 'perf', + 'test', + 'chore', + 'ci', + 'build', + 'revert', + ], + ], + 'subject-case': [2, 'never', ['start-case', 'pascal-case', 'upper-case']], + 'subject-max-length': [2, 'always', 72], + }, +}; +EOF + +# Setup husky +npx husky init +echo "npx --no -- commitlint --edit \$1" > .husky/commit-msg +``` + +### Method 2: standard-version Configuration + +```javascript +// .versionrc.js +module.exports = { + types: [ + { type: "feat", section: "Features" }, + { type: "fix", section: "Bug Fixes" }, + { type: "perf", section: "Performance Improvements" }, + { type: "revert", section: "Reverts" }, + { type: "docs", section: "Documentation", hidden: true }, + { type: "style", section: "Styles", hidden: true }, + { type: "chore", section: "Miscellaneous", hidden: true }, + { type: "refactor", section: "Code Refactoring", hidden: true }, + { type: "test", section: "Tests", hidden: true }, + { type: "build", section: "Build System", hidden: true }, + { type: "ci", section: "CI/CD", hidden: true }, + ], + commitUrlFormat: "{{host}}/{{owner}}/{{repository}}/commit/{{hash}}", + compareUrlFormat: + "{{host}}/{{owner}}/{{repository}}/compare/{{previousTag}}...{{currentTag}}", + issueUrlFormat: "{{host}}/{{owner}}/{{repository}}/issues/{{id}}", + userUrlFormat: "{{host}}/{{user}}", + releaseCommitMessageFormat: "chore(release): {{currentTag}}", + scripts: { + prebump: 'echo "Running prebump"', + postbump: 'echo "Running postbump"', + prechangelog: 'echo "Running prechangelog"', + postchangelog: 'echo "Running postchangelog"', + }, +}; +``` + +```json +// package.json scripts +{ + "scripts": { + "release": "standard-version", + "release:minor": "standard-version --release-as minor", + "release:major": "standard-version --release-as major", + "release:patch": "standard-version --release-as patch", + "release:dry": "standard-version --dry-run" + } +} +``` + +### Method 3: semantic-release (Full Automation) + +```javascript +// release.config.js +module.exports = { + branches: [ + "main", + { name: "beta", prerelease: true }, + { name: "alpha", prerelease: true }, + ], + plugins: [ + "@semantic-release/commit-analyzer", + "@semantic-release/release-notes-generator", + [ + "@semantic-release/changelog", + { + changelogFile: "CHANGELOG.md", + }, + ], + [ + "@semantic-release/npm", + { + npmPublish: true, + }, + ], + [ + "@semantic-release/github", + { + assets: ["dist/**/*.js", "dist/**/*.css"], + }, + ], + [ + "@semantic-release/git", + { + assets: ["CHANGELOG.md", "package.json"], + message: + "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}", + }, + ], + ], +}; +``` + +### Method 4: GitHub Actions Workflow + +```yaml +# .github/workflows/release.yml +name: Release + +on: + push: + branches: [main] + workflow_dispatch: + inputs: + release_type: + description: "Release type" + required: true + default: "patch" + type: choice + options: + - patch + - minor + - major + +permissions: + contents: write + pull-requests: write + +jobs: + release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.GITHUB_TOKEN }} + + - uses: actions/setup-node@v4 + with: + node-version: "20" + cache: "npm" + + - run: npm ci + + - name: Configure Git + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + - name: Run semantic-release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + run: npx semantic-release + + # Alternative: manual release with standard-version + manual-release: + if: github.event_name == 'workflow_dispatch' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - uses: actions/setup-node@v4 + with: + node-version: "20" + + - run: npm ci + + - name: Configure Git + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + - name: Bump version and generate changelog + run: npx standard-version --release-as ${{ inputs.release_type }} + + - name: Push changes + run: git push --follow-tags origin main + + - name: Create GitHub Release + uses: softprops/action-gh-release@v1 + with: + tag_name: ${{ steps.version.outputs.tag }} + body_path: RELEASE_NOTES.md + generate_release_notes: true +``` + +### Method 5: git-cliff (Rust-based, Fast) + +```toml +# cliff.toml +[changelog] +header = """ +# Changelog + +All notable changes to this project will be documented in this file. + +""" +body = """ +{% if version %}\ + ## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }} +{% else %}\ + ## [Unreleased] +{% endif %}\ +{% for group, commits in commits | group_by(attribute="group") %} + ### {{ group | upper_first }} + {% for commit in commits %} + - {% if commit.scope %}**{{ commit.scope }}:** {% endif %}\ + {{ commit.message | upper_first }}\ + {% if commit.github.pr_number %} ([#{{ commit.github.pr_number }}](https://github.com/owner/repo/pull/{{ commit.github.pr_number }})){% endif %}\ + {% endfor %} +{% endfor %} +""" +footer = """ +{% for release in releases -%} + {% if release.version -%} + {% if release.previous.version -%} + [{{ release.version | trim_start_matches(pat="v") }}]: \ + https://github.com/owner/repo/compare/{{ release.previous.version }}...{{ release.version }} + {% endif -%} + {% else -%} + [unreleased]: https://github.com/owner/repo/compare/{{ release.previous.version }}...HEAD + {% endif -%} +{% endfor %} +""" +trim = true + +[git] +conventional_commits = true +filter_unconventional = true +split_commits = false +commit_parsers = [ + { message = "^feat", group = "Features" }, + { message = "^fix", group = "Bug Fixes" }, + { message = "^doc", group = "Documentation" }, + { message = "^perf", group = "Performance" }, + { message = "^refactor", group = "Refactoring" }, + { message = "^style", group = "Styling" }, + { message = "^test", group = "Testing" }, + { message = "^chore\\(release\\)", skip = true }, + { message = "^chore", group = "Miscellaneous" }, +] +filter_commits = false +tag_pattern = "v[0-9]*" +skip_tags = "" +ignore_tags = "" +topo_order = false +sort_commits = "oldest" + +[github] +owner = "owner" +repo = "repo" +``` + +```bash +# Generate changelog +git cliff -o CHANGELOG.md + +# Generate for specific range +git cliff v1.0.0..v2.0.0 -o RELEASE_NOTES.md + +# Preview without writing +git cliff --unreleased --dry-run +``` + +### Method 6: Python (commitizen) + +```toml +# pyproject.toml +[tool.commitizen] +name = "cz_conventional_commits" +version = "1.0.0" +version_files = [ + "pyproject.toml:version", + "src/__init__.py:__version__", +] +tag_format = "v$version" +update_changelog_on_bump = true +changelog_incremental = true +changelog_start_rev = "v0.1.0" + +[tool.commitizen.customize] +message_template = "{{change_type}}{% if scope %}({{scope}}){% endif %}: {{message}}" +schema = "(): " +schema_pattern = "^(feat|fix|docs|style|refactor|perf|test|chore)(\\(\\w+\\))?:\\s.*" +bump_pattern = "^(feat|fix|perf|refactor)" +bump_map = {"feat" = "MINOR", "fix" = "PATCH", "perf" = "PATCH", "refactor" = "PATCH"} +``` + +```bash +# Install +pip install commitizen + +# Create commit interactively +cz commit + +# Bump version and update changelog +cz bump --changelog + +# Check commits +cz check --rev-range HEAD~5..HEAD +``` + +## Release Notes Templates + +### GitHub Release Template + +```markdown +## What's Changed + +### 🚀 Features + +{{ range .Features }} + +- {{ .Title }} by @{{ .Author }} in #{{ .PR }} + {{ end }} + +### 🐛 Bug Fixes + +{{ range .Fixes }} + +- {{ .Title }} by @{{ .Author }} in #{{ .PR }} + {{ end }} + +### 📚 Documentation + +{{ range .Docs }} + +- {{ .Title }} by @{{ .Author }} in #{{ .PR }} + {{ end }} + +### 🔧 Maintenance + +{{ range .Chores }} + +- {{ .Title }} by @{{ .Author }} in #{{ .PR }} + {{ end }} + +## New Contributors + +{{ range .NewContributors }} + +- @{{ .Username }} made their first contribution in #{{ .PR }} + {{ end }} + +**Full Changelog**: https://github.com/owner/repo/compare/v{{ .Previous }}...v{{ .Current }} +``` + +### Internal Release Notes + +```markdown +# Release v2.1.0 - January 15, 2024 + +## Summary + +This release introduces dark mode support and improves checkout performance +by 40%. It also includes important security updates. + +## Highlights + +### 🌙 Dark Mode + +Users can now switch to dark mode from settings. The preference is +automatically saved and synced across devices. + +### ⚡ Performance + +- Checkout flow is 40% faster +- Reduced bundle size by 15% + +## Breaking Changes + +None in this release. + +## Upgrade Guide + +No special steps required. Standard deployment process applies. + +## Known Issues + +- Dark mode may flicker on initial load (fix scheduled for v2.1.1) + +## Dependencies Updated + +| Package | From | To | Reason | +| ------- | ------- | ------- | ------------------------ | +| react | 18.2.0 | 18.3.0 | Performance improvements | +| lodash | 4.17.20 | 4.17.21 | Security patch | +``` + +## Commit Message Examples + +```bash +# Feature with scope +feat(auth): add OAuth2 support for Google login + +# Bug fix with issue reference +fix(checkout): resolve race condition in payment processing + +Closes #123 + +# Breaking change +feat(api)!: change user endpoint response format + +BREAKING CHANGE: The user endpoint now returns `userId` instead of `id`. +Migration guide: Update all API consumers to use the new field name. + +# Multiple paragraphs +fix(database): handle connection timeouts gracefully + +Previously, connection timeouts would cause the entire request to fail +without retry. This change implements exponential backoff with up to +3 retries before failing. + +The timeout threshold has been increased from 5s to 10s based on p99 +latency analysis. + +Fixes #456 +Reviewed-by: @alice +``` + +## Best Practices + +### Do's + +- **Follow Conventional Commits** - Enables automation +- **Write clear messages** - Future you will thank you +- **Reference issues** - Link commits to tickets +- **Use scopes consistently** - Define team conventions +- **Automate releases** - Reduce manual errors + +### Don'ts + +- **Don't mix changes** - One logical change per commit +- **Don't skip validation** - Use commitlint +- **Don't manual edit** - Generated changelogs only +- **Don't forget breaking changes** - Mark with `!` or footer +- **Don't ignore CI** - Validate commits in pipeline