mirror of
https://github.com/magnus919/agent-skills.git
synced 2026-09-11 19:47:12 +03:00
chore(main): release 0.6.0 (#163)
* chore(main): release 0.6.0 * fix(release-engineering): align validators with release tooling --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Magnus Hedemark <magnus919@pm.me>
This commit is contained in:
co-authored by
github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Magnus Hedemark
parent
a57c96a9d5
commit
22ee6494b1
@@ -1,3 +1,3 @@
|
||||
{
|
||||
".": "0.5.0"
|
||||
".": "0.6.0"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,101 @@
|
||||
# Changelog
|
||||
|
||||
## [0.6.0](https://github.com/magnus919/agent-skills/compare/v0.5.0...v0.6.0) (2026-08-03)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add CNCF Landscape technology selection skill ([622f341](https://github.com/magnus919/agent-skills/commit/622f341ea467616174592e036c5d3fa8f121ae03))
|
||||
* add comic chat PNG renderer skill ([2494a66](https://github.com/magnus919/agent-skills/commit/2494a663952f32d5807f900804bafc05aa417352))
|
||||
* add lightweight test-hardening path to neckbeard ([#230](https://github.com/magnus919/agent-skills/issues/230)) ([36d3fa8](https://github.com/magnus919/agent-skills/commit/36d3fa837e928951aa17bfc7ec4dc772f47becc6))
|
||||
* **agent-production-operations:** add agent production operations bundle ([#229](https://github.com/magnus919/agent-skills/issues/229)) ([ac1ad5d](https://github.com/magnus919/agent-skills/commit/ac1ad5dbd905fe8de6ea3298896b56d845f30fc7)), closes [#201](https://github.com/magnus919/agent-skills/issues/201)
|
||||
* binary-analysis skill with Ghidra backend ([0d4a365](https://github.com/magnus919/agent-skills/commit/0d4a3652e4ccb3c25869f5baca52a29f08ddbf44))
|
||||
* **binary-analysis:** implement CLI skeleton with argparse, JSON envelope, and exit codes ([e9397bb](https://github.com/magnus919/agent-skills/commit/e9397bbb542b195e6c9741805bad491a13ff9ef5))
|
||||
* **bundles:** define bundle manifests and lifecycle capability matrix ([#203](https://github.com/magnus919/agent-skills/issues/203)) ([#231](https://github.com/magnus919/agent-skills/issues/231)) ([aa893e3](https://github.com/magnus919/agent-skills/commit/aa893e3ec20594da4982f645a31b2675f0abdcf8))
|
||||
* **capacity-and-cost-engineering:** add capacity-and-cost-engineering skill ([#199](https://github.com/magnus919/agent-skills/issues/199)) ([#224](https://github.com/magnus919/agent-skills/issues/224)) ([a471888](https://github.com/magnus919/agent-skills/commit/a4718886761af0f90438cfd7c14f2460f4dfff89))
|
||||
* **ci:** add linting, formatting, coverage, and security configs ([476d7e1](https://github.com/magnus919/agent-skills/commit/476d7e11b02f2bee65a2368adff02d9366376791))
|
||||
* **ci:** add mypy, radon, and deptry to CI pipeline ([bfe05ef](https://github.com/magnus919/agent-skills/commit/bfe05ef18aed5f90e17b2da4b725d1a4d565bfe1))
|
||||
* **conditional-customer-success:** add conditional customer success skill ([#192](https://github.com/magnus919/agent-skills/issues/192)) ([#218](https://github.com/magnus919/agent-skills/issues/218)) ([1dd564e](https://github.com/magnus919/agent-skills/commit/1dd564e3d9eb8d73129332658d8b7504beeb0f89))
|
||||
* **decompile:** implement decompile command with pseudocode, address map, and diagnostics ([3e4f07a](https://github.com/magnus919/agent-skills/commit/3e4f07a34cf14550802005c111f91eb76aa710b9))
|
||||
* **doctor-bootstrap:** implement doctor, bootstrap, and version commands ([55c1451](https://github.com/magnus919/agent-skills/commit/55c145185fd88d51267f5fa776d67207546fd874))
|
||||
* **domain-foundation:** implement canonical domain model with entities, enums, schemas, errors, and selectors ([3481663](https://github.com/magnus919/agent-skills/commit/3481663595a097a8cb5b1d9fa87db74024ff7813))
|
||||
* **fake-backend:** implement FakeAdapter with controllable backend testing ([6184673](https://github.com/magnus919/agent-skills/commit/6184673f3585da829d5b64feaba1a6154f16ace4))
|
||||
* fix remaining agent readiness signals for level 5 ([865a1e9](https://github.com/magnus919/agent-skills/commit/865a1e90c6bb6bdb23c2b182be2fddbf26fd0c17))
|
||||
* **fix-coverage-config:** add .coveragerc with placeholder module omissions and exclude plain-text output helpers ([86b248e](https://github.com/magnus919/agent-skills/commit/86b248e89a2425fdff520be48eb6aa042f4c6579))
|
||||
* **fix-fake-adapter-env:** add BINARY_FAKE_* env var support to FakeAdapter ([c408259](https://github.com/magnus919/agent-skills/commit/c408259a7269da8528c250961e6f52b0875df66b))
|
||||
* **fix-missing-tests:** add register_binary(), clamp warnings in JSON envelope, and new tests ([50e48de](https://github.com/magnus919/agent-skills/commit/50e48deeb7b318b630a6fe4f645e9a34de176246))
|
||||
* **function-queries:** implement functions, disassemble, and bytes CLI commands ([3cf347b](https://github.com/magnus919/agent-skills/commit/3cf347b06035f6651585686966d867e43e19a5d7))
|
||||
* **ghidra-adapter:** implement GhidraAdapter skeleton with PyGhidra bridge ([9e8234f](https://github.com/magnus919/agent-skills/commit/9e8234f70f8df1d77b6ca6484f6942bc42f4739e))
|
||||
* **implementation-planning:** add implementation planning skill ([#217](https://github.com/magnus919/agent-skills/issues/217)) ([f82515e](https://github.com/magnus919/agent-skills/commit/f82515e85d6620e962a93d6341be9d0474b83215)), closes [#186](https://github.com/magnus919/agent-skills/issues/186)
|
||||
* **import-analyze:** implement binary import, analyze, and metadata commands ([f4e254a](https://github.com/magnus919/agent-skills/commit/f4e254ac6703005fcdb702b63aa64dbaaaa0dfa4))
|
||||
* improve agent readiness with dev tooling, CI checks, and tests ([6b44d6f](https://github.com/magnus919/agent-skills/commit/6b44d6f490481de100667d900066024f88deafe3))
|
||||
* **incident-learning:** add incident-learning skill ([#226](https://github.com/magnus919/agent-skills/issues/226)) ([4f14ce3](https://github.com/magnus919/agent-skills/commit/4f14ce3df6e447848392dd477de13a9b5531c7d8)), closes [#200](https://github.com/magnus919/agent-skills/issues/200)
|
||||
* **json-contracts:** implement JSON contract consistency across all commands ([801a5be](https://github.com/magnus919/agent-skills/commit/801a5be65f2478dd8a04677be1c0f7a90093cd75))
|
||||
* **migration-engineering:** add migration-engineering skill ([#222](https://github.com/magnus919/agent-skills/issues/222)) ([652521a](https://github.com/magnus919/agent-skills/commit/652521a09e16f222ada2a74ce6a7ed760396dc91))
|
||||
* **neckbeard:** issue-to-PR delivery workflow ([#181](https://github.com/magnus919/agent-skills/issues/181)-[#185](https://github.com/magnus919/agent-skills/issues/185)) ([#208](https://github.com/magnus919/agent-skills/issues/208)) ([4a4958b](https://github.com/magnus919/agent-skills/commit/4a4958b6761bcdb4382770e4096b92f5a644fcf7))
|
||||
* **privacy-engineering:** add privacy-engineering skill ([#202](https://github.com/magnus919/agent-skills/issues/202)) ([#225](https://github.com/magnus919/agent-skills/issues/225)) ([6f429a9](https://github.com/magnus919/agent-skills/commit/6f429a91b1a41505c512fe529dd10d67f3b141eb))
|
||||
* **product-adoption:** add product adoption skill ([#214](https://github.com/magnus919/agent-skills/issues/214)) ([11a6595](https://github.com/magnus919/agent-skills/commit/11a6595d1ca9539fb97e118fdd17fb5026788905))
|
||||
* **product-analytics-and-measurement:** add product analytics and measurement skill ([#213](https://github.com/magnus919/agent-skills/issues/213)) ([6b650b7](https://github.com/magnus919/agent-skills/commit/6b650b722c2657a45c2f97630bca9ca72e687fcf))
|
||||
* **product-experimentation:** add product experimentation skill ([#212](https://github.com/magnus919/agent-skills/issues/212)) ([0b32a96](https://github.com/magnus919/agent-skills/commit/0b32a96521e72b21fa5a387da271f19365ce8c0f))
|
||||
* **product-lifecycle-learning:** add product lifecycle learning skill ([#194](https://github.com/magnus919/agent-skills/issues/194)) ([#219](https://github.com/magnus919/agent-skills/issues/219)) ([2c247a1](https://github.com/magnus919/agent-skills/commit/2c247a17473edce9b41ccd90f59f01e42d22a7ca))
|
||||
* **product-lifecycle:** add thin product-lifecycle bundle ([#227](https://github.com/magnus919/agent-skills/issues/227)) ([46b92aa](https://github.com/magnus919/agent-skills/commit/46b92aa489891e45be0bf3afe3d69021394c1737)), closes [#187](https://github.com/magnus919/agent-skills/issues/187)
|
||||
* **product-operations-and-governance:** add product operations and governance skill ([#216](https://github.com/magnus919/agent-skills/issues/216)) ([7756266](https://github.com/magnus919/agent-skills/commit/77562664b87cb3d556e154600735b5a1eb863a95)), closes [#193](https://github.com/magnus919/agent-skills/issues/193)
|
||||
* **product-roadmapping-and-portfolio:** add product roadmapping and portfolio skill ([#215](https://github.com/magnus919/agent-skills/issues/215)) ([5d95dd6](https://github.com/magnus919/agent-skills/commit/5d95dd6a303303244af42ca821e998a4454efbd3)), closes [#189](https://github.com/magnus919/agent-skills/issues/189)
|
||||
* **production-excellence:** add thin production-excellence bundle ([#228](https://github.com/magnus919/agent-skills/issues/228)) ([8c05a07](https://github.com/magnus919/agent-skills/commit/8c05a076bb1a29700bdadc246f2bf7a93faff34c))
|
||||
* **production-readiness:** add production-readiness skill ([#221](https://github.com/magnus919/agent-skills/issues/221)) ([2183c22](https://github.com/magnus919/agent-skills/commit/2183c221352a939636c278b54e10087b6fe31aa9))
|
||||
* **project-lifecycle:** implement all project lifecycle commands and state machine ([756b50e](https://github.com/magnus919/agent-skills/commit/756b50e285cfa038de4731aeb6204b737885804a))
|
||||
* **project-system:** implement workspace, manifest, locking, and cache ([defe46c](https://github.com/magnus919/agent-skills/commit/defe46c1386d4c518318e95ba557a2ad96f74a33))
|
||||
* **qa-methodology:** add 2 stdlib-only CLI scripts and colocated pytest suite ([974fde0](https://github.com/magnus919/agent-skills/commit/974fde017cf6760d491caec7f4c0c79bb1b54b04))
|
||||
* **qa-methodology:** add 3 new traditional QA references ([ff69b09](https://github.com/magnus919/agent-skills/commit/ff69b0982f036543392352c635ecbefff78893da))
|
||||
* **qa-methodology:** add 5 fillable templates and 3 assets ([3325787](https://github.com/magnus919/agent-skills/commit/332578766db926695a31adc24060aa6d0665abe8))
|
||||
* **qa-methodology:** add modern agentic references (ai-code-quality-gates, agentic-eval-design) ([aa8c027](https://github.com/magnus919/agent-skills/commit/aa8c027a6e2d0ed8fba3af93f3bd7ce6dfe1e3de))
|
||||
* **qa-methodology:** add modern QA career levels and SDET engineering references ([9b10ff5](https://github.com/magnus919/agent-skills/commit/9b10ff546ae968b6df9909ae6f7192c148543d33))
|
||||
* **qa-methodology:** add mutation-guided test hardening evidence workflow ([8bd042e](https://github.com/magnus919/agent-skills/commit/8bd042eae5a851419c3f6324e4709eb894a8e36f)), closes [#209](https://github.com/magnus919/agent-skills/issues/209)
|
||||
* **qa-methodology:** add schema-v1 evals with 7 output-quality cases ([107d6d1](https://github.com/magnus919/agent-skills/commit/107d6d11631f70e957b16605ca0bdf4a098e833d))
|
||||
* **qa-methodology:** rebuild as thin-index QA/SDET skill bundle ([726de89](https://github.com/magnus919/agent-skills/commit/726de898e8d8b81b9cfb2a13902f38d0cf8c63a0))
|
||||
* **qa-methodology:** rebuild SKILL.md as thin index and rewrite README.md ([8b0220b](https://github.com/magnus919/agent-skills/commit/8b0220b75b62907e9c954cc7dc60584ba077b616))
|
||||
* **qa-methodology:** refresh 5 traditional QA support references ([5bad13a](https://github.com/magnus919/agent-skills/commit/5bad13af568567529071f65d4cd756ac8492a1c8))
|
||||
* **qa-methodology:** refresh traditional QA core references and split monolithic file ([966edcf](https://github.com/magnus919/agent-skills/commit/966edcf0c75e2eb64f4320e1f455d64776928ba5))
|
||||
* **reference-queries:** implement xrefs, callers, callees, and callgraph CLI commands ([93b0431](https://github.com/magnus919/agent-skills/commit/93b04315a9cdfe987d7390aff947aae5df59dd4d))
|
||||
* **release-engineering:** add release engineering skill bundle ([818d8ca](https://github.com/magnus919/agent-skills/commit/818d8cafa2b435b1556fdafa8603aa70f39cf01d))
|
||||
* **reporting:** implement export-report and audit commands ([010a308](https://github.com/magnus919/agent-skills/commit/010a3086aa373afc82edb4a0947ee8cfee16be4a))
|
||||
* **resilience-and-recovery:** add resilience-and-recovery skill ([#223](https://github.com/magnus919/agent-skills/issues/223)) ([c032580](https://github.com/magnus919/agent-skills/commit/c032580197f2f370d4f96895fafc09b36c21f4dd))
|
||||
* **safety-hardening:** implement path security, output limits, memory limits, and report containment ([e62cf47](https://github.com/magnus919/agent-skills/commit/e62cf47a9b2b01905bfbf0864be7fe13365c7908))
|
||||
* **search-trace:** implement search and trace commands with cross-area integration flows ([1ead735](https://github.com/magnus919/agent-skills/commit/1ead735513a00bfb3b8dc5a93a82cfb074e30072))
|
||||
* **security-rules:** implement suspicious-apis and capability-map commands ([d005b9a](https://github.com/magnus919/agent-skills/commit/d005b9aadaa2e7404d4718a7a55877a40c000f20))
|
||||
* **skill-content:** write SKILL.md and README.md for binary-analysis skill ([72d8462](https://github.com/magnus919/agent-skills/commit/72d8462f073cb20cdeb8dc6b48c08c9515bfc431))
|
||||
* **skill-evals:** write 6 eval cases for binary-analysis skill ([f79124d](https://github.com/magnus919/agent-skills/commit/f79124d360ae4212816bf595a7ccff9425252a90))
|
||||
* **skill-references:** write 11 reference files for binary-analysis skill ([a799e0f](https://github.com/magnus919/agent-skills/commit/a799e0f7eb46d48867f0ca9cff5b94c0b22d21f7))
|
||||
* **structural-queries:** implement sections, entrypoints, imports, exports, symbols, and strings CLI commands ([7df699b](https://github.com/magnus919/agent-skills/commit/7df699ba20d94d09479104caafbad403962269db))
|
||||
* **triage-diagnostics:** implement triage and diagnostics commands ([0e05960](https://github.com/magnus919/agent-skills/commit/0e05960dd6c53ffa2b07b929469ffa5a22c61ec8))
|
||||
* **worker:** implement optional local worker with start/stop/status commands and one-shot fallback ([5e8f1d3](https://github.com/magnus919/agent-skills/commit/5e8f1d3aafbb5f06a2aa7898cd16a4d390db7012))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **ci:** add binary-analysis to deptry extend_exclude ([8ea4053](https://github.com/magnus919/agent-skills/commit/8ea4053e01826008582b9e942fdecae7c3932361))
|
||||
* **ci:** add sys.path setup in test __init__.py for unittest discover ([4c7f5c4](https://github.com/magnus919/agent-skills/commit/4c7f5c42f49cdc9eba4c537a47f6fe2352b20ded))
|
||||
* **ci:** add sys.path setup to all test sub-package __init__.py files ([f9354df](https://github.com/magnus919/agent-skills/commit/f9354df2870a97fe85d15e66ad1df1de94afc3f7))
|
||||
* **ci:** add sys.path setup to individual binary-analysis test files ([736859e](https://github.com/magnus919/agent-skills/commit/736859eafa9ab7c40d0291479a6d87f4a6895055))
|
||||
* **ci:** prevent sys.modules cross-contamination between test directories in check-artifacts ([96f0bd4](https://github.com/magnus919/agent-skills/commit/96f0bd4e46c8023cd5035aba2299df70562c2837))
|
||||
* **ci:** use full path for deptry binary-analysis exclude ([b56183b](https://github.com/magnus919/agent-skills/commit/b56183bbabed58089bf79e3d571433e8fe6dd217))
|
||||
* permit removal of eval-covered skills ([687d7d7](https://github.com/magnus919/agent-skills/commit/687d7d7c33510b7496c50052161596f34ad58eae))
|
||||
* **product-strategy:** correct stale RICE reference ([#211](https://github.com/magnus919/agent-skills/issues/211)) ([8d30f22](https://github.com/magnus919/agent-skills/commit/8d30f22cb89508b2982c36b8a627a79944f5f2b6))
|
||||
* **release-engineering:** address review findings in DORA asset, cadence, link, metrics script ([2b90656](https://github.com/magnus919/agent-skills/commit/2b906565d443bf7d460cfe1a8f5d5c258844de51))
|
||||
* **release-engineering:** align 0.x version bumps with Release Please's minor-feature policy
|
||||
* **release-engineering:** validate Keep a Changelog and Release Please formats
|
||||
* relocate binary analysis skill ([6387f7f](https://github.com/magnus919/agent-skills/commit/6387f7f4752a2dd8fd7a92a7e640ec6b62c11698))
|
||||
* require dated commitments for CoS tasks ([857dfc6](https://github.com/magnus919/agent-skills/commit/857dfc6e1cecccf94ec241a89be20bca3a539fb3))
|
||||
* **security-ship:** ensure diagnostics have both recoverable values and add pagination cursors to security commands ([d04af37](https://github.com/magnus919/agent-skills/commit/d04af37602eae8304e4c089076c047a0eae8fb9c))
|
||||
* **security-ship:** fix --limit routing, truncation warnings, and clean confirmation order ([7b0109b](https://github.com/magnus919/agent-skills/commit/7b0109b328c097e6c40c1ff07ac3ce4c01e98aa2))
|
||||
* **security-ship:** fix three scrutiny blocking issues ([a20adde](https://github.com/magnus919/agent-skills/commit/a20adde298209480b49279aca84a5b6e3c54457e))
|
||||
* state CoS task-capture boundary ([f285316](https://github.com/magnus919/agent-skills/commit/f285316206258471343c66ea9bfaf15f07f3bfbc))
|
||||
|
||||
|
||||
### Reverts
|
||||
|
||||
* restore clean base64 import in helpers.py ([746df95](https://github.com/magnus919/agent-skills/commit/746df95150e7ec092c2d37daa8261f4c3d12004a))
|
||||
|
||||
## [0.5.0](https://github.com/magnus919/agent-skills/compare/v0.4.0...v0.5.0) (2026-07-27)
|
||||
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ It also covers the parts of release work that quietly break teams: versioning an
|
||||
| `references/` | 15 dense topic files: role-and-career, skills-competency-model, release-process-models, cd-and-pipeline-stages, progressive-delivery, change-governance-and-compliance, readiness-and-quality-gates, rollback-and-recovery, versioning-and-artifacts, feature-flag-lifecycle, monorepo-polyrepo-release, toolchain-landscape, supply-chain-security, metrics-and-dora, release-operations-and-triage |
|
||||
| `templates/` | 6 fillable templates: release-plan, release-readiness-checklist, rollback-runbook, release-notes, change-governance-record, hotfix-emergency-release-plan |
|
||||
| `assets/` | 4 quick-reference files: dora-metrics-reference, versioning-decision-table, deployment-strategy-matrix, release-toolchain-cheatsheet |
|
||||
| `scripts/` | 5 Python CLIs: version_bump (next-SemVer from conventional commits), semver_check (validate/compare/sort), changelog_check (Keep a Changelog validator), dora_metrics (five-metric computation), release_plan_scaffold (plan generator) |
|
||||
| `scripts/` | 5 Python CLIs: version_bump (next-SemVer from conventional commits, including the documented 0.x policy), semver_check (validate/compare/sort), changelog_check (Keep a Changelog and Release Please validator), dora_metrics (five-metric computation), release_plan_scaffold (plan generator) |
|
||||
| `evals/` | Schema-v1 output-quality eval manifest (8 cases) |
|
||||
|
||||
## Quick Start
|
||||
@@ -30,6 +30,8 @@ Validate a changelog before it ships:
|
||||
|
||||
```bash
|
||||
python3 release-engineering/scripts/changelog_check.py CHANGELOG.md
|
||||
# Or select Release Please's linked-header format explicitly:
|
||||
python3 release-engineering/scripts/changelog_check.py CHANGELOG.md --format release-please
|
||||
```
|
||||
|
||||
Compute the five DORA metrics from deployment and commit event data:
|
||||
|
||||
@@ -93,7 +93,7 @@ Senior-to-principal release engineering methodology: designing and operating the
|
||||
| `assets/release-toolchain-cheatsheet.md` | Quick tool lookup by category — one-liner and when-to-pick per tool |
|
||||
| `scripts/version_bump.py` | Computing the next SemVer from conventional commits or a git range |
|
||||
| `scripts/semver_check.py` | Validating, comparing, or sorting strict SemVer versions |
|
||||
| `scripts/changelog_check.py` | Validating a CHANGELOG.md against Keep a Changelog |
|
||||
| `scripts/changelog_check.py` | Validating Keep a Changelog or Release Please CHANGELOG.md files |
|
||||
| `scripts/dora_metrics.py` | Computing the five DORA metrics from deployment and commit event data |
|
||||
| `scripts/release_plan_scaffold.py` | Scaffolding a release plan document from flags or a git range |
|
||||
| `evals/evals.json` | Running output-quality evals for this skill (schema v1, 8 cases) |
|
||||
@@ -107,9 +107,9 @@ Senior-to-principal release engineering methodology: designing and operating the
|
||||
|
||||
| Script | Invocation | Purpose |
|
||||
|--------|-----------|---------|
|
||||
| version_bump | `python3 scripts/version_bump.py --current-version 1.4.0 --git-range v1.4.0..HEAD` | Computes the next SemVer from Conventional Commits — breaking → major, feat → minor, fix → patch; optional prerelease tag |
|
||||
| version_bump | `python3 scripts/version_bump.py --current-version 1.4.0 --git-range v1.4.0..HEAD` | Computes the next SemVer from Conventional Commits — breaking → major (minor in 0.x), feat → minor, fix → patch; optional prerelease tag |
|
||||
| semver_check | `python3 scripts/semver_check.py --check 1.2.3-beta.1` | Validates strict SemVer 2.0.0, compares two versions, or sorts a list |
|
||||
| changelog_check | `python3 scripts/changelog_check.py CHANGELOG.md` | Validates a changelog against Keep a Changelog — headers, dates, change types, link references |
|
||||
| changelog_check | `python3 scripts/changelog_check.py CHANGELOG.md [--format auto|keep-a-changelog|release-please]` | Validates supported changelog headers, dates, sections, bullets, and links; reports selected/detected format |
|
||||
| dora_metrics | `python3 scripts/dora_metrics.py --events events.json` | Computes all five DORA metrics from deployment and commit event data |
|
||||
| release_plan_scaffold | `python3 scripts/release_plan_scaffold.py --version 2.0.0 --owner alice --output plan.md` | Scaffolds a release plan document with filled placeholders from flags or a git range |
|
||||
|
||||
|
||||
@@ -36,9 +36,14 @@
|
||||
| `BREAKING CHANGE:` footer, or `feat!` / `fix!` | MAJOR | `feat!: drop v1 API` |
|
||||
| `feat` | MINOR | `feat(auth): add refresh tokens` |
|
||||
| `fix` | PATCH | `fix(api): retry on 429` |
|
||||
| `perf`, `refactor`, `docs`, `test`, `chore`, `ci`, `build`, `style` | No bump (or PATCH, if you choose) | `docs: update readme` |
|
||||
| `perf`, `refactor`, `docs`, `test`, `chore`, `ci`, `build`, `style` | PATCH in this skill | `docs: update readme` |
|
||||
|
||||
> **Gotcha —** the bump is decided by the highest-priority type in the release range: one `BREAKING CHANGE` forces a major even if the rest are fixes. Automate with the `version_bump.py` script.
|
||||
For `0.y.z`, this skill's Release Please-compatible policy maps both
|
||||
`feat` and breaking changes to MINOR (`0.5.0` -> `0.6.0`), while fixes and
|
||||
other changes remain PATCH. At `1.0.0` and later, normal SemVer priority
|
||||
applies.
|
||||
|
||||
> **Gotcha —** the bump is decided by the highest-priority type in the release range: one `BREAKING CHANGE` forces a MAJOR at 1.0.0+, or a MINOR bump in 0.x, even if the rest are fixes. Automate with the `version_bump.py` script.
|
||||
|
||||
## Prerelease and Build Metadata Rules
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ Two rules that commonly surprise: numeric identifiers compare **numerically** (`
|
||||
`0.y.z` means **initial development**: the spec explicitly states that "anything may change at any time" and the public API should not be considered stable. Practical consequences:
|
||||
|
||||
- `0.1.0` → `0.2.0` usually signals breaking changes in pre-1.0 libraries — the `1.0.0` MAJOR convention is effectively deferred.
|
||||
- Many tools map `feat` commits to MINOR even in 0.x, which can silently bump `0.3.0` → `0.4.0` for an additive change. Decide and document your 0.x policy; a common choice is "breaking changes bump MINOR until 1.0."
|
||||
- This skill's default Release Please-compatible policy maps `feat` and breaking commits to MINOR in 0.x (`0.5.0` → `0.6.0`); fixes and other commit types remain PATCH (`0.5.0` → `0.5.1`). This keeps pre-1.0 release lines meaningful while preserving normal SemVer behavior at 1.0+.
|
||||
- Consumers pinning `0.x` with caret ranges (`^0.3.1`) get **no automatic updates** in most package managers (npm, for example, treats caret on `0.x` as `>=0.3.1 <0.4.0`), which is exactly the behavior you want for a pre-stable API.
|
||||
|
||||
Declare a policy so both humans and automation agree on what a `0.x` bump means:
|
||||
@@ -50,7 +50,7 @@ Declare a policy so both humans and automation agree on what a `0.x` bump means:
|
||||
| Policy | Rule | Consequence |
|
||||
|--------|------|-------------|
|
||||
| **Strict** | Breaking changes bump MAJOR even in 0.x | Version jumps `0.3.0` → `1.0.0` early; signals commitment before the API is ready |
|
||||
| **Deferred** (most common) | Breaking changes bump MINOR until 1.0 | `0.3.0` → `0.4.0`; 1.0 arrives when the API stabilizes |
|
||||
| **Deferred** (skill default) | Features and breaking changes bump MINOR until 1.0; fixes and other changes bump PATCH | `0.5.0` → `0.6.0` for `feat`, `0.5.0` → `0.5.1` for `fix`; 1.0 arrives when the API stabilizes |
|
||||
| **Tooling-default** | Whatever your release tool computes from commits | Usually `feat`→MINOR; document that pre-1.0 MINOR may break |
|
||||
|
||||
> **Gotcha — The 0.x trap:** A 1.0.0 release is a promise about API stability. If your library has public consumers, treat 1.0.0 as a deliberate commitment — and conversely, do not stay in `0.x` forever because bumping to 1.0 feels risky; consumers already treat `0.x` as unstable either way.
|
||||
@@ -138,7 +138,7 @@ Consistency matters more than the exact mapping: if `perf` bumps PATCH in one re
|
||||
|
||||
Automated bump tooling reads this history: **semantic-release** analyzes commits and performs version + changelog + publish with no human gate; **release-please** generates a release PR (version bump + changelog) that a human merges; **git-cliff** generates the changelog from commits without publishing. For monorepo specifics (per-package vs combined releases), see [monorepo-polyrepo-release.md](./monorepo-polyrepo-release.md).
|
||||
|
||||
## Changelogs (Keep a Changelog)
|
||||
## Changelogs (Keep a Changelog and Release Please)
|
||||
|
||||
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/) is the de-facto human changelog format, designed for **people, not machines** (machines read commits). Core conventions:
|
||||
|
||||
@@ -169,7 +169,7 @@ A minimal conforming structure:
|
||||
[2.1.0]: https://github.com/acme/app/compare/v2.0.0...v2.1.0
|
||||
```
|
||||
|
||||
The `scripts/changelog_check.py` in this skill validates this shape: required `# Changelog` title, `[Unreleased]` section, strict-SemVer date-stamped version headers, allowed change types, and consistent reference links.
|
||||
The `scripts/changelog_check.py` in this skill validates this shape with `--format keep-a-changelog` (or safe `--format auto` detection). It also validates Release Please output with linked dated headers such as `## [0.6.0](https://github.com/example/proj/compare/v0.5.0...v0.6.0) (2026-08-03)`, conventional `###` sections such as `Features`, `Bug Fixes`, and `Reverts`, and `*` bullets with inline links. Release Please section labels are configurable. Release Please files do not use an `Unreleased` section; select that format explicitly in CI when auto-detection is not appropriate.
|
||||
|
||||
## Artifact Immutability and Promotion
|
||||
|
||||
|
||||
@@ -1,9 +1,21 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Validate a CHANGELOG.md against the Keep a Changelog conventions.
|
||||
"""Validate Keep a Changelog or Release Please CHANGELOG.md files.
|
||||
|
||||
Checks performed:
|
||||
- The first non-empty line is the `# Changelog` title.
|
||||
- A `## [Unreleased]` section exists.
|
||||
Keep a Changelog validation requires the first non-empty line to be the
|
||||
`# Changelog` title, an `## [Unreleased]` section, dated version headers,
|
||||
allowed change types, and reference links. Release Please validation accepts
|
||||
linked dated headers such as `## [1.2.0](https://...) (2026-08-03)`, conventional
|
||||
changelog sections such as `Features`, `Bug Fixes`, and `Reverts`, and star
|
||||
bullets; it rejects an `Unreleased` section. Release Please section labels are
|
||||
configurable, so the validator checks that non-empty `###` headings contain the
|
||||
bullets.
|
||||
|
||||
With `--format auto` (the default), a valid Release Please header selects the
|
||||
Release Please validator; otherwise the strict Keep a Changelog validator is
|
||||
used. Explicit `--format` selection is available for CI gates.
|
||||
|
||||
Keep a Changelog checks:
|
||||
- Version headers use the form `## [X.Y.Z] - YYYY-MM-DD` with a strict
|
||||
SemVer version (pre-releases allowed) and a valid ISO-8601 date
|
||||
(YYYY-MM-DD or YYYY-MM); the optional `[YANKED]` marker is allowed.
|
||||
@@ -18,7 +30,7 @@ Checks performed:
|
||||
Each problem is reported with its line number. Exit 0 when the file is
|
||||
clean, exit 1 when any problem is found.
|
||||
|
||||
Arguments: [changelog.md] (default: CHANGELOG.md), --json.
|
||||
Arguments: [changelog.md] (default: CHANGELOG.md), --format, --json.
|
||||
|
||||
Exit codes:
|
||||
0 changelog is valid
|
||||
@@ -37,10 +49,15 @@ UNRELEASED_HEADER_RE = re.compile(r"^##\s+\[Unreleased\](\s+\[YANKED\])?\s*$")
|
||||
VERSION_HEADER_RE = re.compile(
|
||||
r"^##\s+\[([^\]]+)\]\s*-\s*(\d{4}-\d{2}-\d{2}|\d{4}-\d{2})(\s+\[YANKED\])?\s*$"
|
||||
)
|
||||
RELEASE_PLEASE_HEADER_RE = re.compile(
|
||||
r"^##\s+\[([^\]]+)\]\(([^)]+)\)\s+\((\d{4}-\d{2}-\d{2})\)\s*$"
|
||||
)
|
||||
BULLET_RE = re.compile(r"^-\s+(\S+)")
|
||||
STAR_BULLET_RE = re.compile(r"^\*\s+(\S+)")
|
||||
LINK_REF_RE = re.compile(r"^\[([^\]]+)\]:\s+(\S+)")
|
||||
|
||||
CHANGE_TYPES = ("Added", "Changed", "Deprecated", "Removed", "Fixed", "Security")
|
||||
FORMATS = ("auto", "keep-a-changelog", "release-please")
|
||||
|
||||
SEMVER_RE = re.compile(
|
||||
r"^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)"
|
||||
@@ -55,10 +72,8 @@ def parse_args(argv=None):
|
||||
parser = argparse.ArgumentParser(
|
||||
prog="changelog_check.py",
|
||||
description=(
|
||||
"Validate a CHANGELOG.md against the Keep a Changelog "
|
||||
"conventions: title, [Unreleased] section, strict SemVer version "
|
||||
"headers with valid dates, allowed change-type bullets, and "
|
||||
"consistent reference links."
|
||||
"Validate a CHANGELOG.md as Keep a Changelog or Release Please; "
|
||||
"auto-detect the format unless explicitly selected."
|
||||
),
|
||||
epilog=(
|
||||
"Exit codes: 0 valid, 1 problems found / file unreadable, "
|
||||
@@ -66,6 +81,7 @@ def parse_args(argv=None):
|
||||
"Examples:\n"
|
||||
" changelog_check.py\n"
|
||||
" changelog_check.py CHANGELOG.md\n"
|
||||
" changelog_check.py CHANGELOG.md --format release-please\n"
|
||||
" changelog_check.py CHANGELOG.md --json\n"
|
||||
),
|
||||
)
|
||||
@@ -76,6 +92,16 @@ def parse_args(argv=None):
|
||||
metavar="CHANGELOG.md",
|
||||
help="Path to the changelog file (default: CHANGELOG.md).",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--format",
|
||||
choices=FORMATS,
|
||||
default="auto",
|
||||
dest="format",
|
||||
help=(
|
||||
"Changelog format: auto (default), keep-a-changelog, or "
|
||||
"release-please."
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
"--json",
|
||||
action="store_true",
|
||||
@@ -107,7 +133,15 @@ def valid_date(text):
|
||||
return False
|
||||
|
||||
|
||||
def check_changelog(text):
|
||||
def detect_format(text):
|
||||
"""Detect Release Please only from its unambiguous linked header shape."""
|
||||
for line in text.splitlines():
|
||||
if RELEASE_PLEASE_HEADER_RE.match(line.rstrip()):
|
||||
return "release-please"
|
||||
return "keep-a-changelog"
|
||||
|
||||
|
||||
def check_keep_a_changelog(text):
|
||||
"""Validate changelog text; returns (valid, problems).
|
||||
|
||||
problems is a list of {"line": int, "message": str} dicts.
|
||||
@@ -252,6 +286,104 @@ def check_changelog(text):
|
||||
return len(problems) == 0, problems
|
||||
|
||||
|
||||
def check_release_please(text):
|
||||
"""Validate the Release Please changelog format."""
|
||||
problems = []
|
||||
lines = text.splitlines()
|
||||
non_empty = [i for i, line in enumerate(lines) if line.strip()]
|
||||
if not non_empty:
|
||||
return False, [{"line": 1, "message": "file is empty"}]
|
||||
|
||||
if not TITLE_RE.match(lines[non_empty[0]].strip()):
|
||||
problems.append(
|
||||
{
|
||||
"line": non_empty[0] + 1,
|
||||
"message": "expected '# Changelog' title as the first non-empty line",
|
||||
}
|
||||
)
|
||||
|
||||
in_section = False
|
||||
subsection = None
|
||||
release_count = 0
|
||||
for idx, raw in enumerate(lines):
|
||||
line = raw.rstrip()
|
||||
stripped = line.strip()
|
||||
lineno = idx + 1
|
||||
|
||||
if line.startswith("## "):
|
||||
in_section = False
|
||||
subsection = None
|
||||
if stripped == "## [Unreleased]" or stripped.startswith("## [Unreleased]"):
|
||||
problems.append(
|
||||
{"line": lineno, "message": "Release Please files must not contain an '## [Unreleased]' section"}
|
||||
)
|
||||
continue
|
||||
match = RELEASE_PLEASE_HEADER_RE.match(stripped)
|
||||
if not match:
|
||||
problems.append(
|
||||
{
|
||||
"line": lineno,
|
||||
"message": "malformed Release Please version header (expected '## [X.Y.Z](<url>) (YYYY-MM-DD)')",
|
||||
}
|
||||
)
|
||||
continue
|
||||
version, url, date_text = match.groups()
|
||||
release_count += 1
|
||||
in_section = True
|
||||
if not valid_semver(version):
|
||||
problems.append(
|
||||
{"line": lineno, "message": "version '{}' is not strict SemVer".format(version)}
|
||||
)
|
||||
if not url.startswith(("https://", "http://")):
|
||||
problems.append(
|
||||
{"line": lineno, "message": "Release Please header link must be an http(s) URL"}
|
||||
)
|
||||
if not valid_date(date_text):
|
||||
problems.append(
|
||||
{"line": lineno, "message": "invalid release date '{}' in header".format(date_text)}
|
||||
)
|
||||
continue
|
||||
|
||||
if not in_section:
|
||||
continue
|
||||
if line.startswith("### "):
|
||||
subsection = stripped[len("### "):].strip()
|
||||
if not subsection:
|
||||
problems.append(
|
||||
{
|
||||
"line": lineno,
|
||||
"message": "Release Please subsection headings must not be empty",
|
||||
}
|
||||
)
|
||||
continue
|
||||
if stripped.startswith("*"):
|
||||
if not STAR_BULLET_RE.match(stripped):
|
||||
problems.append(
|
||||
{"line": lineno, "message": "malformed Release Please bullet (expected '* <change>')"}
|
||||
)
|
||||
elif subsection is None:
|
||||
problems.append(
|
||||
{"line": lineno, "message": "Release Please bullets must be under a subsection heading"}
|
||||
)
|
||||
continue
|
||||
if stripped.startswith("-"):
|
||||
problems.append(
|
||||
{"line": lineno, "message": "Release Please bullets must use '*' rather than '-'"}
|
||||
)
|
||||
|
||||
if release_count == 0:
|
||||
problems.append({"line": 1, "message": "missing Release Please version section"})
|
||||
return len(problems) == 0, problems
|
||||
|
||||
|
||||
def check_changelog(text, format="auto"):
|
||||
"""Validate text using an explicit format or safe auto-detection."""
|
||||
selected = detect_format(text) if format == "auto" else format
|
||||
if selected == "release-please":
|
||||
return check_release_please(text)
|
||||
return check_keep_a_changelog(text)
|
||||
|
||||
|
||||
def main(argv=None):
|
||||
"""Entry point."""
|
||||
args = parse_args(argv)
|
||||
@@ -262,13 +394,17 @@ def main(argv=None):
|
||||
print("error: cannot read '{}': {}".format(args.changelog, exc), file=sys.stderr)
|
||||
return 1
|
||||
|
||||
valid, problems = check_changelog(text)
|
||||
detected_format = detect_format(text)
|
||||
selected_format = detected_format if args.format == "auto" else args.format
|
||||
valid, problems = check_changelog(text, selected_format)
|
||||
|
||||
if args.json_output:
|
||||
print(
|
||||
json.dumps(
|
||||
{
|
||||
"file": args.changelog,
|
||||
"format": selected_format,
|
||||
"detected_format": detected_format,
|
||||
"valid": valid,
|
||||
"problem_count": len(problems),
|
||||
"problems": problems,
|
||||
@@ -278,7 +414,9 @@ def main(argv=None):
|
||||
)
|
||||
else:
|
||||
if not problems:
|
||||
print("valid: {} conforms to Keep a Changelog".format(args.changelog))
|
||||
print("valid: {} conforms to {} (detected: {})".format(
|
||||
args.changelog, selected_format, detected_format
|
||||
))
|
||||
else:
|
||||
for problem in problems:
|
||||
print(
|
||||
|
||||
@@ -11,8 +11,9 @@ Bump rules (Conventional Commits 1.0.0):
|
||||
- BREAKING CHANGE footer, or a `!` after the type/scope -> MAJOR
|
||||
- feat -> MINOR
|
||||
- fix and all other types -> PATCH
|
||||
- 0.x versions (initial development): MAJOR bumps become MINOR,
|
||||
MINOR bumps become PATCH (the public API is not yet stable).
|
||||
- 0.x versions (initial development): MAJOR and MINOR bumps both become
|
||||
MINOR under the documented Release Please-compatible policy, while
|
||||
PATCH bumps remain PATCH.
|
||||
|
||||
Pre-release handling (--pre-release alpha|beta|rc):
|
||||
- If the current version is already a pre-release with the SAME tag
|
||||
@@ -194,7 +195,7 @@ def bump_core(current, level):
|
||||
return (major + 1, 0, 0)
|
||||
if level == "minor":
|
||||
if major == 0:
|
||||
return (major, minor, patch + 1)
|
||||
return (major, minor + 1, 0)
|
||||
return (major, minor + 1, 0)
|
||||
return (major, minor, patch + 1)
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""Tests for changelog_check.py.
|
||||
|
||||
Covers: Keep a Changelog validation (title, [Unreleased], version headers,
|
||||
dates, change types, reference links), --json output, and exit codes.
|
||||
Covers: Keep a Changelog and Release Please validation, format selection,
|
||||
--json output, and exit codes.
|
||||
|
||||
Discoverable by both pytest and unittest (unittest.TestCase classes).
|
||||
"""
|
||||
@@ -38,6 +38,21 @@ All notable changes to this project will be documented in this file.
|
||||
[1.1.0]: https://github.com/example/proj/releases/tag/v1.1.0
|
||||
"""
|
||||
|
||||
VALID_RELEASE_PLEASE = """\
|
||||
# Changelog
|
||||
|
||||
## [0.6.0](https://github.com/magnus919/agent-skills/compare/v0.5.0...v0.6.0) (2026-08-03)
|
||||
|
||||
### Features
|
||||
* add a feature ([abc123](https://github.com/example/proj/commit/abc123))
|
||||
|
||||
### Bug Fixes
|
||||
* fix a bug ([def456](https://github.com/example/proj/commit/def456))
|
||||
|
||||
### Reverts
|
||||
* revert an earlier change ([fedcba](https://github.com/example/proj/commit/fedcba))
|
||||
"""
|
||||
|
||||
|
||||
def run_changelog(args, cwd=None):
|
||||
"""Run changelog_check.py with given args, return (returncode, stdout, stderr)."""
|
||||
@@ -144,6 +159,36 @@ class TestChangelogCheckValid(unittest.TestCase):
|
||||
finally:
|
||||
os.unlink(path)
|
||||
|
||||
def test_release_please_format_valid(self):
|
||||
"""Release Please's dated linked headers and star bullets pass."""
|
||||
path = write_changelog(VALID_RELEASE_PLEASE)
|
||||
try:
|
||||
rc, out, _ = run_changelog([path])
|
||||
self.assertEqual(rc, 0)
|
||||
self.assertIn("release-please", out.lower())
|
||||
finally:
|
||||
os.unlink(path)
|
||||
|
||||
def test_release_please_explicit_format_valid(self):
|
||||
"""The Release Please format can be selected explicitly."""
|
||||
path = write_changelog(VALID_RELEASE_PLEASE)
|
||||
try:
|
||||
rc, out, _ = run_changelog([path, "--format", "release-please"])
|
||||
self.assertEqual(rc, 0)
|
||||
self.assertIn("release-please", out.lower())
|
||||
finally:
|
||||
os.unlink(path)
|
||||
|
||||
def test_release_please_custom_section_valid(self):
|
||||
"""Custom Release Please section names remain valid."""
|
||||
content = VALID_RELEASE_PLEASE.replace("### Features", "### Documentation")
|
||||
path = write_changelog(content)
|
||||
try:
|
||||
rc, _, _ = run_changelog([path, "--format", "release-please"])
|
||||
self.assertEqual(rc, 0)
|
||||
finally:
|
||||
os.unlink(path)
|
||||
|
||||
|
||||
class TestChangelogCheckProblems(unittest.TestCase):
|
||||
"""Each Keep a Changelog violation is reported with exit 1."""
|
||||
@@ -256,6 +301,32 @@ class TestChangelogCheckProblems(unittest.TestCase):
|
||||
finally:
|
||||
os.unlink(path)
|
||||
|
||||
def test_malformed_release_please_header_exit_1(self):
|
||||
"""A Release Please header without its compare link is invalid."""
|
||||
content = VALID_RELEASE_PLEASE.replace(
|
||||
"## [0.6.0](https://github.com/magnus919/agent-skills/compare/v0.5.0...v0.6.0) (2026-08-03)",
|
||||
"## [0.6.0] (2026-08-03)",
|
||||
)
|
||||
path = write_changelog(content)
|
||||
try:
|
||||
rc, out, _ = run_changelog([path, "--format", "release-please"])
|
||||
self.assertEqual(rc, 1)
|
||||
self.assertIn("header", out.lower())
|
||||
finally:
|
||||
os.unlink(path)
|
||||
|
||||
def test_release_please_rejects_unreleased_section(self):
|
||||
"""Release Please files must not contain Keep a Changelog Unreleased."""
|
||||
path = write_changelog(VALID_RELEASE_PLEASE.replace(
|
||||
"# Changelog\n", "# Changelog\n\n## [Unreleased]\n"
|
||||
))
|
||||
try:
|
||||
rc, out, _ = run_changelog([path, "--format", "release-please"])
|
||||
self.assertEqual(rc, 1)
|
||||
self.assertIn("unreleased", out.lower())
|
||||
finally:
|
||||
os.unlink(path)
|
||||
|
||||
|
||||
class TestChangelogCheckExitCodes(unittest.TestCase):
|
||||
"""Exit codes for missing files and usage errors."""
|
||||
@@ -300,6 +371,29 @@ class TestChangelogCheckJsonOutput(unittest.TestCase):
|
||||
self.assertTrue(data["valid"])
|
||||
self.assertEqual(data["problem_count"], 0)
|
||||
self.assertEqual(data["problems"], [])
|
||||
self.assertEqual(data["format"], "keep-a-changelog")
|
||||
finally:
|
||||
os.unlink(path)
|
||||
|
||||
def test_json_release_please_reports_format(self):
|
||||
"""JSON reports the selected and detected Release Please format."""
|
||||
path = write_changelog(VALID_RELEASE_PLEASE)
|
||||
try:
|
||||
rc, out, _ = run_changelog([path, "--json"])
|
||||
self.assertEqual(rc, 0)
|
||||
data = json.loads(out)
|
||||
self.assertEqual(data["format"], "release-please")
|
||||
self.assertEqual(data["detected_format"], "release-please")
|
||||
finally:
|
||||
os.unlink(path)
|
||||
|
||||
def test_explicit_keep_format_rejects_release_please(self):
|
||||
"""Explicit Keep a Changelog validation remains strict."""
|
||||
path = write_changelog(VALID_RELEASE_PLEASE)
|
||||
try:
|
||||
rc, out, _ = run_changelog([path, "--format", "keep-a-changelog"])
|
||||
self.assertEqual(rc, 1)
|
||||
self.assertIn("unreleased", out.lower())
|
||||
finally:
|
||||
os.unlink(path)
|
||||
|
||||
|
||||
@@ -114,15 +114,15 @@ class TestVersionBumpBumpRules(unittest.TestCase):
|
||||
finally:
|
||||
os.unlink(commits)
|
||||
|
||||
def test_zero_major_feat_bumps_patch(self):
|
||||
"""On a 0.x version, feat bumps patch."""
|
||||
def test_zero_major_feat_bumps_minor(self):
|
||||
"""On a 0.x version, feat follows Release Please and bumps minor."""
|
||||
commits = write_temp_file("feat: add helper\n")
|
||||
try:
|
||||
rc, out, _ = run_version_bump(
|
||||
["--current-version", "0.2.0", "--commits-file", commits]
|
||||
["--current-version", "0.5.0", "--commits-file", commits]
|
||||
)
|
||||
self.assertEqual(rc, 0)
|
||||
self.assertIn("0.2.1", out)
|
||||
self.assertIn("0.6.0", out)
|
||||
finally:
|
||||
os.unlink(commits)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user