diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..468c804 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,55 @@ +name: Release + +on: + push: + branches: [main] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: false + +permissions: + contents: write + +jobs: + release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Detect release tag in commit message + id: detect + run: | + MSG="${{ github.event.head_commit.message }}" + if echo "$MSG" | grep -qE '\[(major|minor|patch)\]'; then + echo "triggered=true" >> "$GITHUB_OUTPUT" + else + echo "triggered=false" >> "$GITHUB_OUTPUT" + fi + + - name: Read version + if: steps.detect.outputs.triggered == 'true' + id: version + run: echo "version=$(cat VERSION)" >> "$GITHUB_OUTPUT" + + - name: Create and push tag + if: steps.detect.outputs.triggered == 'true' + run: | + git tag "v${{ steps.version.outputs.version }}" + git push origin "v${{ steps.version.outputs.version }}" + + - name: Package release artifact + if: steps.detect.outputs.triggered == 'true' + run: zip -r release.zip . --exclude ".git/*" --exclude ".github/*" + + - name: Create GitHub Release + if: steps.detect.outputs.triggered == 'true' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh release create "v${{ steps.version.outputs.version }}" \ + release.zip \ + --title "Release v${{ steps.version.outputs.version }}" \ + --generate-notes diff --git a/.github/workflows/validate-version.yml b/.github/workflows/validate-version.yml new file mode 100644 index 0000000..03ffaaf --- /dev/null +++ b/.github/workflows/validate-version.yml @@ -0,0 +1,21 @@ +name: Validate version + +on: + pull_request: + branches: [main] + +jobs: + validate: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Check version consistency + run: | + VERSION=$(cat VERSION) + PLUGIN_VERSION=$(jq -r '.version' .claude-plugin/plugin.json) + if [ "$VERSION" != "$PLUGIN_VERSION" ]; then + echo "::error::Version mismatch: VERSION=$VERSION but .claude-plugin/plugin.json.version=$PLUGIN_VERSION" + exit 1 + fi + echo "All versions consistent: $VERSION" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 06018fd..2d4b37f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -43,11 +43,19 @@ This downloads the pinned upstream tarball and replaces the contents of `skills/ - [ ] `node scripts/validate-claude-plugin.mjs` passes. - [ ] `claude plugin validate` passes (before directory submission or major releases). -- [ ] Version bumped in [`.claude-plugin/plugin.json`](.claude-plugin/plugin.json) when the plugin changes. - [ ] No secrets, credentials, or files under `**/local-cache/` committed. - [ ] If the skill tree changed: `pin` in `.github/scripts/sync-skills-vendor.json` matches the upstream tag the new tree was generated from. - [ ] Smoke-test: `claude --plugin-dir .` from the repo root. +## Releasing + +To cut a release: + +1. In your PR, bump `VERSION` and sync `.claude-plugin/plugin.json` `.version` to match. The `validate-version` PR check enforces this. +2. Merge to `main` with `[major]`, `[minor]`, or `[patch]` anywhere in the commit message. + +The release workflow reads `VERSION`, creates a `vX.Y.Z` git tag, and publishes a GitHub Release with a repo zip attached. No bot push to `main` — the version bump is part of the PR itself. + ### Submitting to the Claude plugin directory Use [Submitting your plugin](https://claude.com/docs/plugins/submit). Submit the **public GitHub URL** of this repository — the **repository root** is the plugin root (manifest in `.claude-plugin/`, skills committed under `skills/`, vendored from [jfrog/jfrog-skills](https://github.com/jfrog/jfrog-skills)). diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..b003284 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +0.2.7