diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml index 0bed39c..518fd36 100644 --- a/.github/workflows/npm-publish.yml +++ b/.github/workflows/npm-publish.yml @@ -11,48 +11,112 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 0 + + - name: Parse release tag + id: tag + run: | + TAG="${{ github.event.release.tag_name }}" + if [[ "$TAG" != *"@"* ]]; then + echo "❌ Tag '$TAG' is not in package@version format" + exit 1 + fi + PACKAGE_NAME="${TAG%%@*}" + VERSION="${TAG#*@}" + echo "package=$PACKAGE_NAME" >> "$GITHUB_OUTPUT" + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + echo "Package: $PACKAGE_NAME" + echo "Version: $VERSION" + - name: Install GitVersion run: | curl -sL https://github.com/GitTools/GitVersion/releases/download/6.6.0/gitversion-linux-x64-6.6.0.tar.gz -o /tmp/gitversion.tar.gz tar xzf /tmp/gitversion.tar.gz -C /usr/local/bin gitversion chmod +x /usr/local/bin/gitversion + - uses: pnpm/action-setup@v4 - uses: actions/setup-node@v4 with: node-version: 24 registry-url: https://registry.npmjs.org/ cache: 'pnpm' + - run: pnpm audit - run: pnpm i --frozen-lockfile - run: pnpm run --if-present build --only - run: pnpm run --if-present type-check --only - run: pnpm run --if-present test --only - run: pnpm run ci - - name: Verify release tag matches package.json + + - name: Resolve package directory + id: package + env: + PACKAGE_NAME: ${{ steps.tag.outputs.package }} run: | - cd "apps/$(cat .packagename)" - VERSION=$(node -p "require('./package.json').version") - RELEASE_TAG="${{ github.event.release.tag_name }}" - echo "package.json version: $VERSION" - echo "Release tag: $RELEASE_TAG" - if [ "$VERSION" != "$RELEASE_TAG" ]; then - echo "❌ Version mismatch! Release tag does not match package.json" + PACKAGE_DIR=$(node -e " + const fs = require('fs'); + const name = process.env.PACKAGE_NAME; + const dirs = ['apps', 'packages'] + .flatMap(d => fs.readdirSync(d).map(p => d + '/' + p)) + .filter(d => { try { fs.statSync(d + '/package.json'); return true; } catch { return false; } }); + const match = dirs.find(d => { + const pkg = JSON.parse(fs.readFileSync(d + '/package.json', 'utf8')); + return pkg.name.split('/').pop() === name; + }); + if (!match) { process.stderr.write('No package found for: ' + name + '\\n'); process.exit(1); } + process.stdout.write(match); + ") + echo "dir=$PACKAGE_DIR" >> "$GITHUB_OUTPUT" + echo "Package directory: $PACKAGE_DIR" + + + - name: Verify changelog + run: | + CHANGELOG="${{ steps.package.outputs.dir }}/CHANGELOG.md" + if [ ! -f "$CHANGELOG" ]; then + echo "❌ No CHANGELOG.md found in ${{ steps.package.outputs.dir }}" + exit 1 + fi + # Strip pre-release suffix to get base version (e.g. 1.0.0-alpha.5 → 1.0.0) + BASE_VERSION=$(echo "${{ steps.tag.outputs.version }}" | sed 's/^\([0-9]*\.[0-9]*\.[0-9]*\).*/\1/') + FIRST_VERSION=$(grep -oE '^## \[[0-9]+\.[0-9]+\.[0-9]+\]' "$CHANGELOG" | head -n1 | sed 's/## \[\(.*\)\]/\1/') + if [ -z "$FIRST_VERSION" ]; then + echo "✅ No version entries yet — OK for pre-release" + exit 0 + fi + if [ "$BASE_VERSION" != "$FIRST_VERSION" ]; then + echo "❌ First changelog entry [$FIRST_VERSION] does not match release base version [$BASE_VERSION]" + exit 1 + fi + if ! grep -qE "^## \[$BASE_VERSION\] - [0-9]{4}-[0-9]{2}-[0-9]{2}$" "$CHANGELOG"; then + echo "❌ Entry ## [$BASE_VERSION] is missing a date (expected: ## [$BASE_VERSION] - YYYY-MM-DD)" + exit 1 + fi + echo "✅ Changelog OK" + + - name: Verify version matches tag + run: | + cd "${{ steps.package.outputs.dir }}" + PKG_VERSION=$(node -p "require('./package.json').version") + TAG_VERSION="${{ steps.tag.outputs.version }}" + echo "package.json version: $PKG_VERSION" + echo "Tag version: $TAG_VERSION" + if [ "$PKG_VERSION" != "$TAG_VERSION" ]; then + echo "❌ Version mismatch" exit 1 fi echo "✅ Versions match" - - run: | - . ./scripts/get-npm-tag.sh - cd "apps/$(cat .packagename)" + - name: Publish + run: | + . ./scripts/get-npm-tag.sh + cd "${{ steps.package.outputs.dir }}" VERSION=$(node -p "require('./package.json').version") - echo "Package version: $VERSION" TAG=$(get_npm_tag "$VERSION") if [ $? -ne 0 ]; then echo "Failed to get valid npm tag: $TAG" exit 1 fi echo "Publishing with tag: $TAG" - pnpm publish --ignore-scripts --no-git-checks --tag "$TAG" env: - NODE_AUTH_TOKEN: ${{secrets.npm_token}} + NODE_AUTH_TOKEN: ${{ secrets.npm_token }} diff --git a/.packagename b/.packagename deleted file mode 100644 index 676fc13..0000000 --- a/.packagename +++ /dev/null @@ -1 +0,0 @@ -claude-cli \ No newline at end of file diff --git a/apps/claude-cli/CHANGELOG.md b/apps/claude-cli/CHANGELOG.md new file mode 100644 index 0000000..1a58814 --- /dev/null +++ b/apps/claude-cli/CHANGELOG.md @@ -0,0 +1,3 @@ +# Changelog + +## [Unreleased] diff --git a/apps/claude-sdk-cli/CHANGELOG.md b/apps/claude-sdk-cli/CHANGELOG.md new file mode 100644 index 0000000..1a58814 --- /dev/null +++ b/apps/claude-sdk-cli/CHANGELOG.md @@ -0,0 +1,3 @@ +# Changelog + +## [Unreleased] diff --git a/apps/claude-sdk-cli/package.json b/apps/claude-sdk-cli/package.json index 62a7e9a..638c5dd 100644 --- a/apps/claude-sdk-cli/package.json +++ b/apps/claude-sdk-cli/package.json @@ -1,6 +1,6 @@ { "name": "@shellicar/claude-sdk-cli", - "version": "1.0.0-alpha.4", + "version": "1.0.0-alpha.5", "private": false, "description": "Interactive CLI for Claude AI built on the Anthropic SDK", "license": "MIT", diff --git a/lefthook.yml b/lefthook.yml index 861fb9a..56ff35c 100644 --- a/lefthook.yml +++ b/lefthook.yml @@ -8,6 +8,3 @@ pre-push: check: files: git diff --name-only origin/main...HEAD run: pnpm biome ci --diagnostic-level=error --no-errors-on-unmatched --colors=off {files} - scripts: - 'verify-version.sh': - runner: sh diff --git a/packages/claude-core/CHANGELOG.md b/packages/claude-core/CHANGELOG.md new file mode 100644 index 0000000..1a58814 --- /dev/null +++ b/packages/claude-core/CHANGELOG.md @@ -0,0 +1,3 @@ +# Changelog + +## [Unreleased] diff --git a/packages/claude-sdk-tools/CHANGELOG.md b/packages/claude-sdk-tools/CHANGELOG.md new file mode 100644 index 0000000..1a58814 --- /dev/null +++ b/packages/claude-sdk-tools/CHANGELOG.md @@ -0,0 +1,3 @@ +# Changelog + +## [Unreleased] diff --git a/packages/claude-sdk/CHANGELOG.md b/packages/claude-sdk/CHANGELOG.md new file mode 100644 index 0000000..1a58814 --- /dev/null +++ b/packages/claude-sdk/CHANGELOG.md @@ -0,0 +1,3 @@ +# Changelog + +## [Unreleased] diff --git a/packages/typescript-config/package.json b/packages/typescript-config/package.json index 2f2c126..be1177c 100644 --- a/packages/typescript-config/package.json +++ b/packages/typescript-config/package.json @@ -1,7 +1,7 @@ { "name": "@shellicar/typescript-config", "version": "0.0.0", - "private": "true", + "private": true, "exports": { "./base.json": "./base.json" }, diff --git a/scripts/verify-version.sh b/scripts/verify-version.sh deleted file mode 100755 index e85bdfc..0000000 --- a/scripts/verify-version.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/sh -# Verify that package.json version matches gitversion -# -# Usage: -# scripts/verify-version.sh - -set -e - -# Get full version from package.json -PACKAGE_DIR="apps/$(cat .packagename)" -full_version=$(node -p "JSON.parse(require('fs').readFileSync('$PACKAGE_DIR/package.json')).version") - -# Extract base version (x.y.z) stripping any prerelease suffix -base_version=$(echo "$full_version" | sed 's/^\([0-9]\+\.[0-9]\+\.[0-9]\+\).*/\1/') - -# Get version from gitversion -if command -v gitversion >/dev/null 2>&1; then - GITVERSION=gitversion -elif command -v dotnet-gitversion >/dev/null 2>&1; then - GITVERSION=dotnet-gitversion -else - echo "❌ gitversion not found" >&2 - exit 1 -fi - -gitversion_output=$($GITVERSION /showvariable SemVer) - -if [ "$base_version" = "$gitversion_output" ]; then - echo "✅ Version match: $base_version (package.json: $full_version)" -else - echo "❌ Version mismatch" >&2 - echo " package.json base: $base_version (full: $full_version)" >&2 - echo " gitversion: $gitversion_output" >&2 - exit 1 -fi