diff --git a/.github/workflows/auto-release.yml b/.github/workflows/auto-release.yml index 6065a86..06c7b35 100644 --- a/.github/workflows/auto-release.yml +++ b/.github/workflows/auto-release.yml @@ -1,91 +1,166 @@ name: Auto Release on: - pull_request: - types: [closed] + push: branches: [main] permissions: contents: write jobs: - auto-tag: - name: Auto Tag Patch Release - # Only run if PR was merged (not just closed) - if: github.event.pull_request.merged == true + version: + name: Determine Version runs-on: ubuntu-latest + if: "!startsWith(github.event.head_commit.message, 'chore(release):')" + outputs: + tag: ${{ steps.version.outputs.next }} + version: ${{ steps.version.outputs.version }} steps: - - name: Checkout - uses: actions/checkout@v4 + - uses: actions/checkout@v4 with: fetch-depth: 0 - token: ${{ secrets.GITHUB_TOKEN }} - - name: Setup Git - run: | - git config user.name "github-actions[bot]" - git config user.email "github-actions[bot]@users.noreply.github.com" + - name: Setup Bun + uses: oven-sh/setup-bun@v2 + with: + bun-version: latest - - name: Get current version - id: current - run: | - VERSION=$(jq -r '.version' package.json) - echo "version=$VERSION" >> $GITHUB_OUTPUT - echo "Current version: $VERSION" + - name: Install Just + uses: extractions/setup-just@v2 - - name: Calculate next patch version - id: next - run: | - CURRENT="${{ steps.current.outputs.version }}" - # Split version into parts - IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT" - # Increment patch - NEXT_PATCH=$((PATCH + 1)) - NEXT_VERSION="${MAJOR}.${MINOR}.${NEXT_PATCH}" - echo "version=$NEXT_VERSION" >> $GITHUB_OUTPUT - echo "Next version: $NEXT_VERSION" - - - name: Check if tag already exists - id: check_tag + - name: Determine next version + id: version run: | - if git rev-parse "v${{ steps.next.outputs.version }}" >/dev/null 2>&1; then - echo "exists=true" >> $GITHUB_OUTPUT - echo "Tag v${{ steps.next.outputs.version }} already exists, skipping" + latest_tag=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0") + echo "latest=$latest_tag" >> "$GITHUB_OUTPUT" + + version="${latest_tag#v}" + IFS='.' read -r major minor patch <<< "$version" + + commits=$(git log "$latest_tag"..HEAD --pretty=format:"%s" 2>/dev/null || git log --pretty=format:"%s") + + if echo "$commits" | grep -qE "^feat(\(.+\))?!:|^fix(\(.+\))?!:|^refactor(\(.+\))?!:|BREAKING CHANGE"; then + major=$((major + 1)) + minor=0 + patch=0 + elif echo "$commits" | grep -qE "^feat(\(.+\))?:"; then + minor=$((minor + 1)) + patch=0 else - echo "exists=false" >> $GITHUB_OUTPUT + patch=$((patch + 1)) fi - - name: Update package.json version - if: steps.check_tag.outputs.exists == 'false' + next="v${major}.${minor}.${patch}" + echo "next=$next" >> "$GITHUB_OUTPUT" + echo "version=${major}.${minor}.${patch}" >> "$GITHUB_OUTPUT" + echo "Next version: $next (from $latest_tag)" + + - name: Update versions run: | - jq '.version = "${{ steps.next.outputs.version }}"' package.json > package.json.tmp - mv package.json.tmp package.json - cat package.json | head -5 + bun install --frozen-lockfile + just set-version ${{ steps.version.outputs.version }} - - name: Commit version bump - if: steps.check_tag.outputs.exists == 'false' + - name: Verify run: | - git add package.json - git commit -m "chore(release): bump version to ${{ steps.next.outputs.version }}" - git push + bun run lint + bun test - - name: Create and push tag - if: steps.check_tag.outputs.exists == 'false' + - name: Commit and tag + env: + TAG: ${{ steps.version.outputs.next }} + VERSION: ${{ steps.version.outputs.version }} run: | - git tag "v${{ steps.next.outputs.version }}" - git push origin "v${{ steps.next.outputs.version }}" - echo "Created tag v${{ steps.next.outputs.version }}" + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git add -A + git commit -m "chore(release): bump version to v$VERSION" + git tag -a "$TAG" -m "Release $TAG" + git push origin main --follow-tags + + build: + name: Build ${{ matrix.target }} + needs: version + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + - target: linux-x64 + os: ubuntu-latest + artifact: uncov-linux-x64 + - target: darwin-arm64 + os: macos-latest + artifact: uncov-darwin-arm64 + - target: darwin-x64 + os: macos-latest + artifact: uncov-darwin-x64 + - target: windows-x64 + os: windows-latest + artifact: uncov-windows-x64.exe + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ needs.version.outputs.tag }} + + - name: Setup Bun + uses: oven-sh/setup-bun@v2 + with: + bun-version: latest + + - name: Install dependencies + run: bun install --frozen-lockfile + + - name: Build binary + run: bun build --compile --target=bun-${{ matrix.target }} --outfile=dist/${{ matrix.artifact }} ./src/cli.ts - - name: Summary + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.artifact }} + path: dist/${{ matrix.artifact }} + if-no-files-found: error + + release: + name: Create Release + needs: [version, build] + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ needs.version.outputs.tag }} + fetch-depth: 0 + + - name: Download all artifacts + uses: actions/download-artifact@v4 + with: + path: artifacts + + - name: Prepare release files run: | - if [[ "${{ steps.check_tag.outputs.exists }}" == "true" ]]; then - echo "### Skipped - Tag Already Exists" >> $GITHUB_STEP_SUMMARY - echo "Tag v${{ steps.next.outputs.version }} already exists." >> $GITHUB_STEP_SUMMARY - else - echo "### Auto Release Triggered" >> $GITHUB_STEP_SUMMARY - echo "- Previous version: v${{ steps.current.outputs.version }}" >> $GITHUB_STEP_SUMMARY - echo "- New version: v${{ steps.next.outputs.version }}" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo "The release workflow will now build and publish binaries." >> $GITHUB_STEP_SUMMARY - fi + mkdir -p release + find artifacts -type f -exec cp {} release/ \; + chmod +x release/*-linux-* release/*-darwin-* || true + ls -la release/ + + - name: Generate changelog + uses: orhun/git-cliff-action@v4 + id: changelog + with: + config: cliff.toml + args: --latest --strip header + env: + OUTPUT: CHANGELOG.md + + - name: Create GitHub Release + uses: softprops/action-gh-release@v2 + with: + tag_name: ${{ needs.version.outputs.tag }} + files: release/* + body: ${{ steps.changelog.outputs.content }} + draft: false + prerelease: false diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index b2adc4d..0000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,119 +0,0 @@ -name: Release - -on: - push: - tags: - - 'v*' - -permissions: - contents: write - -jobs: - build: - name: Build ${{ matrix.target }} - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - include: - - target: linux-x64 - os: ubuntu-latest - artifact: uncov-linux-x64 - - target: darwin-arm64 - os: macos-latest - artifact: uncov-darwin-arm64 - - target: darwin-x64 - os: macos-latest - artifact: uncov-darwin-x64 - - target: windows-x64 - os: windows-latest - artifact: uncov-windows-x64.exe - - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Setup Bun - uses: oven-sh/setup-bun@v2 - with: - bun-version: latest - - - name: Install dependencies - run: bun install --frozen-lockfile - - - name: Build binary - run: bun build --compile --target=bun-${{ matrix.target }} --outfile=dist/${{ matrix.artifact }} ./src/cli.ts - - - name: Generate checksum - shell: bash - run: | - cd dist - if [[ "${{ matrix.os }}" == "windows-latest" ]]; then - sha256sum ${{ matrix.artifact }} > ${{ matrix.artifact }}.sha256 - else - shasum -a 256 ${{ matrix.artifact }} > ${{ matrix.artifact }}.sha256 - fi - cat ${{ matrix.artifact }}.sha256 - - - name: Upload binary artifact - uses: actions/upload-artifact@v4 - with: - name: ${{ matrix.artifact }} - path: dist/${{ matrix.artifact }} - if-no-files-found: error - - - name: Upload checksum artifact - uses: actions/upload-artifact@v4 - with: - name: ${{ matrix.artifact }}.sha256 - path: dist/${{ matrix.artifact }}.sha256 - if-no-files-found: error - - release: - name: Create Release - needs: build - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Download all artifacts - uses: actions/download-artifact@v4 - with: - path: artifacts - - - name: Prepare release files - run: | - mkdir -p release - # Copy binaries - cp artifacts/uncov-linux-x64/uncov-linux-x64 release/ - cp artifacts/uncov-darwin-arm64/uncov-darwin-arm64 release/ - cp artifacts/uncov-darwin-x64/uncov-darwin-x64 release/ - cp artifacts/uncov-windows-x64.exe/uncov-windows-x64.exe release/ - # Copy checksums - cp artifacts/uncov-linux-x64.sha256/uncov-linux-x64.sha256 release/ - cp artifacts/uncov-darwin-arm64.sha256/uncov-darwin-arm64.sha256 release/ - cp artifacts/uncov-darwin-x64.sha256/uncov-darwin-x64.sha256 release/ - cp artifacts/uncov-windows-x64.exe.sha256/uncov-windows-x64.exe.sha256 release/ - # Make binaries executable - chmod +x release/uncov-linux-x64 - chmod +x release/uncov-darwin-arm64 - chmod +x release/uncov-darwin-x64 - ls -la release/ - - - name: Create GitHub Release - uses: softprops/action-gh-release@v2 - with: - files: | - release/uncov-linux-x64 - release/uncov-linux-x64.sha256 - release/uncov-darwin-arm64 - release/uncov-darwin-arm64.sha256 - release/uncov-darwin-x64 - release/uncov-darwin-x64.sha256 - release/uncov-windows-x64.exe - release/uncov-windows-x64.exe.sha256 - generate_release_notes: true - draft: false - prerelease: false diff --git a/justfile b/justfile index c202ae0..32420d5 100644 --- a/justfile +++ b/justfile @@ -71,77 +71,7 @@ changelog-preview: version: @echo "Current version: $(jq -r '.version' package.json)" -# Bump patch version (0.1.2 → 0.1.3) -bump-patch: - #!/bin/sh - set -e - CURRENT=$(jq -r '.version' package.json) - echo "Current version: $CURRENT" - MAJOR=$(echo "$CURRENT" | cut -d. -f1) - MINOR=$(echo "$CURRENT" | cut -d. -f2) - PATCH=$(echo "$CURRENT" | cut -d. -f3) - NEW="$MAJOR.$MINOR.$((PATCH + 1))" - echo "New version: $NEW" - jq --tab --arg v "$NEW" '.version = $v' package.json > package.json.tmp && mv package.json.tmp package.json - bun run lint:fix >/dev/null - git add package.json - git commit -m "chore(release): bump version to $NEW" - git tag "v$NEW" - echo "" - echo "Created tag v$NEW" - echo "" - echo "Push with:" - echo " git push origin main --tags" - -# Bump minor version (0.1.2 → 0.2.0) -bump-minor: - #!/bin/sh - set -e - CURRENT=$(jq -r '.version' package.json) - echo "Current version: $CURRENT" - MAJOR=$(echo "$CURRENT" | cut -d. -f1) - MINOR=$(echo "$CURRENT" | cut -d. -f2) - NEW="$MAJOR.$((MINOR + 1)).0" - echo "New version: $NEW" - jq --tab --arg v "$NEW" '.version = $v' package.json > package.json.tmp && mv package.json.tmp package.json - bun run lint:fix >/dev/null - git add package.json - git commit -m "chore(release): bump version to $NEW" - git tag "v$NEW" - echo "" - echo "Created tag v$NEW" - echo "" - echo "Push with:" - echo " git push origin main --tags" - -# Bump major version (0.1.2 → 1.0.0) -bump-major: - #!/bin/sh - set -e - CURRENT=$(jq -r '.version' package.json) - echo "Current version: $CURRENT" - MAJOR=$(echo "$CURRENT" | cut -d. -f1) - NEW="$((MAJOR + 1)).0.0" - echo "New version: $NEW" - jq --tab --arg v "$NEW" '.version = $v' package.json > package.json.tmp && mv package.json.tmp package.json - bun run lint:fix >/dev/null - git add package.json - git commit -m "chore(release): bump version to $NEW" - git tag "v$NEW" - echo "" - echo "Created tag v$NEW" - echo "" - echo "Push with:" - echo " git push origin main --tags" - -# Release: bump patch, push, and trigger release workflow -release-patch: bump-patch - git push origin main --tags - -# Release: bump minor, push, and trigger release workflow -release-minor: bump-minor - git push origin main --tags - -# Release: bump major, push, and trigger release workflow -release-major: bump-major - git push origin main --tags +# CI-friendly version setter (Linux sed compatible) +set-version version: + jq --tab --arg v "{{version}}" '.version = $v' package.json > package.json.tmp && mv package.json.tmp package.json + @echo "Set version to {{version}}" diff --git a/package.json b/package.json index dc6ff2b..0b8fea8 100644 --- a/package.json +++ b/package.json @@ -1,39 +1,39 @@ { - "name": "@llbbl/uncov", - "version": "0.1.5", - "description": "Report files with low test coverage from Vitest/Istanbul output", - "type": "module", - "main": "./dist/cli.js", - "bin": { - "uncov": "./dist/cli.js" - }, - "files": [ - "dist" - ], - "scripts": { - "dev": "bun run src/cli.ts", - "test": "bun test", - "lint": "biome check .", - "lint:fix": "biome check --write .", - "build": "bun run scripts/build.ts", - "build:local": "bun build --compile --outfile=uncov src/cli.ts", - "build:npm": "bun build src/cli.ts --outdir=dist --target=node", - "test:coverage": "vitest run --coverage", - "coverage:low": "uncov" - }, - "devDependencies": { - "@biomejs/biome": "^2.4.6", - "@types/bun": "^1.3.10" - }, - "keywords": [ - "coverage", - "vitest", - "testing", - "cli" - ], - "license": "MIT", - "repository": { - "type": "git", - "url": "git+https://github.com/llbbl/uncov.git" - } + "name": "@llbbl/uncov", + "version": "0.1.5", + "description": "Report files with low test coverage from Vitest/Istanbul output", + "type": "module", + "main": "./dist/cli.js", + "bin": { + "uncov": "./dist/cli.js" + }, + "files": [ + "dist" + ], + "scripts": { + "dev": "bun run src/cli.ts", + "test": "bun test", + "lint": "biome check .", + "lint:fix": "biome check --write .", + "build": "bun run scripts/build.ts", + "build:local": "bun build --compile --outfile=uncov src/cli.ts", + "build:npm": "bun build src/cli.ts --outdir=dist --target=node", + "test:coverage": "vitest run --coverage", + "coverage:low": "uncov" + }, + "devDependencies": { + "@biomejs/biome": "^2.4.6", + "@types/bun": "^1.3.10" + }, + "keywords": [ + "coverage", + "vitest", + "testing", + "cli" + ], + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/llbbl/uncov.git" + } }