--- name: wp-bump description: "Structured WordPress plugin release-bump workflow that orchestrates version sync, changelog, rebuild, and validation steps with explicit gates." compatibility: "WordPress plugin projects with PHP; optional package.json, Composer, npm, and build/test scripts." version: "1.1.0" --- # WP Bump ## When to use Use this skill when: - Performing a plugin release bump with coordinated version updates across existing files. - Generating release notes from commit history and writing them to available changelog locations. - Running the project's existing build and validation commands as a release gate. ## Inputs required - Repo root (current working directory). - Target version, preferably SemVer (`1.2.3`). If missing, ask the user. - Changelog entry: auto-derived from `git log` since the last tag; prompt only if no useful commits are found. - Release date. Default to today's date. ## Determinism checklist Before declaring this skill run complete: 1. Scope fixed: inputs and target files are explicit. 2. Read-first: inspect current state before edits. 3. Plan-first: preview actions before writes when tooling supports it. 4. Confirm-before-write: get user confirmation before destructive or broad writes. 5. One step, one done-test: each step has a checkable completion criterion. 6. Verify outcomes: run the smallest available validation commands. 7. Report skips: list what was skipped and why. 8. Stop on blockers: capture exact failing command and error summary. Do not create commits, tags, or releases unless the user explicitly asks. ## Procedure ### 0) Inspect project state Before editing, check for existing user changes and project files: ```sh git status --short ``` Detect the main plugin file by scanning root-level PHP files for a `Plugin Name:` header. If multiple files match, ask the user which one to update. #### Gather commits since last release Find the most recent tag and collect commit subjects since then: ```sh git tag --sort=-creatordate | head -1 # latest tag, empty if none git log ..HEAD --oneline --no-merges # commits since last tag ``` If there is no tag yet, use `git log --oneline --no-merges` (all commits). Store these subjects as candidate changelog lines. Filter out noise: commits whose subject starts with `Merge`, `Revert`, `chore:`, `ci:`, `build:`, `style:`, or is identical to the bump commit itself. If any candidate lines remain, use them to draft the changelog entry (see step 3). Only prompt the user for changelog content when no useful commits are found after filtering. Inspect these files if they exist: - Main plugin file (`Version:` header) - `readme.txt` (`Stable tag:` and `== Changelog ==`) - `package.json` (`version` field and `scripts` object — extract script names for step 5) - `package-lock.json` or `npm-shrinkwrap.json` - `composer.json` (`scripts` object — extract script names for step 5) - `CHANGELOG.md` Completion criterion: Current version sources, candidate changelog commits, and available scripts are collected before any edits. ### 1) Validate the target version Use a plain version string without a leading `v` in project files. If the user provides `v1.2.3`, write `1.2.3`. Confirm the target version is newer than the current plugin header version when both are valid SemVer values. If the target version is not newer, ask before continuing. Completion criterion: Target version format and upgrade direction are validated, and any non-increasing bump is explicitly user-approved. ### 2) Bump version fields Update all version fields that exist in the project: - Main plugin file: update the header line matching `Version:`. - `readme.txt`: update `Stable tag:` to the target version. - `package.json`: update `version` if the file exists. For `package.json`, prefer the package manager when lockfiles exist: ```sh npm version --no-git-tag-version ``` If there is no npm lockfile, it is acceptable to edit `package.json` directly as structured JSON. Do not create `package.json` only for a version bump. Completion criterion: All existing version fields match the target version. ### 3) Update changelogs #### Draft the changelog entry Use the candidate commit subjects collected in step 0 to draft bullet points: - Strip conventional-commit prefixes (`fix:`, `feat:`, `docs:`, etc.) and capitalise the first letter. - One bullet per subject line. - Present the draft to the user for confirmation or editing before writing files. - If no candidates were found, prompt the user for concise release notes. Hard gate: Do not write changelog files until the draft entry is confirmed by the user. Update both changelog locations. #### CHANGELOG.md If `CHANGELOG.md` exists, insert a new release section near the top, below the title and optional `Unreleased` section: ```md ## - YYYY-MM-DD - Release note. ``` If the project already follows a different changelog style, preserve that style. If `CHANGELOG.md` does not exist, create it with: ```md # Changelog ## - YYYY-MM-DD - Release note. ``` #### readme.txt In `readme.txt`, insert the release entry directly under `== Changelog ==`: ```txt = = * Release note. ``` Preserve the existing WordPress.org readme format. If `readme.txt` does not exist, skip it and report that it was absent. Completion criterion: Changelog entry exists in every available changelog location with consistent version/date. ### 4) Rebuild Run the project's build step if one exists. For npm projects: ```sh npm run build --if-present ``` If dependencies are missing and the project has a lockfile, install them with the matching package manager before rebuilding. Do not add new dependencies as part of a version bump unless the user explicitly asks. For Composer-only projects, run the relevant generated/build script only if it exists in `composer.json`. Completion criterion: Existing build command(s) completed or the exact skip reason was reported. ### 5) Run tests and checks Run only the tests and checks that exist in the project. Detect available scripts by inspecting `package.json` and `composer.json`: #### Detect available scripts From `package.json`, read the `scripts` object. Common test-related scripts include `test`, `test:unit`, `test:js`, `lint`, `lint:js`, `lint:css`, `check`, `phpcs`. Only run scripts that are actually defined. From `composer.json`, read the `scripts` object. Common test-related scripts include `test`, `test:unit`, `phpunit`, `lint`, `phpcs`, `check`, `analyze`, `stan`. Only run scripts that are actually defined. #### Execution order 1. If `composer.json` exists: run `composer validate --no-check-publish`. 2. For each test/lint/check script found in `composer.json`, run it with `composer run