diff --git a/.github/workflows/publish-on-branch.yml b/.github/workflows/publish-on-branch.yml deleted file mode 100644 index c2acd6f..0000000 --- a/.github/workflows/publish-on-branch.yml +++ /dev/null @@ -1,243 +0,0 @@ -# BRANCH-BASED RELEASE WORKFLOW -# This workflow is triggered when PRs are merged to release branches. -# Use this for: Standard releases with PR review gate -# -# Release branches: -# - release/angular-3d -> Publishes @hive-academy/angular-3d -# - release/angular-gsap -> Publishes @hive-academy/angular-gsap -# -# For emergency hotfixes without PR review, use the tag-based workflow: -# - See .github/workflows/publish.yml - -name: Publish on Release Branch - -on: - push: - branches: - - 'release/angular-3d' - - 'release/angular-gsap' - -# Prevent concurrent publishes for same branch -concurrency: - group: publish-${{ github.ref }} - cancel-in-progress: false - -permissions: - contents: write # For creating GitHub Releases and tags - id-token: write # For npm provenance - pull-requests: read # For reading PR metadata - -jobs: - # Job 1: Determine which library to publish based on branch - determine-package: - runs-on: ubuntu-latest - outputs: - package_name: ${{ steps.detect.outputs.package_name }} - package_path: ${{ steps.detect.outputs.package_path }} - should_publish: ${{ steps.check-version.outputs.should_publish }} - version: ${{ steps.check-version.outputs.version }} - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - fetch-depth: 0 # Full history for version detection - - - name: Detect package from branch - id: detect - shell: bash - run: | - BRANCH="${GITHUB_REF#refs/heads/}" - case "$BRANCH" in - "release/angular-3d") - echo "package_name=@hive-academy/angular-3d" >> $GITHUB_OUTPUT - echo "package_path=libs/angular-3d" >> $GITHUB_OUTPUT - ;; - "release/angular-gsap") - echo "package_name=@hive-academy/angular-gsap" >> $GITHUB_OUTPUT - echo "package_path=libs/angular-gsap" >> $GITHUB_OUTPUT - ;; - *) - echo "::error::Unknown release branch: $BRANCH" - exit 1 - ;; - esac - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: 20 - cache: 'npm' - - - name: Check if version changed - id: check-version - shell: bash - run: | - # Get version from package.json in the library - CURRENT_VERSION=$(node -p "require('./${{ steps.detect.outputs.package_path }}/package.json').version") - - # Check if this version is already published - PACKAGE_NAME="${{ steps.detect.outputs.package_name }}" - NPM_VERSION=$(npm view "$PACKAGE_NAME@$CURRENT_VERSION" version 2>/dev/null || echo "not-found") - - if [ "$NPM_VERSION" = "$CURRENT_VERSION" ]; then - echo "Version $CURRENT_VERSION already published, skipping" - echo "should_publish=false" >> $GITHUB_OUTPUT - else - echo "Version $CURRENT_VERSION not yet published" - echo "should_publish=true" >> $GITHUB_OUTPUT - fi - - echo "version=$CURRENT_VERSION" >> $GITHUB_OUTPUT - - # Job 2: Validate before publishing - validate-release: - needs: determine-package - if: needs.determine-package.outputs.should_publish == 'true' - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: 20 - cache: 'npm' - registry-url: 'https://registry.npmjs.org' - - - name: Install dependencies - shell: bash - run: npm ci - - - name: Verify NPM authentication - shell: bash - run: npm whoami - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - - - name: Run validation pipeline - shell: bash - run: | - echo "::group::Linting" - npx nx run-many -t lint - echo "::endgroup::" - - echo "::group::Testing" - npx nx run-many -t test - echo "::endgroup::" - - echo "::group::Type Checking" - npx nx run-many -t typecheck - echo "::endgroup::" - - echo "::group::Building" - npx nx run-many -t build - echo "::endgroup::" - - - name: Validate build artifacts - shell: bash - run: | - PACKAGE_PATH="${{ needs.determine-package.outputs.package_path }}" - DIST_PATH="dist/$PACKAGE_PATH" - - if [[ ! -d "$DIST_PATH" ]]; then - echo "::error::Build output not found at $DIST_PATH" - exit 1 - fi - - if [[ ! -f "$DIST_PATH/package.json" ]]; then - echo "::error::package.json not found in $DIST_PATH" - exit 1 - fi - - echo "Build artifacts validated successfully" - - # Job 3: Publish to npm - publish: - needs: [determine-package, validate-release] - if: needs.determine-package.outputs.should_publish == 'true' - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: 20 - cache: 'npm' - registry-url: 'https://registry.npmjs.org' - - - name: Install dependencies - shell: bash - run: npm ci - - - name: Build packages - shell: bash - run: npx nx run-many -t build - - - name: Publish to NPM with provenance - uses: nick-fields/retry@v3 - with: - timeout_minutes: 10 - max_attempts: 3 - retry_wait_seconds: 30 - shell: bash - command: npx nx release publish --projects=${{ needs.determine-package.outputs.package_name }} - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - NPM_CONFIG_PROVENANCE: true - - - name: Create git tag - shell: bash - env: - # Disable Husky hooks in CI - validation already done by pipeline - HUSKY: '0' - run: | - VERSION="${{ needs.determine-package.outputs.version }}" - PACKAGE="${{ needs.determine-package.outputs.package_name }}" - TAG="${PACKAGE}@${VERSION}" - - git config user.name "github-actions[bot]" - git config user.email "github-actions[bot]@users.noreply.github.com" - - # Create tag if it doesn't exist - if ! git rev-parse "$TAG" >/dev/null 2>&1; then - git tag -a "$TAG" -m "Release $TAG" - git push origin "$TAG" - fi - - - name: Create GitHub Release - uses: softprops/action-gh-release@v2 - with: - tag_name: ${{ needs.determine-package.outputs.package_name }}@${{ needs.determine-package.outputs.version }} - name: ${{ needs.determine-package.outputs.package_name }}@${{ needs.determine-package.outputs.version }} - body: | - ## ${{ needs.determine-package.outputs.package_name }} v${{ needs.determine-package.outputs.version }} - - Published via branch-based release workflow. - - **Install:** - ```bash - npm install ${{ needs.determine-package.outputs.package_name }}@${{ needs.determine-package.outputs.version }} - ``` - draft: false - prerelease: false - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - # Job 4: Skip notification when version unchanged - skip-notification: - needs: determine-package - if: needs.determine-package.outputs.should_publish == 'false' - runs-on: ubuntu-latest - steps: - - name: Log skip reason - shell: bash - run: | - echo "Skipping publish: version ${{ needs.determine-package.outputs.version }} already published" - echo "::notice::Version ${{ needs.determine-package.outputs.version }} already exists on npm, no publish needed" diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index f3566ac..d0e4496 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,12 +1,18 @@ -# TAG-BASED RELEASE WORKFLOW -# This workflow is triggered when git tags are pushed. -# Use this for: Emergency hotfixes, automated releases +# TAG-BASED RELEASE WORKFLOW (EMERGENCY USE ONLY) +# This workflow is triggered when git tags are pushed manually. # -# For standard releases with PR review, use the branch-based workflow: -# - Create PR to release/angular-3d or release/angular-gsap -# - See docs/publishing/README.md for details +# ⚠️ IMPORTANT: For standard releases, just merge PRs to main. +# Release Please will automatically create release PRs and publish. +# +# Use this workflow ONLY for: +# - Emergency hotfixes that bypass the normal flow +# - Manual re-publishing of failed releases +# +# To use: +# git tag "@hive-academy/angular-3d@1.2.3" +# git push origin "@hive-academy/angular-3d@1.2.3" -name: Publish to NPM +name: Publish to NPM (Manual Tag) on: push: diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml new file mode 100644 index 0000000..bd75b57 --- /dev/null +++ b/.github/workflows/release-please.yml @@ -0,0 +1,125 @@ +# RELEASE PLEASE WORKFLOW +# This workflow automates versioning and releases using Google's Release Please. +# +# How it works: +# 1. On every push to main, Release Please analyzes conventional commits +# 2. It creates/updates a "Release PR" with version bumps and CHANGELOG +# 3. When you merge the Release PR, it creates tags and GitHub releases +# 4. The publish workflow then publishes to npm +# +# Commit types and their effects: +# - feat: → minor version bump (1.0.0 → 1.1.0) +# - fix: → patch version bump (1.0.0 → 1.0.1) +# - feat!: or BREAKING CHANGE: → major version bump (1.0.0 → 2.0.0) +# - chore:, docs:, style:, refactor:, test: → no version bump +# +# For monorepo packages, use scopes: +# - feat(angular-3d): new feature → bumps @hive-academy/angular-3d +# - fix(angular-gsap): bug fix → bumps @hive-academy/angular-gsap + +name: Release Please + +on: + push: + branches: + - main + workflow_dispatch: # Allow manual trigger + +permissions: + contents: write + pull-requests: write + +jobs: + release-please: + runs-on: ubuntu-latest + outputs: + angular-3d--release_created: ${{ steps.release.outputs['libs/angular-3d--release_created'] }} + angular-3d--tag_name: ${{ steps.release.outputs['libs/angular-3d--tag_name'] }} + angular-3d--version: ${{ steps.release.outputs['libs/angular-3d--version'] }} + angular-gsap--release_created: ${{ steps.release.outputs['libs/angular-gsap--release_created'] }} + angular-gsap--tag_name: ${{ steps.release.outputs['libs/angular-gsap--tag_name'] }} + angular-gsap--version: ${{ steps.release.outputs['libs/angular-gsap--version'] }} + steps: + - name: Run Release Please + id: release + uses: googleapis/release-please-action@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + config-file: release-please-config.json + manifest-file: .release-please-manifest.json + + # Publish @hive-academy/angular-3d when released + publish-angular-3d: + needs: release-please + if: needs.release-please.outputs.angular-3d--release_created == 'true' + runs-on: ubuntu-latest + permissions: + contents: read + id-token: write # For npm provenance + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: 'npm' + registry-url: 'https://registry.npmjs.org' + + - name: Install dependencies + run: npm ci + + - name: Build + run: npx nx build angular-3d + + - name: Publish to npm + run: | + cd dist/libs/angular-3d + npm publish --access public --provenance + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + + - name: Summary + run: | + echo "## 🚀 Published @hive-academy/angular-3d@${{ needs.release-please.outputs.angular-3d--version }}" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Tag:** ${{ needs.release-please.outputs.angular-3d--tag_name }}" >> $GITHUB_STEP_SUMMARY + + # Publish @hive-academy/angular-gsap when released + publish-angular-gsap: + needs: release-please + if: needs.release-please.outputs.angular-gsap--release_created == 'true' + runs-on: ubuntu-latest + permissions: + contents: read + id-token: write # For npm provenance + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: 'npm' + registry-url: 'https://registry.npmjs.org' + + - name: Install dependencies + run: npm ci + + - name: Build + run: npx nx build angular-gsap + + - name: Publish to npm + run: | + cd dist/libs/angular-gsap + npm publish --access public --provenance + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + + - name: Summary + run: | + echo "## 🚀 Published @hive-academy/angular-gsap@${{ needs.release-please.outputs.angular-gsap--version }}" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Tag:** ${{ needs.release-please.outputs.angular-gsap--tag_name }}" >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/release-pr-check.yml b/.github/workflows/release-pr-check.yml deleted file mode 100644 index b01d058..0000000 --- a/.github/workflows/release-pr-check.yml +++ /dev/null @@ -1,257 +0,0 @@ -# RELEASE PR VALIDATION WORKFLOW -# This workflow validates PRs targeting release branches before they can be merged. -# It automatically bumps the patch version if needed, runs the full validation -# pipeline, and adds a comment with release information. -# -# Required for branch protection status checks on: -# - release/angular-3d -# - release/angular-gsap - -name: Release PR Validation - -on: - pull_request: - branches: - - 'release/angular-3d' - - 'release/angular-gsap' - -permissions: - contents: write # Required to push version bump commits - pull-requests: write - -jobs: - # Job 0: Skip if triggered by bot commit (prevent infinite loop) - check-trigger: - runs-on: ubuntu-latest - outputs: - should_run: ${{ steps.check.outputs.should_run }} - steps: - - name: Check if triggered by bot - id: check - shell: bash - run: | - if [[ "${{ github.event.head_commit.author.name }}" == "github-actions[bot]" ]]; then - echo "Skipping workflow - triggered by bot commit" - echo "should_run=false" >> $GITHUB_OUTPUT - else - echo "should_run=true" >> $GITHUB_OUTPUT - fi - - # Job 1: Auto-bump version if it matches the published npm version - auto-version-bump: - needs: check-trigger - if: needs.check-trigger.outputs.should_run == 'true' - runs-on: ubuntu-latest - outputs: - package_name: ${{ steps.detect.outputs.package_name }} - package_path: ${{ steps.detect.outputs.package_path }} - version: ${{ steps.final-version.outputs.version }} - npm_version: ${{ steps.version.outputs.npm_version }} - was_bumped: ${{ steps.bump.outputs.was_bumped }} - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - ref: ${{ github.head_ref }} - fetch-depth: 0 - token: ${{ secrets.GITHUB_TOKEN }} - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: 20 - cache: 'npm' - - - name: Detect target package - id: detect - shell: bash - run: | - TARGET_BRANCH="${{ github.base_ref }}" - case "$TARGET_BRANCH" in - "release/angular-3d") - echo "package_name=@hive-academy/angular-3d" >> $GITHUB_OUTPUT - echo "package_path=libs/angular-3d" >> $GITHUB_OUTPUT - ;; - "release/angular-gsap") - echo "package_name=@hive-academy/angular-gsap" >> $GITHUB_OUTPUT - echo "package_path=libs/angular-gsap" >> $GITHUB_OUTPUT - ;; - esac - - - name: Get version info - id: version - shell: bash - run: | - CURRENT=$(node -p "require('./${{ steps.detect.outputs.package_path }}/package.json').version") - echo "current_version=$CURRENT" >> $GITHUB_OUTPUT - - # Check npm for published versions - NPM_LATEST=$(npm view "${{ steps.detect.outputs.package_name }}" version 2>/dev/null || echo "0.0.0") - echo "npm_version=$NPM_LATEST" >> $GITHUB_OUTPUT - - - name: Auto-bump patch version if needed - id: bump - shell: bash - run: | - CURRENT="${{ steps.version.outputs.current_version }}" - NPM="${{ steps.version.outputs.npm_version }}" - - echo "Current package.json version: $CURRENT" - echo "Latest npm version: $NPM" - - if [ "$CURRENT" = "$NPM" ]; then - echo "Version matches npm, auto-bumping patch version..." - cd ${{ steps.detect.outputs.package_path }} - npm version patch --no-git-tag-version - NEW_VERSION=$(node -p "require('./package.json').version") - echo "Bumped version to: $NEW_VERSION" - echo "was_bumped=true" >> $GITHUB_OUTPUT - echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT - else - echo "Version $CURRENT is already different from npm ($NPM), no bump needed" - echo "was_bumped=false" >> $GITHUB_OUTPUT - fi - - - name: Commit and push version bump - if: steps.bump.outputs.was_bumped == 'true' - shell: bash - run: | - git config user.name "github-actions[bot]" - git config user.email "github-actions[bot]@users.noreply.github.com" - git add ${{ steps.detect.outputs.package_path }}/package.json - git commit -m "chore(release): bump ${{ steps.detect.outputs.package_name }} to ${{ steps.bump.outputs.new_version }}" - git push - - - name: Get final version - id: final-version - shell: bash - run: | - VERSION=$(node -p "require('./${{ steps.detect.outputs.package_path }}/package.json').version") - echo "version=$VERSION" >> $GITHUB_OUTPUT - - # Job 2: Validate the release PR (runs after version bump) - validate-release-pr: - needs: auto-version-bump - if: needs.auto-version-bump.result == 'success' - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - ref: ${{ github.head_ref }} - fetch-depth: 0 - - - name: Pull latest changes - shell: bash - run: | - # Ensure we have the latest commit (including any version bump from Job 1) - git pull origin ${{ github.head_ref }} --ff-only || true - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: 20 - cache: 'npm' - - - name: Install dependencies - shell: bash - run: npm ci - - - name: Get current version from file - id: current-version - shell: bash - run: | - # Read version directly from file to ensure we have the latest - VERSION=$(node -p "require('./${{ needs.auto-version-bump.outputs.package_path }}/package.json').version") - echo "version=$VERSION" >> $GITHUB_OUTPUT - - - name: Validate version is ready for publish - shell: bash - run: | - VERSION="${{ steps.current-version.outputs.version }}" - NPM="${{ needs.auto-version-bump.outputs.npm_version }}" - WAS_BUMPED="${{ needs.auto-version-bump.outputs.was_bumped }}" - - echo "Version to publish: $VERSION" - echo "Current npm version: $NPM" - echo "Was auto-bumped: $WAS_BUMPED" - - if [ "$VERSION" = "$NPM" ]; then - echo "::error::Version $VERSION still matches npm. This should not happen after auto-bump." - exit 1 - fi - - echo "✓ Version $VERSION is valid for publishing" - - - name: Run full validation - shell: bash - run: | - echo "::group::Linting" - npx nx run-many -t lint - echo "::endgroup::" - - echo "::group::Testing" - npx nx run-many -t test - echo "::endgroup::" - - echo "::group::Type Checking" - npx nx run-many -t typecheck - echo "::endgroup::" - - echo "::group::Building" - npx nx run-many -t build - echo "::endgroup::" - - - name: Validate build output - shell: bash - run: | - DIST_PATH="dist/${{ needs.auto-version-bump.outputs.package_path }}" - - if [[ ! -d "$DIST_PATH" ]]; then - echo "::error::Build output not found" - exit 1 - fi - - echo "Build artifacts validated" - - - name: Add PR comment with release info - uses: actions/github-script@v7 - with: - script: | - const version = '${{ steps.current-version.outputs.version }}'; - const package_name = '${{ needs.auto-version-bump.outputs.package_name }}'; - const npm_version = '${{ needs.auto-version-bump.outputs.npm_version }}'; - const was_bumped = '${{ needs.auto-version-bump.outputs.was_bumped }}'; - - const bumpNote = was_bumped === 'true' - ? `\n> **Note:** Version was automatically bumped from \`${npm_version}\` to \`${version}\`\n` - : ''; - - const body = `## 🚀 Release Validation Passed - ${bumpNote} - | Property | Value | - |----------|-------| - | **Package** | \`${package_name}\` | - | **Version to Publish** | \`${version}\` | - | **Current npm Version** | \`${npm_version}\` | - - ### Pre-Publish Checklist - - [x] Version bump validated (auto-bumped: ${was_bumped}) - - [x] Lint validation passed - - [x] Tests passed - - [x] Type checking passed - - [x] Build successful - - ### What happens on merge? - 1. Package will be published to npm with provenance - 2. Git tag \`${package_name}@${version}\` will be created - 3. GitHub Release will be created - - **Merge this PR to publish to npm.**`; - - github.rest.issues.createComment({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - body: body - }); diff --git a/.release-please-manifest.json b/.release-please-manifest.json new file mode 100644 index 0000000..a056de8 --- /dev/null +++ b/.release-please-manifest.json @@ -0,0 +1,4 @@ +{ + "libs/angular-3d": "1.0.0", + "libs/angular-gsap": "1.0.0" +} diff --git a/docs/publishing/README.md b/docs/publishing/README.md index 063041d..2c7fc8c 100644 --- a/docs/publishing/README.md +++ b/docs/publishing/README.md @@ -9,411 +9,198 @@ This guide covers everything you need to know about publishing the Angular 3D li | `@hive-academy/angular-3d` | Angular wrapper for Three.js 3D graphics | [npm](https://www.npmjs.com/package/@hive-academy/angular-3d) | | `@hive-academy/angular-gsap` | Angular wrapper for GSAP scroll animations | [npm](https://www.npmjs.com/package/@hive-academy/angular-gsap) | -## Release Workflows +## Release Workflow (Automated with Release Please) -We support **two release workflows** for different scenarios: - -| Workflow | Trigger | Use Case | Review Required | -| ---------------- | ----------------------- | ------------------ | --------------- | -| **Branch-Based** | PR merge to `release/*` | Standard releases | Yes (PR review) | -| **Tag-Based** | Git tag push | Emergency hotfixes | No | - ---- - -## Branch-Based Release (Recommended) - -The branch-based workflow provides safety through PR reviews and validation checks. +We use [Release Please](https://github.com/googleapis/release-please) from Google for fully automated releases. ### How It Works ``` -1. Developer bumps version on main branch -2. Creates PR from main → release/angular-3d (or release/angular-gsap) -3. PR triggers validation workflow -4. Reviewer approves PR -5. Merge triggers publish to npm -6. Git tag and GitHub Release created automatically +1. Developer makes changes and commits using conventional commits +2. PRs are merged to main +3. Release Please analyzes commits and creates a "Release PR" +4. When Release PR is merged → package is published to npm ``` -### Step-by-Step Guide - -#### 1. Prepare the Release - -First, bump the version and update the changelog: +### Benefits -```bash -# For @hive-academy/angular-3d -npm run release:prepare:a3d +- ✅ **Fully automated** - No manual version bumping +- ✅ **CHANGELOG generated** - From conventional commits +- ✅ **Reviewable** - Release PR can be reviewed before publishing +- ✅ **No branch protection issues** - Release Please creates its own PRs +- ✅ **Monorepo support** - Each package is versioned independently -# For @hive-academy/angular-gsap -npm run release:prepare:gsap -``` - -This command: +--- -- Analyzes commits since last release -- Determines version bump (major/minor/patch) based on conventional commits -- Updates `libs/{library}/package.json` with new version -- Updates `CHANGELOG.md` -- Creates a git commit -- Pushes to main branch +## Standard Release Flow -#### 2. Create Release PR +### 1. Develop with Conventional Commits -Create a pull request to the release branch: +Use [conventional commits](https://www.conventionalcommits.org/) with package scope: ```bash # For @hive-academy/angular-3d -npm run release:pr:a3d +git commit -m "feat(angular-3d): add new primitive component" +git commit -m "fix(angular-3d): resolve memory leak in scene" # For @hive-academy/angular-gsap -npm run release:pr:gsap +git commit -m "feat(angular-gsap): add parallax directive" +git commit -m "fix(angular-gsap): fix scroll trigger timing" ``` -This creates a PR from `main` to `release/angular-3d` (or `release/angular-gsap`). +### 2. Merge to Main -#### 3. Review and Approve +When your PR is merged to `main`, Release Please will: -The PR will automatically: +- Analyze all commits since the last release +- Create or update a "Release PR" with: + - Version bump based on commit types + - Updated CHANGELOG.md + - Updated package.json version -- Run validation (lint, test, typecheck, build) -- Check that the version isn't already published -- Add a comment with release information +### 3. Review and Merge Release PR -A reviewer must approve the PR before it can be merged. +When you're ready to publish: -#### 4. Merge to Publish +1. Review the Release PR created by Release Please +2. Verify the version bump and changelog look correct +3. Merge the Release PR -When the PR is merged: +### 4. Automatic Publishing -- Package is published to npm with provenance -- Git tag is created (e.g., `@hive-academy/angular-3d@1.0.0`) -- GitHub Release is created +When the Release PR is merged: -### Quick Reference - -```bash -# Full release flow for angular-3d -npm run release:prepare:a3d # Bump version, update changelog -npm run release:pr:a3d # Create release PR -# → Review and merge PR in GitHub - -# Full release flow for angular-gsap -npm run release:prepare:gsap -npm run release:pr:gsap -# → Review and merge PR in GitHub -``` +- Package is built and validated +- Published to npm with provenance +- Git tag is created +- GitHub Release is created --- -## Tag-Based Release (Emergency) +## Commit Types and Version Bumps -Use the tag-based workflow for emergency hotfixes when PR review would cause unacceptable delay. +| Commit Type | Example | Version Bump | +| ------------------------------------------------- | ---------------------------------------- | --------------------- | +| `feat:` | `feat(angular-3d): add box primitive` | Minor (1.0.0 → 1.1.0) | +| `fix:` | `fix(angular-3d): resolve memory leak` | Patch (1.0.0 → 1.0.1) | +| `feat!:` or `BREAKING CHANGE:` | `feat(angular-3d)!: change API` | Major (1.0.0 → 2.0.0) | +| `perf:` | `perf(angular-3d): optimize render loop` | Patch | +| `docs:`, `chore:`, `style:`, `test:`, `refactor:` | Various | No release | -### How It Works +### Scoping for Monorepo -``` -1. Developer creates version (bumps package.json, updates changelog, creates tag) -2. Pushes commit and tag to remote -3. Tag push triggers GitHub Actions workflow -4. Workflow validates and publishes immediately -``` - -### Step-by-Step Guide +Use the package name (without `@hive-academy/`) as the scope: ```bash -# 1. Create version and tag for angular-3d -npm run release:version -- --projects=@hive-academy/angular-3d +# Affects @hive-academy/angular-3d +feat(angular-3d): description -# 2. Push commit and tag -git push && git push --tags +# Affects @hive-academy/angular-gsap +fix(angular-gsap): description -# The workflow will automatically: -# - Validate (lint, test, typecheck, build) -# - Publish to npm with provenance -# - Create GitHub Release +# Affects both (or workspace-level) +chore: update dependencies ``` -### When to Use - -- Critical security patches -- Production-breaking bugs -- When PR review delay is unacceptable -- Automated releases from CI/CD - --- -## Local/Manual Publishing - -For development testing or when CI/CD is unavailable. - -### Prerequisites - -1. **NPM Token**: Get an automation token from [npmjs.com](https://www.npmjs.com/settings/~/tokens) -2. **Scope Access**: Token must have publish access to `@hive-academy` scope +## Emergency Manual Release -### Step-by-Step Guide +For emergency hotfixes that need to bypass the normal flow: -```bash -# 1. Set NPM token -export NPM_TOKEN= - -# 2. Preview version changes (dry-run) -npm run release:version:dry -- --projects=@hive-academy/angular-3d - -# 3. Create version (if dry-run looks good) -npm run release:version -- --projects=@hive-academy/angular-3d - -# 4. Publish to npm -npm run release:publish -- --projects=@hive-academy/angular-3d - -# 5. Push to GitHub -git push && git push --tags -``` - -### Manual GitHub Release - -If the automated GitHub Release fails: +### Using Git Tags ```bash -# Using GitHub CLI -gh release create @hive-academy/angular-3d@1.0.0 \ - --title "@hive-academy/angular-3d@1.0.0" \ - --notes-file CHANGELOG.md -``` - ---- - -## Versioning Strategy - -### Semantic Versioning - -All packages follow [Semantic Versioning](https://semver.org/): - -| Version | When to Use | Example | -| ------------------------- | ---------------------------------- | -------------------------------- | -| **MAJOR** (1.0.0 → 2.0.0) | Breaking changes | Removing APIs, changing behavior | -| **MINOR** (1.0.0 → 1.1.0) | New features (backward compatible) | New components, new options | -| **PATCH** (1.0.0 → 1.0.1) | Bug fixes (backward compatible) | Fixes, performance improvements | - -### Automatic Version Detection - -Version bumps are automatically determined from conventional commits: - -| Commit Type | Version Bump | Example | -| ------------------ | ------------ | ------------------------------------------ | -| `feat:` | MINOR | `feat(angular-3d): add sphere component` | -| `fix:` | PATCH | `fix(angular-3d): resolve memory leak` | -| `BREAKING CHANGE:` | MAJOR | Footer in commit message | -| `feat!:` | MAJOR | `feat(angular-3d)!: remove deprecated API` | - -### Independent Versioning - -Each library is versioned independently: - -- `@hive-academy/angular-3d` can be at `2.0.0` -- `@hive-academy/angular-gsap` can be at `1.5.0` - ---- - -## Pre-Release Checklist - -Before creating a release: - -- [ ] All tests passing: `npx nx run-many -t test` -- [ ] All lints passing: `npx nx run-many -t lint` -- [ ] All type-checks passing: `npx nx run-many -t typecheck` -- [ ] All builds successful: `npx nx run-many -t build` -- [ ] CHANGELOG.md preview reviewed (dry-run) -- [ ] Version bump type is correct (major/minor/patch) -- [ ] No uncommitted changes: `git status` -- [ ] Main branch is up to date: `git pull origin main` - -Run all checks at once: +# 1. Ensure version is updated in package.json +cd libs/angular-3d +npm version patch # or minor, major -```bash -npx nx run-many -t lint test typecheck build -``` - ---- - -## Troubleshooting - -### Authentication Errors - -**Problem**: `npm publish` fails with 401 Unauthorized - -**Solution**: - -```bash -# Verify your token is valid -npm whoami - -# Check token has correct scope -npm access ls-packages @hive-academy -``` - -### Version Already Exists - -**Problem**: `npm publish` fails with "version already exists" - -**Solution**: - -```bash -# Check published versions -npm view @hive-academy/angular-3d versions --json - -# If tag exists but package doesn't, delete the tag -git tag -d @hive-academy/angular-3d@1.0.0 -git push origin :refs/tags/@hive-academy/angular-3d@1.0.0 -``` - -### CI Workflow Fails at Validation - -**Problem**: GitHub Actions workflow fails during lint/test/build - -**Solution**: - -```bash -# Reproduce locally -npx nx run-many -t lint test typecheck build --verbose - -# Fix issues, then push fix +# 2. Commit the change git add . -git commit -m "fix(ci): resolve validation failures" -git push -``` +git commit -m "chore(release): emergency release @hive-academy/angular-3d@1.0.1" -### PR Validation Fails - -**Problem**: Release PR shows validation failed - -**Solution**: - -1. Check the PR checks for specific error -2. Fix on main branch -3. Update the PR (it will re-run validation) - -### Build Artifacts Missing +# 3. Create and push tag +git tag "@hive-academy/angular-3d@1.0.1" +git push origin main --tags +``` -**Problem**: Workflow fails with "dist/ not found" +The tag-based workflow will: -**Solution**: +- Run validation +- Publish to npm +- Create GitHub Release -```bash -# Ensure build runs successfully -npx nx run-many -t build - -# Check dist directory exists -ls dist/libs/angular-3d/ -ls dist/libs/angular-gsap/ -``` +⚠️ **Note**: This bypasses the Release Please flow. After an emergency release, you may need to update `.release-please-manifest.json` to sync the version. --- -## Rollback Procedures +## Configuration Files -### Deprecate a Bad Version +### `release-please-config.json` -If you published a broken version: +Configuration for Release Please: -```bash -# Mark version as deprecated (users see warning on install) -npm deprecate @hive-academy/angular-3d@1.0.0 "This version has issues, please upgrade to 1.0.1" +```json +{ + "packages": { + "libs/angular-3d": { + "package-name": "@hive-academy/angular-3d", + "release-type": "node" + }, + "libs/angular-gsap": { + "package-name": "@hive-academy/angular-gsap", + "release-type": "node" + } + } +} ``` -### Unpublish (Within 72 Hours) +### `.release-please-manifest.json` -If you need to completely remove a version (only works within 72 hours): +Tracks current versions: -```bash -npm unpublish @hive-academy/angular-3d@1.0.0 +```json +{ + "libs/angular-3d": "1.0.0", + "libs/angular-gsap": "1.0.0" +} ``` -### Publish Corrected Version - -1. Fix the issue -2. Bump to next patch version -3. Publish using standard workflow - --- -## Repository Setup (One-Time) +## Troubleshooting -### Create Release Branches +### Release PR Not Created -```bash -git checkout main -git pull origin main +1. Check that commits use conventional commit format +2. Ensure commits have the correct scope (`angular-3d` or `angular-gsap`) +3. Check GitHub Actions for errors -# Create angular-3d release branch -git checkout -b release/angular-3d -git push -u origin release/angular-3d +### Version Mismatch After Manual Release -# Create angular-gsap release branch -git checkout main -git checkout -b release/angular-gsap -git push -u origin release/angular-gsap +If you did an emergency release, update `.release-please-manifest.json`: -git checkout main +```json +{ + "libs/angular-3d": "1.0.1", // Update to current version + "libs/angular-gsap": "1.0.0" +} ``` -### Configure Branch Protection (GitHub Settings) - -For both `release/angular-3d` and `release/angular-gsap`: - -1. Go to Settings → Branches → Add rule -2. Branch name pattern: `release/angular-3d` (or `release/angular-gsap`) -3. Enable: - - Require a pull request before merging - - Require approvals: 1 - - Require status checks to pass before merging - - Status checks: `validate-release-pr` - - Do not allow bypassing the above settings - -### Configure NPM_TOKEN Secret +### NPM Publish Failed -1. Go to Settings → Secrets and variables → Actions -2. Add secret: `NPM_TOKEN` -3. Value: Your npm automation token +1. Check that `NPM_TOKEN` secret is valid +2. Verify the package isn't already published with that version +3. Check npm registry status --- -## Reference - -### npm Scripts - -| Script | Description | -| ------------------------------ | ------------------------------------------ | -| `npm run release:version` | Create version, changelog, and tag | -| `npm run release:version:dry` | Preview version changes (no modifications) | -| `npm run release:publish` | Publish to npm | -| `npm run release` | Full release (version + publish) | -| `npm run release:prepare:a3d` | Prepare angular-3d release | -| `npm run release:prepare:gsap` | Prepare angular-gsap release | -| `npm run release:pr:a3d` | Create PR for angular-3d release | -| `npm run release:pr:gsap` | Create PR for angular-gsap release | - -### GitHub Workflows +## Workflow Files -| Workflow | Trigger | Purpose | -| ----------------------- | ------------------ | ------------------------------- | -| `publish.yml` | Tag push | Tag-based publish (emergency) | -| `publish-on-branch.yml` | Push to release/\* | Branch-based publish (standard) | -| `release-pr-check.yml` | PR to release/\* | Validate release PR | -| `ci.yml` | Push/PR to main | Standard CI validation | - -### Verification Commands - -```bash -# Check published versions -npm view @hive-academy/angular-3d versions --json -npm view @hive-academy/angular-gsap versions --json - -# Verify package contents -npm pack @hive-academy/angular-3d --dry-run -npm pack @hive-academy/angular-gsap --dry-run - -# Verify provenance -npm audit signatures -``` +| File | Purpose | +| -------------------------------------- | ---------------------------- | +| `.github/workflows/release-please.yml` | Main release workflow | +| `.github/workflows/publish.yml` | Emergency tag-based releases | +| `.github/workflows/ci.yml` | PR validation | +| `release-please-config.json` | Release Please configuration | +| `.release-please-manifest.json` | Version tracking | diff --git a/release-please-config.json b/release-please-config.json new file mode 100644 index 0000000..7a5a9f5 --- /dev/null +++ b/release-please-config.json @@ -0,0 +1,43 @@ +{ + "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json", + "packages": { + "libs/angular-3d": { + "package-name": "@hive-academy/angular-3d", + "release-type": "node", + "changelog-path": "CHANGELOG.md", + "bump-minor-pre-major": true, + "bump-patch-for-minor-pre-major": true, + "include-component-in-tag": true, + "include-v-in-tag": false, + "tag-separator": "@", + "extra-files": [] + }, + "libs/angular-gsap": { + "package-name": "@hive-academy/angular-gsap", + "release-type": "node", + "changelog-path": "CHANGELOG.md", + "bump-minor-pre-major": true, + "bump-patch-for-minor-pre-major": true, + "include-component-in-tag": true, + "include-v-in-tag": false, + "tag-separator": "@", + "extra-files": [] + } + }, + "changelog-sections": [ + { "type": "feat", "section": "Features" }, + { "type": "fix", "section": "Bug Fixes" }, + { "type": "perf", "section": "Performance Improvements" }, + { "type": "refactor", "section": "Code Refactoring", "hidden": true }, + { "type": "docs", "section": "Documentation", "hidden": true }, + { "type": "style", "section": "Styles", "hidden": true }, + { "type": "test", "section": "Tests", "hidden": true }, + { "type": "build", "section": "Build System", "hidden": true }, + { "type": "ci", "section": "Continuous Integration", "hidden": true }, + { "type": "chore", "section": "Miscellaneous Chores", "hidden": true } + ], + "pull-request-title-pattern": "chore(release): ${component} ${version}", + "pull-request-header": "## Release PR\n\nThis PR was automatically created by [Release Please](https://github.com/googleapis/release-please).\n\n**Merge this PR to publish to npm.**", + "group-pull-request-title-pattern": "chore(release): ${component} ${version}", + "separate-pull-requests": true +}