feat: /core:release version and release workflow (#87)

Adds a new `/core:release` command to streamline the release process for modules.

This command automates the following workflow:
- Bumps the version in `package.json` (and `gemini-extension.json` if it exists).
- Generates a `CHANGELOG.md` entry from conventional commit messages.
- Commits the changes with a `chore(release): vX.Y.Z` message.
- Creates and pushes a new git tag to trigger the CI release.

A `--preview` flag is included to allow for a dry run of the release process without making any changes.
This commit is contained in:
Snider 2026-02-02 07:21:59 +00:00 committed by GitHub
parent 60e41264f1
commit 31d7509bea
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 227 additions and 0 deletions

View file

@ -49,6 +49,9 @@
"version": "0.1.0"
},
{
"name": "core",
"source": "./claude/core",
"description": "Core functionality - release management",
"name": "issue",
"source": "./claude/issue",
"description": "Integration with GitHub Issues",

View file

@ -0,0 +1,8 @@
{
"name": "core",
"description": "Core functionality - release management",
"version": "0.1.0",
"author": {
"name": "Host UK"
}
}

View file

@ -0,0 +1,44 @@
---
name: release
description: Release a new version of a module
args: [patch|minor|major]
flags:
preview:
description: Show what would happen without actually making a release
type: boolean
default: false
---
# Release new version
Streamlines the release process for modules.
## Commands
### Bump patch version
`/core:release patch`
### Bump minor version
`/core:release minor`
### Bump major version
`/core:release major`
### Preview release
`/core:release patch --preview`
## Workflow
1. **Bump version**: Bumps the version in `package.json` and other necessary files.
2. **Update CHANGELOG.md**: Generates a new entry in the changelog based on commit history.
3. **Create git tag**: Creates a new git tag for the release.
4. **Push tag**: Pushes the new tag to the remote repository.
5. **Trigger CI release**: The new tag should trigger the CI/CD release pipeline.
## Implementation
This command is implemented by the `release.sh` script.
```bash
/bin/bash ../scripts/release.sh "$@"
```

172
claude/core/scripts/release.sh Executable file
View file

@ -0,0 +1,172 @@
#!/bin/bash
# Exit on error
set -e
# --- Argument Parsing ---
BUMP_TYPE=""
PREVIEW=false
# Loop through all arguments
while [[ "$#" -gt 0 ]]; do
case $1 in
patch|minor|major)
if [ -n "$BUMP_TYPE" ]; then
echo "Error: Only one version bump type (patch, minor, major) can be specified." >&2
exit 1
fi
BUMP_TYPE="$1"
;;
--preview)
PREVIEW=true
;;
*)
# Stop parsing at the first non-recognized argument, assuming it's for another script
break
;;
esac
shift
done
# --- Validation ---
if [ -z "$BUMP_TYPE" ]; then
echo "Usage: /core:release [patch|minor|major] [--preview]"
echo "Error: A version bump type must be specified." >&2
exit 1
fi
echo "Configuration:"
echo " Bump Type: $BUMP_TYPE"
echo " Preview Mode: $PREVIEW"
echo "-------------------------"
# --- Version Calculation ---
PACKAGE_JSON_PATH="package.json"
if [ ! -f "$PACKAGE_JSON_PATH" ]; then
echo "Error: package.json not found in the current directory." >&2
exit 1
fi
CURRENT_VERSION=$(jq -r '.version' "$PACKAGE_JSON_PATH")
echo "Current version: $CURRENT_VERSION"
# Version bumping logic
IFS='.' read -r -a VERSION_PARTS <<< "$CURRENT_VERSION"
MAJOR=${VERSION_PARTS[0]}
MINOR=${VERSION_PARTS[1]}
PATCH=${VERSION_PARTS[2]}
case $BUMP_TYPE in
patch)
PATCH=$((PATCH + 1))
;;
minor)
MINOR=$((MINOR + 1))
PATCH=0
;;
major)
MAJOR=$((MAJOR + 1))
MINOR=0
PATCH=0
;;
esac
NEW_VERSION="$MAJOR.$MINOR.$PATCH"
echo "New version: $NEW_VERSION"
# --- Changelog Generation ---
# Get the latest tag, or the first commit if no tags exist
LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || git rev-list --max-parents=0 HEAD)
# Get commit messages since the last tag
COMMIT_LOG=$(git log "$LATEST_TAG"..HEAD --pretty=format:"%s")
# Prepare changelog entry
CHANGELOG_ENTRY="## [$NEW_VERSION] - $(date +%Y-%m-%d)\n\n"
ADDED=""
FIXED=""
OTHER=""
while IFS= read -r line; do
if [[ "$line" == feat* ]]; then
ADDED="$ADDED- ${line#*: }\n"
elif [[ "$line" == fix* ]]; then
FIXED="$FIXED- ${line#*: }\n"
else
OTHER="$OTHER- $line\n"
fi
done <<< "$COMMIT_LOG"
if [ -n "$ADDED" ]; then
CHANGELOG_ENTRY="${CHANGELOG_ENTRY}### Added\n$ADDED\n"
fi
if [ -n "$FIXED" ]; then
CHANGELOG_ENTRY="${CHANGELOG_ENTRY}### Fixed\n$FIXED\n"
fi
if [ -n "$OTHER" ]; then
CHANGELOG_ENTRY="${CHANGELOG_ENTRY}### Other\n$OTHER\n"
fi
echo -e "\nGenerated CHANGELOG entry:\n━━━━━━━━━━━━━━━━━━━━━━━━━━━\n$CHANGELOG_ENTRY━━━━━━━━━━━━━━━━━━━━━━━━━━━"
# --- Execution ---
GEMINI_EXTENSION_PATH="gemini-extension.json"
CHANGELOG_PATH="CHANGELOG.md"
if [ "$PREVIEW" = true ]; then
echo -e "\nPreview mode enabled. The following actions would be taken:"
echo " - Bump version in $PACKAGE_JSON_PATH to $NEW_VERSION"
echo " - Bump version in $GEMINI_EXTENSION_PATH to $NEW_VERSION (if it exists)"
echo " - Prepend the generated entry to $CHANGELOG_PATH"
echo " - git add (conditionally including $GEMINI_EXTENSION_PATH if it exists)"
echo " - git commit -m \"chore(release): v$NEW_VERSION\""
echo " - git tag v$NEW_VERSION"
echo " - git push origin HEAD --follow-tags"
exit 0
fi
read -p "Proceed with release? [y/N] " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo "Release cancelled."
exit 1
fi
echo "Proceeding with release..."
# Update package.json
jq --arg v "$NEW_VERSION" '.version = $v' "$PACKAGE_JSON_PATH" > tmp.$$.json && mv tmp.$$.json "$PACKAGE_JSON_PATH"
echo "Updated $PACKAGE_JSON_PATH"
# Update gemini-extension.json
if [ -f "$GEMINI_EXTENSION_PATH" ]; then
jq --arg v "$NEW_VERSION" '.version = $v' "$GEMINI_EXTENSION_PATH" > tmp.$$.json && mv tmp.$$.json "$GEMINI_EXTENSION_PATH"
echo "Updated $GEMINI_EXTENSION_PATH"
fi
# Update CHANGELOG.md
if [ ! -f "$CHANGELOG_PATH" ]; then
echo -e "# Changelog\n\nAll notable changes to this project will be documented in this file.\n" > "$CHANGELOG_PATH"
fi
echo -e "$CHANGELOG_ENTRY$(cat $CHANGELOG_PATH)" > "$CHANGELOG_PATH"
echo "Updated $CHANGELOG_PATH"
# Git operations
echo "Committing changes..."
FILES_TO_ADD=("$PACKAGE_JSON_PATH" "$CHANGELOG_PATH")
if [ -f "$GEMINI_EXTENSION_PATH" ]; then
FILES_TO_ADD+=("$GEMINI_EXTENSION_PATH")
fi
git add "${FILES_TO_ADD[@]}"
git commit -m "chore(release): v$NEW_VERSION"
echo "Creating git tag..."
git tag "v$NEW_VERSION"
echo "Pushing changes and tag..."
git push origin HEAD --follow-tags
echo "Release complete."