From 386fd2cd1151b4e98bc5b469fb7595dcf6ac4af8 Mon Sep 17 00:00:00 2001 From: David Snelling Date: Wed, 1 Oct 2025 13:26:04 -0700 Subject: [PATCH] feat: implement simpler, more reliable release workflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add scripts/release.sh for automated build → test → commit → push → publish → release - Fix .versionrc.json types configuration (was causing 'types.find is not a function' error) - Remove problematic precommit/postcommit hooks that ran full test suite during release - Keep standard-version as fallback option (npm run release:standard-version:*) - New workflow is faster, more reliable, and easier to debug Usage: npm run release # patch release (3.20.4 → 3.20.5) npm run release:minor # minor release (3.20.4 → 3.21.0) npm run release:major # major release (3.20.4 → 4.0.0) npm run release:dry # dry-run mode (no changes) --- .versionrc.json | 62 ++++--------------- package.json | 14 +++-- scripts/release.sh | 148 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 170 insertions(+), 54 deletions(-) create mode 100755 scripts/release.sh diff --git a/.versionrc.json b/.versionrc.json index 24da1955..dac6ceca 100644 --- a/.versionrc.json +++ b/.versionrc.json @@ -1,48 +1,16 @@ { - "types": { - "feat": { - "description": "✨ New Features", - "title": "✨ Features" - }, - "fix": { - "description": "🐛 Bug Fixes", - "title": "🐛 Bug Fixes" - }, - "docs": { - "description": "📚 Documentation", - "title": "📚 Documentation" - }, - "style": { - "description": "💄 Code Style", - "title": "💄 Styles", - "hidden": true - }, - "refactor": { - "description": "♻️ Code Refactoring", - "title": "♻️ Code Refactoring" - }, - "perf": { - "description": "⚡ Performance Improvements", - "title": "⚡ Performance Improvements" - }, - "test": { - "description": "✅ Tests", - "title": "✅ Tests" - }, - "build": { - "description": "🔧 Build System", - "title": "🔧 Build System" - }, - "ci": { - "description": "🔄 CI/CD", - "title": "🔄 CI/CD" - }, - "chore": { - "description": "🔧 Chores", - "title": "🔧 Chores", - "hidden": true - } - }, + "types": [ + {"type": "feat", "section": "✨ Features"}, + {"type": "fix", "section": "🐛 Bug Fixes"}, + {"type": "docs", "section": "📚 Documentation"}, + {"type": "refactor", "section": "♻️ Code Refactoring"}, + {"type": "perf", "section": "⚡ Performance Improvements"}, + {"type": "test", "section": "✅ Tests"}, + {"type": "build", "section": "🔧 Build System"}, + {"type": "ci", "section": "🔄 CI/CD"}, + {"type": "style", "hidden": true}, + {"type": "chore", "hidden": true} + ], "compareUrlFormat": "https://github.com/soulcraftlabs/brainy/compare/{{previousTag}}...{{currentTag}}", "commitUrlFormat": "https://github.com/soulcraftlabs/brainy/commit/{{hash}}", "issueUrlFormat": "https://github.com/soulcraftlabs/brainy/issues/{{id}}", @@ -51,10 +19,6 @@ "issuePrefixes": ["#"], "header": "# Changelog\n\nAll notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.\n", "scripts": { - "postbump": "echo 'Version bumped to' $(node -p \"require('./package.json').version\")", - "precommit": "npm run build && npm test", - "postcommit": "echo 'Release commit created. Ready to push and publish!'", - "pretag": "echo 'Creating tag...'", - "posttag": "echo 'Tag created. Use: git push --follow-tags origin main && npm publish'" + "postbump": "echo '✅ Version bumped to' $(node -p \"require('./package.json').version\")" } } \ No newline at end of file diff --git a/package.json b/package.json index cb019552..157b2cab 100644 --- a/package.json +++ b/package.json @@ -81,11 +81,15 @@ "format:check": "prettier --check \"src/**/*.{ts,js}\"", "migrate:logger": "tsx scripts/migrate-to-structured-logger.ts", "migrate:logger:dry": "tsx scripts/migrate-to-structured-logger.ts --dry-run", - "release": "standard-version", - "release:patch": "standard-version --release-as patch", - "release:minor": "standard-version --release-as minor", - "release:major": "standard-version --release-as major", - "release:dry": "standard-version --dry-run" + "release": "./scripts/release.sh patch", + "release:patch": "./scripts/release.sh patch", + "release:minor": "./scripts/release.sh minor", + "release:major": "./scripts/release.sh major", + "release:dry": "./scripts/release.sh patch --dry-run", + "release:standard-version": "standard-version", + "release:standard-version:patch": "standard-version --release-as patch", + "release:standard-version:minor": "standard-version --release-as minor", + "release:standard-version:major": "standard-version --release-as major" }, "keywords": [ "ai-database", diff --git a/scripts/release.sh b/scripts/release.sh new file mode 100755 index 00000000..bf0ea4cf --- /dev/null +++ b/scripts/release.sh @@ -0,0 +1,148 @@ +#!/bin/bash +set -e # Exit on error + +# Brainy Release Script +# Simple, reliable release workflow: build → test → commit → push → publish → release + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Parse arguments +RELEASE_TYPE="${1:-patch}" # patch, minor, or major +DRY_RUN="${2}" + +echo -e "${BLUE}🚀 Brainy Release Script${NC}" +echo -e "${BLUE}Release type: ${RELEASE_TYPE}${NC}\n" + +if [ "$DRY_RUN" == "--dry-run" ]; then + echo -e "${YELLOW}⚠️ DRY RUN MODE - No changes will be made${NC}\n" +fi + +# Step 1: Verify clean git state +echo -e "${BLUE}1️⃣ Checking git status...${NC}" +if [ -n "$(git status --porcelain)" ]; then + echo -e "${RED}❌ Working directory not clean. Commit or stash changes first.${NC}" + exit 1 +fi +echo -e "${GREEN}✅ Working directory clean${NC}\n" + +# Step 2: Build +echo -e "${BLUE}2️⃣ Building project...${NC}" +if [ "$DRY_RUN" != "--dry-run" ]; then + npm run build +fi +echo -e "${GREEN}✅ Build successful${NC}\n" + +# Step 3: Test +echo -e "${BLUE}3️⃣ Running tests...${NC}" +if [ "$DRY_RUN" != "--dry-run" ]; then + npm test +fi +echo -e "${GREEN}✅ Tests passed${NC}\n" + +# Step 4: Get current and new version +CURRENT_VERSION=$(node -p "require('./package.json').version") +echo -e "${BLUE}Current version: ${CURRENT_VERSION}${NC}" + +# Calculate new version +IFS='.' read -r -a VERSION_PARTS <<< "$CURRENT_VERSION" +MAJOR="${VERSION_PARTS[0]}" +MINOR="${VERSION_PARTS[1]}" +PATCH="${VERSION_PARTS[2]}" + +case $RELEASE_TYPE in + major) + NEW_VERSION="$((MAJOR + 1)).0.0" + ;; + minor) + NEW_VERSION="${MAJOR}.$((MINOR + 1)).0" + ;; + patch) + NEW_VERSION="${MAJOR}.${MINOR}.$((PATCH + 1))" + ;; + *) + echo -e "${RED}❌ Invalid release type: ${RELEASE_TYPE}${NC}" + echo "Usage: ./scripts/release.sh [patch|minor|major] [--dry-run]" + exit 1 + ;; +esac + +echo -e "${BLUE}New version: ${NEW_VERSION}${NC}\n" + +if [ "$DRY_RUN" == "--dry-run" ]; then + echo -e "${YELLOW}DRY RUN: Would release version ${NEW_VERSION}${NC}" + exit 0 +fi + +# Step 5: Bump version in package files +echo -e "${BLUE}4️⃣ Bumping version to ${NEW_VERSION}...${NC}" +npm version $NEW_VERSION --no-git-tag-version +echo -e "${GREEN}✅ Version bumped${NC}\n" + +# Step 6: Update CHANGELOG +echo -e "${BLUE}5️⃣ Updating CHANGELOG...${NC}" +# Get commits since last tag +LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "") +if [ -z "$LAST_TAG" ]; then + COMMITS=$(git log --oneline --pretty=format:"- %s (%h)") +else + COMMITS=$(git log ${LAST_TAG}..HEAD --oneline --pretty=format:"- %s (%h)") +fi + +# Create new changelog entry +CHANGELOG_ENTRY="### [${NEW_VERSION}](https://github.com/soulcraftlabs/brainy/compare/v${CURRENT_VERSION}...v${NEW_VERSION}) ($(date +%Y-%m-%d)) + +${COMMITS} +" + +# Prepend to CHANGELOG.md after header +if [ -f "CHANGELOG.md" ]; then + # Read header (first 4 lines) + HEADER=$(head -n 4 CHANGELOG.md) + # Read rest of file + REST=$(tail -n +5 CHANGELOG.md) + # Write new CHANGELOG + echo "$HEADER" > CHANGELOG.md + echo "" >> CHANGELOG.md + echo "$CHANGELOG_ENTRY" >> CHANGELOG.md + echo "" >> CHANGELOG.md + echo "$REST" >> CHANGELOG.md +fi +echo -e "${GREEN}✅ CHANGELOG updated${NC}\n" + +# Step 7: Create release commit +echo -e "${BLUE}6️⃣ Creating release commit...${NC}" +git add package.json package-lock.json CHANGELOG.md +git commit -m "chore(release): ${NEW_VERSION}" +echo -e "${GREEN}✅ Release commit created${NC}\n" + +# Step 8: Create git tag +echo -e "${BLUE}7️⃣ Creating git tag v${NEW_VERSION}...${NC}" +git tag "v${NEW_VERSION}" +echo -e "${GREEN}✅ Tag created${NC}\n" + +# Step 9: Push to GitHub +echo -e "${BLUE}8️⃣ Pushing to GitHub...${NC}" +git push --follow-tags origin main +echo -e "${GREEN}✅ Pushed to GitHub${NC}\n" + +# Step 10: Publish to npm +echo -e "${BLUE}9️⃣ Publishing to npm...${NC}" +npm publish +echo -e "${GREEN}✅ Published to npm${NC}\n" + +# Step 11: Create GitHub release +echo -e "${BLUE}🔟 Creating GitHub release...${NC}" +gh release create "v${NEW_VERSION}" --generate-notes +echo -e "${GREEN}✅ GitHub release created${NC}\n" + +echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" +echo -e "${GREEN}🎉 Release ${NEW_VERSION} complete!${NC}" +echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" +echo "" +echo -e "📦 npm: ${BLUE}https://www.npmjs.com/package/@soulcraft/brainy/v/${NEW_VERSION}${NC}" +echo -e "🐙 GitHub: ${BLUE}https://github.com/soulcraftlabs/brainy/releases/tag/v${NEW_VERSION}${NC}"