From 99dc7e73bb3511cd351f5bd65c732888ef6515bb Mon Sep 17 00:00:00 2001 From: Christos Gkoros Date: Mon, 20 Jul 2026 18:10:00 +0300 Subject: [PATCH 1/2] Add release workflow, CHANGELOG, and bump to 1.3.0 - Introduce CHANGELOG.md (Keep a Changelog + SemVer) with history back to 1.0.0 - Bump plugin.json to 1.3.0 to cover the /postman:learn command - Add release workflow that tags -> verifies version -> publishes GitHub Release from the matching CHANGELOG section - Document versioning/release discipline in CLAUDE.md Co-Authored-By: Claude --- .claude-plugin/plugin.json | 2 +- .github/workflows/release.yml | 52 +++++++++++++++++++++++ CHANGELOG.md | 79 +++++++++++++++++++++++++++++++++++ CLAUDE.md | 7 ++++ 4 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/release.yml create mode 100644 CHANGELOG.md diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index b98e5cf..9dc194b 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "postman", - "version": "1.2.0", + "version": "1.3.0", "description": "Full API lifecycle management for Claude Code. Sync collections, generate client code, discover APIs, run tests, create mocks, publish docs, and audit security. Powered by the Postman MCP Server.", "author": { "name": "Postman", diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..e43d1e1 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,52 @@ +name: Release + +on: + push: + tags: + - "v*" + +permissions: + contents: write + +jobs: + release: + name: Publish Release + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Verify tag matches plugin.json version + run: | + TAG="${GITHUB_REF_NAME#v}" + PLUGIN_VERSION=$(python -c "import json; print(json.load(open('.claude-plugin/plugin.json'))['version'])") + echo "Tag version: $TAG" + echo "plugin.json: $PLUGIN_VERSION" + if [ "$TAG" != "$PLUGIN_VERSION" ]; then + echo "::error::Tag v$TAG does not match plugin.json version $PLUGIN_VERSION. Bump plugin.json before tagging." + exit 1 + fi + + - name: Extract release notes from CHANGELOG + id: notes + run: | + TAG="${GITHUB_REF_NAME#v}" + # Print the body of the "## [X.Y.Z]" section, stopping at the next "## " heading. + awk -v ver="$TAG" ' + $0 ~ "^## \\[" ver "\\]" { grab=1; next } + grab && /^## / { exit } + grab { print } + ' CHANGELOG.md > release-notes.md + if [ ! -s release-notes.md ]; then + echo "::error::No CHANGELOG section found for version $TAG. Add a '## [$TAG]' entry." + exit 1 + fi + echo "Release notes:" + cat release-notes.md + + - name: Create GitHub Release + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh release create "$GITHUB_REF_NAME" \ + --title "$GITHUB_REF_NAME" \ + --notes-file release-notes.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..97c0efe --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,79 @@ +# Changelog + +All notable changes to the Postman Plugin for Claude Code are documented here. + +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). + +The version here always matches `version` in `.claude-plugin/plugin.json`. A release +is cut by tagging the matching `vX.Y.Z` (see [Releasing](#releasing)). + +## [Unreleased] + +## [1.3.0] - 2026-07-20 + +### Added + +- `/postman:learn` command — searches the Postman Learning Center via the + `searchLearningCenter` MCP tool. Requires Full MCP mode (the tool is absent in + `minimal` and `code` modes). + +## [1.2.0] - 2026-06-09 + +### Added + +- `postman-context` skill — API discovery, exploration, and client code generation + from real API definitions via `postman context`. + +### Changed + +- Reworked the unified search tool and search strategy around + `searchPostmanElements` (`ownership` + `privateNetwork` filters). +- Reduced plugin token footprint via progressive-disclosure references and leaner + front matter. +- Updated CI validators for scoped tools. + +## [1.1.0] - 2026-04-29 + +### Added + +- OAuth authentication support in `/postman:setup` alongside `POSTMAN_API_KEY`. + +### Changed + +- Added unique headers across components. + +### Removed + +- Redundant tooling. + +## [1.0.0] + +### Added + +- Initial release: 11 slash commands, 7 skills, and the `readiness-analyzer` + sub-agent, powered by the Postman MCP Server (`mcp.postman.com`) plus the + Postman CLI for `request`, `generate-spec`, and `run-collection`. + +## Releasing + +Releases are automated by `.github/workflows/release.yml`. To cut a release: + +1. Bump `version` in `.claude-plugin/plugin.json`. +2. Move your `## [Unreleased]` notes into a new `## [X.Y.Z] - YYYY-MM-DD` section. +3. Merge to `main`. +4. Tag the commit and push the tag: + + ```bash + git tag v1.3.0 + git push origin v1.3.0 + ``` + +The workflow verifies the tag matches `plugin.json`, extracts the matching +CHANGELOG section, and publishes a GitHub Release with those notes. + +[Unreleased]: https://github.com/Postman-Devrel/postman-claude-code-plugin/compare/v1.3.0...HEAD +[1.3.0]: https://github.com/Postman-Devrel/postman-claude-code-plugin/compare/v1.2.0...v1.3.0 +[1.2.0]: https://github.com/Postman-Devrel/postman-claude-code-plugin/compare/v1.1.0...v1.2.0 +[1.1.0]: https://github.com/Postman-Devrel/postman-claude-code-plugin/compare/v1.0.0...v1.1.0 +[1.0.0]: https://github.com/Postman-Devrel/postman-claude-code-plugin/releases/tag/v1.0.0 diff --git a/CLAUDE.md b/CLAUDE.md index bcfd762..b4380af 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -69,3 +69,10 @@ CLI commands work with Postman's git sync structure: `postman/collections/` (v3 - The `allowed-tools` field in front matter controls what tools a command/agent can use - CLI commands need `Bash` in `allowed-tools`; MCP commands list the specific `mcp__postman__` tools they call — never the `mcp__postman__*` wildcard. When a command's workflow gains a new MCP call, add that tool to its `allowed-tools` - Front-matter `description` fields are injected into every user session — keep them to one or two sentences (what it does + when to use it) + +## Versioning & Releases + +- The plugin follows [Semantic Versioning](https://semver.org). `version` in `.claude-plugin/plugin.json` is the single source of truth +- Every user-facing change bumps the version and adds an entry under `## [Unreleased]` in `CHANGELOG.md` (added a command/skill → minor; fix/tweak → patch; breaking change → major) +- To release: bump `plugin.json`, move `[Unreleased]` notes into a dated `## [X.Y.Z]` section, merge to `main`, then `git tag vX.Y.Z && git push origin vX.Y.Z` +- The `Release` GitHub Actions workflow (`.github/workflows/release.yml`) triggers on `v*` tags: it fails if the tag doesn't match `plugin.json`, extracts the matching CHANGELOG section, and publishes a GitHub Release with those notes From a19c51a67578e9708a773897b7bb29280329814d Mon Sep 17 00:00:00 2001 From: Christos Gkoros Date: Mon, 20 Jul 2026 18:17:01 +0300 Subject: [PATCH 2/2] Allow CHANGELOG.md in structure check and changelog-style headings - Add CHANGELOG.md to the structure validator's allowed root markdown files - Set markdownlint MD024 siblings_only so repeated '### Added'/'### Changed' headings across changelog versions are permitted Co-Authored-By: Claude --- .github/.markdownlint.json | 1 + .github/scripts/validate-structure.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/.markdownlint.json b/.github/.markdownlint.json index bc0a51f..00c43bc 100644 --- a/.github/.markdownlint.json +++ b/.github/.markdownlint.json @@ -1,4 +1,5 @@ { + "MD024": { "siblings_only": true }, "MD009": false, "MD013": false, "MD022": false, diff --git a/.github/scripts/validate-structure.py b/.github/scripts/validate-structure.py index ca360b1..6e6de42 100755 --- a/.github/scripts/validate-structure.py +++ b/.github/scripts/validate-structure.py @@ -73,7 +73,7 @@ def main(): errors.append("agents/: Directory not found") # 6. Check for stray markdown files in root (not README, CLAUDE, LICENSE, or examples) - expected_root_md = {"README.md", "CLAUDE.md", "LICENSE", "token-optimization-findings.md"} + expected_root_md = {"README.md", "CLAUDE.md", "CHANGELOG.md", "LICENSE", "token-optimization-findings.md"} for f in sorted(root.glob("*.md")): if f.name not in expected_root_md: errors.append(f"{f.name}: Unexpected markdown file in repo root")