mirror of
https://github.com/nextlevelbuilder/ui-ux-pro-max-skill.git
synced 2026-07-21 21:47:45 +00:00
feat(release): add semantic release automation (#375)
* feat(release): add semantic release automation * fix(release): disable npm publishing * ci: remove obsolete conda workflow * ci: remove Claude review workflows --------- Co-authored-by: Mỹ Ngân <bot@goclaw.dev> Co-authored-by: Mỹ Ngân <my-ngan@goclaw.local>
This commit is contained in:
parent
53d670cd30
commit
c0fca2efdc
44
.github/workflows/claude-code-review.yml
vendored
44
.github/workflows/claude-code-review.yml
vendored
@ -1,44 +0,0 @@
|
||||
name: Claude Code Review
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, ready_for_review, reopened]
|
||||
# Optional: Only run on specific file changes
|
||||
# paths:
|
||||
# - "src/**/*.ts"
|
||||
# - "src/**/*.tsx"
|
||||
# - "src/**/*.js"
|
||||
# - "src/**/*.jsx"
|
||||
|
||||
jobs:
|
||||
claude-review:
|
||||
# Optional: Filter by PR author
|
||||
# if: |
|
||||
# github.event.pull_request.user.login == 'external-contributor' ||
|
||||
# github.event.pull_request.user.login == 'new-developer' ||
|
||||
# github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR'
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
issues: read
|
||||
id-token: write
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Run Claude Code Review
|
||||
id: claude-review
|
||||
uses: anthropics/claude-code-action@v1
|
||||
with:
|
||||
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
||||
plugin_marketplaces: 'https://github.com/anthropics/claude-code.git'
|
||||
plugins: 'code-review@claude-code-plugins'
|
||||
prompt: '/code-review:code-review ${{ github.repository }}/pull/${{ github.event.pull_request.number }}'
|
||||
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
|
||||
# or https://code.claude.com/docs/en/cli-reference for available options
|
||||
|
||||
50
.github/workflows/claude.yml
vendored
50
.github/workflows/claude.yml
vendored
@ -1,50 +0,0 @@
|
||||
name: Claude Code
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
pull_request_review_comment:
|
||||
types: [created]
|
||||
issues:
|
||||
types: [opened, assigned]
|
||||
pull_request_review:
|
||||
types: [submitted]
|
||||
|
||||
jobs:
|
||||
claude:
|
||||
if: |
|
||||
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
|
||||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
|
||||
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
|
||||
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
issues: read
|
||||
id-token: write
|
||||
actions: read # Required for Claude to read CI results on PRs
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Run Claude Code
|
||||
id: claude
|
||||
uses: anthropics/claude-code-action@v1
|
||||
with:
|
||||
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
||||
|
||||
# This is an optional setting that allows Claude to read CI results on PRs
|
||||
additional_permissions: |
|
||||
actions: read
|
||||
|
||||
# Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it.
|
||||
# prompt: 'Update the pull request description to include a summary of changes.'
|
||||
|
||||
# Optional: Add claude_args to customize behavior and configuration
|
||||
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
|
||||
# or https://code.claude.com/docs/en/cli-reference for available options
|
||||
# claude_args: '--allowed-tools Bash(gh pr:*)'
|
||||
|
||||
39
.github/workflows/python-package-conda.yml
vendored
39
.github/workflows/python-package-conda.yml
vendored
@ -1,39 +0,0 @@
|
||||
name: Python Package using Conda
|
||||
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- '**/*.md'
|
||||
- 'docs/**'
|
||||
- '.claude/**'
|
||||
|
||||
jobs:
|
||||
build-linux:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
max-parallel: 5
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Python 3.10
|
||||
uses: actions/setup-python@v3
|
||||
with:
|
||||
python-version: '3.10'
|
||||
- name: Add conda to system path
|
||||
run: |
|
||||
# $CONDA is an environment variable pointing to the root of the miniconda directory
|
||||
echo $CONDA/bin >> $GITHUB_PATH
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
conda env update --file environment.yml --name base
|
||||
- name: Lint with flake8
|
||||
run: |
|
||||
conda install flake8
|
||||
# stop the build if there are Python syntax errors or undefined names
|
||||
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
|
||||
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
|
||||
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
|
||||
- name: Test with pytest
|
||||
run: |
|
||||
conda install pytest
|
||||
pytest
|
||||
64
.github/workflows/release.yml
vendored
Normal file
64
.github/workflows/release.yml
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- dev
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
issues: write
|
||||
pull-requests: write
|
||||
id-token: write
|
||||
|
||||
concurrency:
|
||||
group: release-${{ github.ref }}
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
release:
|
||||
name: Semantic release
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'nextlevelbuilder/ui-ux-pro-max-skill'
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Bun
|
||||
uses: oven-sh/setup-bun@v2
|
||||
with:
|
||||
bun-version: latest
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '22'
|
||||
cache: npm
|
||||
cache-dependency-path: cli/package-lock.json
|
||||
|
||||
- name: Install CLI dependencies
|
||||
working-directory: cli
|
||||
run: npm ci
|
||||
|
||||
- name: Build CLI
|
||||
working-directory: cli
|
||||
run: bun run build
|
||||
|
||||
- name: Run semantic-release
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: npx --yes \
|
||||
-p semantic-release \
|
||||
-p @semantic-release/commit-analyzer \
|
||||
-p @semantic-release/release-notes-generator \
|
||||
-p @semantic-release/changelog \
|
||||
-p @semantic-release/exec \
|
||||
-p @semantic-release/git \
|
||||
-p @semantic-release/github \
|
||||
-p conventional-changelog-conventionalcommits \
|
||||
semantic-release
|
||||
58
.releaserc.json
Normal file
58
.releaserc.json
Normal file
@ -0,0 +1,58 @@
|
||||
{
|
||||
"branches": [
|
||||
"main",
|
||||
{
|
||||
"name": "dev",
|
||||
"channel": "beta",
|
||||
"prerelease": "beta"
|
||||
}
|
||||
],
|
||||
"tagFormat": "v${version}",
|
||||
"plugins": [
|
||||
[
|
||||
"@semantic-release/commit-analyzer",
|
||||
{
|
||||
"preset": "conventionalcommits"
|
||||
}
|
||||
],
|
||||
[
|
||||
"@semantic-release/release-notes-generator",
|
||||
{
|
||||
"preset": "conventionalcommits"
|
||||
}
|
||||
],
|
||||
[
|
||||
"@semantic-release/changelog",
|
||||
{
|
||||
"changelogFile": "CHANGELOG.md"
|
||||
}
|
||||
],
|
||||
[
|
||||
"@semantic-release/exec",
|
||||
{
|
||||
"prepareCmd": "node scripts/sync-release-version.mjs ${nextRelease.version}"
|
||||
}
|
||||
],
|
||||
[
|
||||
"@semantic-release/git",
|
||||
{
|
||||
"assets": [
|
||||
"CHANGELOG.md",
|
||||
"skill.json",
|
||||
".claude-plugin/plugin.json",
|
||||
".claude-plugin/marketplace.json",
|
||||
"cli/package.json",
|
||||
"cli/package-lock.json"
|
||||
],
|
||||
"message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
|
||||
}
|
||||
],
|
||||
[
|
||||
"@semantic-release/github",
|
||||
{
|
||||
"successComment": false,
|
||||
"failTitle": "Release failed for ${branch.name}"
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
18
README.md
18
README.md
@ -508,6 +508,24 @@ gh pr create
|
||||
|
||||
See [CLAUDE.md](CLAUDE.md) for detailed development guidelines.
|
||||
|
||||
|
||||
## Automated Releases
|
||||
|
||||
This repository uses semantic-release with Conventional Commits to create GitHub releases automatically:
|
||||
|
||||
- `dev` branch creates beta GitHub prereleases such as `2.6.0-beta.1`.
|
||||
- `main` branch creates official stable GitHub releases such as `2.6.0`.
|
||||
|
||||
Release notes and `CHANGELOG.md` are generated from Conventional Commit messages. Version numbers are synchronized across `skill.json`, `.claude-plugin/plugin.json`, `.claude-plugin/marketplace.json`, `cli/package.json`, and `cli/package-lock.json` during release preparation.
|
||||
|
||||
Use these commit types for correct version bumps:
|
||||
|
||||
- `fix:` -> patch release
|
||||
- `feat:` -> minor release
|
||||
- `feat!:` or `BREAKING CHANGE:` -> major release
|
||||
|
||||
The release workflow only needs the default `GITHUB_TOKEN`; it does not publish to npm.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### `uipro: unknown command 'uninstall'` or `unknown command 'update'`
|
||||
|
||||
77
scripts/sync-release-version.mjs
Executable file
77
scripts/sync-release-version.mjs
Executable file
@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env node
|
||||
import { readFileSync, writeFileSync } from 'node:fs';
|
||||
import { resolve } from 'node:path';
|
||||
|
||||
const version = process.argv[2];
|
||||
if (!version) {
|
||||
console.error('Usage: node scripts/sync-release-version.mjs <version>');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
function readJson(path) {
|
||||
return JSON.parse(readFileSync(resolve(path), 'utf8'));
|
||||
}
|
||||
|
||||
function replaceJsonVersion(path, updater) {
|
||||
const fullPath = resolve(path);
|
||||
const original = readFileSync(fullPath, 'utf8');
|
||||
const data = JSON.parse(original);
|
||||
updater(data);
|
||||
let next = original;
|
||||
const replacements = [];
|
||||
|
||||
function setTopLevelVersion(value) {
|
||||
replacements.push([/(\"version\"\s*:\s*)\"[^\"]+\"/, `$1\"${value}\"`]);
|
||||
}
|
||||
|
||||
function setMetadataVersion(value) {
|
||||
replacements.push([/(\"metadata\"\s*:\s*\{[\s\S]*?\"version\"\s*:\s*)\"[^\"]+\"/, `$1\"${value}\"`]);
|
||||
}
|
||||
|
||||
function setPluginVersions(value) {
|
||||
replacements.push([/(\"plugins\"\s*:\s*\[[\s\S]*?\"version\"\s*:\s*)\"[^\"]+\"/, `$1\"${value}\"`]);
|
||||
}
|
||||
|
||||
if (path === '.claude-plugin/marketplace.json') {
|
||||
setMetadataVersion(data.metadata?.version);
|
||||
if (data.plugins?.[0]?.version) setPluginVersions(data.plugins[0].version);
|
||||
} else {
|
||||
setTopLevelVersion(data.version);
|
||||
if (data.packages?.['']?.version) {
|
||||
replacements.push([/(\"packages\"\s*:\s*\{\s*\"\"\s*:\s*\{[\s\S]*?\"version\"\s*:\s*)\"[^\"]+\"/, `$1\"${data.packages[''].version}\"`]);
|
||||
}
|
||||
}
|
||||
|
||||
for (const [pattern, replacement] of replacements) next = next.replace(pattern, replacement);
|
||||
writeFileSync(fullPath, next);
|
||||
}
|
||||
|
||||
replaceJsonVersion('skill.json', (data) => {
|
||||
data.version = version;
|
||||
});
|
||||
|
||||
replaceJsonVersion('.claude-plugin/plugin.json', (data) => {
|
||||
data.version = version;
|
||||
});
|
||||
|
||||
replaceJsonVersion('.claude-plugin/marketplace.json', (data) => {
|
||||
if (data.metadata) data.metadata.version = version;
|
||||
if (Array.isArray(data.plugins)) {
|
||||
for (const item of data.plugins) item.version = version;
|
||||
}
|
||||
});
|
||||
|
||||
replaceJsonVersion('cli/package.json', (data) => {
|
||||
data.version = version;
|
||||
});
|
||||
|
||||
try {
|
||||
replaceJsonVersion('cli/package-lock.json', (data) => {
|
||||
data.version = version;
|
||||
if (data.packages?.['']) data.packages[''].version = version;
|
||||
});
|
||||
} catch (err) {
|
||||
if (err.code !== 'ENOENT') throw err;
|
||||
}
|
||||
|
||||
console.log(`Synced release version ${version} across skill, plugin, marketplace, and CLI manifests.`);
|
||||
Loading…
x
Reference in New Issue
Block a user