feat: implement automated versioning.

This commit is contained in:
Xiaohan-Tian
2025-08-28 22:23:47 -07:00
parent 62b3a8c8d7
commit 0eac49493c
9 changed files with 7586 additions and 1 deletions
+197
View File
@@ -0,0 +1,197 @@
name: Release
on:
workflow_dispatch:
inputs:
release_type:
description: 'Release type'
required: true
default: 'patch'
type: choice
options:
- patch
- minor
- major
jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Check authorization
run: |
# List of authorized GitHub usernames (add your username here)
AUTHORIZED_USERS="Xiaohan-Tian"
if [[ ",$AUTHORIZED_USERS," != *",${{ github.actor }},"* ]]; then
echo "❌ Unauthorized user: ${{ github.actor }}"
echo "Only the following users can trigger this workflow: $AUTHORIZED_USERS"
exit 1
fi
echo "✅ Authorized user: ${{ github.actor }}"
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20.19.3'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Configure git
run: |
git config user.name "GitHub Actions Bot"
git config user.email "actions@github.com"
- name: Generate date-based prerelease version
id: version
run: |
# Get current version from package.json
CURRENT_VERSION=$(node -p "require('./package.json').version")
# Extract major.minor.patch
if [[ $CURRENT_VERSION =~ ^([0-9]+)\.([0-9]+)\.([0-9]+) ]]; then
MAJOR=${BASH_REMATCH[1]}
MINOR=${BASH_REMATCH[2]}
PATCH=${BASH_REMATCH[3]}
else
echo "Invalid version format: $CURRENT_VERSION"
exit 1
fi
# Bump version based on input
case "${{ github.event.inputs.release_type }}" in
major)
MAJOR=$((MAJOR + 1))
MINOR=0
PATCH=0
;;
minor)
MINOR=$((MINOR + 1))
PATCH=0
;;
patch)
PATCH=$((PATCH + 1))
;;
esac
# Generate date-based build suffix
BUILD_DATE=$(date -u '+%Y%m%d')
NEW_VERSION="${MAJOR}.${MINOR}.${PATCH}-build.${BUILD_DATE}"
echo "version=${NEW_VERSION}" >> $GITHUB_OUTPUT
echo "Generated version: ${NEW_VERSION}"
- name: Update package.json version
run: |
NEW_VERSION="${{ steps.version.outputs.version }}"
npm version $NEW_VERSION --no-git-tag-version
echo "Updated package.json to version: $NEW_VERSION"
- name: Generate changelog
run: |
# Get last release tag
LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
if [ -z "$LAST_TAG" ]; then
echo "No previous tags found, generating full changelog"
COMMIT_RANGE=""
else
echo "Last tag: $LAST_TAG"
COMMIT_RANGE="${LAST_TAG}..HEAD"
fi
# Generate changelog entry
NEW_VERSION="${{ steps.version.outputs.version }}"
RELEASE_DATE=$(date -u '+%Y-%m-%d')
# Create changelog entry
echo "# [$NEW_VERSION] ($RELEASE_DATE)" > changelog_entry.md
echo "" >> changelog_entry.md
if [ -z "$COMMIT_RANGE" ]; then
git log --oneline --pretty=format:"* %s (%h)" >> changelog_entry.md
else
git log ${COMMIT_RANGE} --oneline --pretty=format:"* %s (%h)" >> changelog_entry.md
fi
# Update or create CHANGELOG.md
if [ -f "CHANGELOG.md" ]; then
# Prepend new entry to existing changelog
echo "" >> changelog_entry.md
cat CHANGELOG.md >> changelog_entry.md
mv changelog_entry.md CHANGELOG.md
else
# Create new changelog
echo "# Changelog" > CHANGELOG.md
echo "" >> CHANGELOG.md
echo "All notable changes to this project will be documented in this file." >> CHANGELOG.md
echo "" >> CHANGELOG.md
cat changelog_entry.md >> CHANGELOG.md
fi
- name: Commit and tag release
run: |
NEW_VERSION="${{ steps.version.outputs.version }}"
# Add updated files
git add package.json CHANGELOG.md
# Commit changes
git commit -m "chore(release): ${NEW_VERSION}" \
-m "Generated release with automated versioning system." \
-m "Release type: ${{ github.event.inputs.release_type }}" \
-m "Build date: $(date -u '+%Y-%m-%d %H:%M:%S UTC')" \
-m "🤖 Generated with automated release workflow"
# Create tag
git tag -a "v${NEW_VERSION}" -m "Release ${NEW_VERSION}"
# Push changes and tag
git push origin main
git push origin "v${NEW_VERSION}"
echo "✅ Released version: ${NEW_VERSION}"
- name: Create GitHub release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: v${{ steps.version.outputs.version }}
release_name: Release ${{ steps.version.outputs.version }}
body: |
## Release ${{ steps.version.outputs.version }}
**Release Type:** ${{ github.event.inputs.release_type }}
**Build Date:** $(date -u '+%Y-%m-%d')
### Changes
See [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/main/CHANGELOG.md) for detailed changes.
---
🤖 Generated with automated release workflow
draft: false
prerelease: true
- name: Summary
run: |
NEW_VERSION="${{ steps.version.outputs.version }}"
echo "🚀 Release Summary:"
echo "- Version: ${NEW_VERSION}"
echo "- Type: ${{ github.event.inputs.release_type }}"
echo "- Tag: v${NEW_VERSION}"
echo "- CHANGELOG.md updated"
echo "- GitHub release created"
echo ""
echo "Next steps:"
echo "1. Review the release at: https://github.com/${{ github.repository }}/releases/tag/v${NEW_VERSION}"
echo "2. Run the 'Deploy to GitHub Pages' workflow when ready to deploy"
+56
View File
@@ -0,0 +1,56 @@
{
"branches": ["main"],
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
[
"@semantic-release/changelog",
{
"changelogFile": "CHANGELOG.md",
"changelogTitle": "# Changelog\n\nAll notable changes to this project will be documented in this file."
}
],
[
"@semantic-release/npm",
{
"npmPublish": false
}
],
[
"@semantic-release/git",
{
"assets": ["CHANGELOG.md", "package.json"],
"message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
}
],
"@semantic-release/github"
],
"preset": "conventionalcommits",
"presetConfig": {
"types": [
{ "type": "feat", "section": "Features" },
{ "type": "fix", "section": "Bug Fixes" },
{ "type": "chore", "hidden": true },
{ "type": "docs", "section": "Documentation" },
{ "type": "style", "hidden": true },
{ "type": "refactor", "section": "Code Refactoring" },
{ "type": "perf", "section": "Performance Improvements" },
{ "type": "test", "hidden": true }
]
},
"releaseRules": [
{ "type": "feat", "release": "minor" },
{ "type": "fix", "release": "patch" },
{ "type": "perf", "release": "patch" },
{ "type": "refactor", "release": "patch" },
{ "type": "docs", "release": false },
{ "type": "test", "release": false },
{ "type": "chore", "release": false }
],
"generateNotes": {
"preset": "conventionalcommits",
"writerOpts": {
"commitPartial": "* {{#if scope}}**{{scope}}:** {{/if}}{{subject}} ({{hash}})"
}
}
}
+19
View File
@@ -0,0 +1,19 @@
# Changelog
All notable changes to this project will be documented in this file.
## [0.5.0-build.20250829] (2025-08-29)
### Initial Release Setup
* fix: reset mute/solo UI states on project/track changes (62b3a8c)
* fix: preserve overlapping notes with same end time in ABC conversion (1fd1486)
* feat: implemented select all notes feature (6445325)
* feat: implemented Claude caching breakpoints (OpenRouter version) (b0e589d)
* feat: implemented ClaudeOpenRouterProvider (efb161d)
* feat: added a configuration option for Claude through OpenRouter (81c6aeb)
* docs: added Disclaimer section to README (efee261)
### Setup Notes
This is the initial setup of automated versioning and changelog generation. Future releases will be automatically managed through the GitHub Actions workflow.
+7295
View File
File diff suppressed because it is too large Load Diff
+4
View File
@@ -24,14 +24,18 @@
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.29.0", "@eslint/js": "^9.29.0",
"@types/node": "^22.9.3",
"@types/react": "^19.1.8", "@types/react": "^19.1.8",
"@types/react-dom": "^19.1.6", "@types/react-dom": "^19.1.6",
"@types/react-syntax-highlighter": "^15.5.13", "@types/react-syntax-highlighter": "^15.5.13",
"@vitejs/plugin-react": "^4.5.2", "@vitejs/plugin-react": "^4.5.2",
"@semantic-release/changelog": "^6.0.3",
"@semantic-release/git": "^10.0.1",
"eslint": "^9.29.0", "eslint": "^9.29.0",
"eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-hooks": "^5.2.0",
"eslint-plugin-react-refresh": "^0.4.20", "eslint-plugin-react-refresh": "^0.4.20",
"globals": "^16.2.0", "globals": "^16.2.0",
"semantic-release": "^21.1.2",
"typescript": "~5.8.3", "typescript": "~5.8.3",
"typescript-eslint": "^8.34.1", "typescript-eslint": "^8.34.1",
"vite": "^7.0.0" "vite": "^7.0.0"
+1 -1
View File
@@ -10,7 +10,7 @@ const StatusBar: React.FC = () => {
{currentStatus} {currentStatus}
</div> </div>
<div className="status-right"> <div className="status-right">
<span>K.G.Studio</span> <span>K.G.Studio (v{__APP_VERSION__})</span>
</div> </div>
</div> </div>
); );
+2
View File
@@ -1 +1,3 @@
/// <reference types="vite/client" /> /// <reference types="vite/client" />
declare const __APP_VERSION__: string
+1
View File
@@ -5,6 +5,7 @@
"lib": ["ES2023"], "lib": ["ES2023"],
"module": "ESNext", "module": "ESNext",
"skipLibCheck": true, "skipLibCheck": true,
"types": ["node"],
/* Bundler mode */ /* Bundler mode */
"moduleResolution": "bundler", "moduleResolution": "bundler",
+11
View File
@@ -1,8 +1,19 @@
import { defineConfig } from 'vite' import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react' import react from '@vitejs/plugin-react'
import { readFileSync } from 'node:fs'
import { resolve } from 'node:path'
import { fileURLToPath, URL } from 'node:url'
// Read version from package.json
const __dirname = fileURLToPath(new URL('.', import.meta.url))
const packageJson = JSON.parse(readFileSync(resolve(__dirname, 'package.json'), 'utf-8'))
const version = packageJson.version
// https://vite.dev/config/ // https://vite.dev/config/
export default defineConfig({ export default defineConfig({
plugins: [react()], plugins: [react()],
base: '/kgstudio/', base: '/kgstudio/',
define: {
__APP_VERSION__: JSON.stringify(version),
},
}) })