Merge pull request #28 from link-foundation/issue-27-05348a151c4d #110
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Checks and release | |
| on: | |
| push: | |
| branches: | |
| - main | |
| pull_request: | |
| types: [opened, synchronize, reopened] | |
| # Manual release support - consolidated here to work with npm trusted publishing | |
| # npm only allows ONE workflow file as trusted publisher, so all publishing | |
| # must go through this workflow (release.yml) | |
| workflow_dispatch: | |
| inputs: | |
| release_mode: | |
| description: 'Manual release mode' | |
| required: true | |
| type: choice | |
| default: 'instant' | |
| options: | |
| - instant | |
| - changeset-pr | |
| bump_type: | |
| description: 'Manual release type' | |
| required: true | |
| type: choice | |
| options: | |
| - patch | |
| - minor | |
| - major | |
| description: | |
| description: 'Manual release description (optional)' | |
| required: false | |
| type: string | |
| # Concurrency: Only one workflow run per branch at a time | |
| # - For main branch (releases): cancel older runs to prevent blocking newer releases | |
| # When multiple commits are pushed quickly, we want the latest to release, not wait | |
| # - For PR branches: queue runs to avoid cancelling checks on force-pushes | |
| # See: docs/case-studies/issue-25/DETAILED-COMPARISON.md for context | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: ${{ github.ref == 'refs/heads/main' }} | |
| jobs: | |
| # === DETECT CHANGES - determines which jobs should run === | |
| detect-changes: | |
| name: Detect Changes | |
| runs-on: ubuntu-latest | |
| # Typical run: ~5s. Cap at 5min so a hung detection step | |
| # surfaces quickly instead of stalling the whole pipeline. | |
| timeout-minutes: 5 | |
| if: github.event_name != 'workflow_dispatch' | |
| outputs: | |
| mjs-changed: ${{ steps.changes.outputs.mjs-changed }} | |
| js-changed: ${{ steps.changes.outputs.js-changed }} | |
| package-changed: ${{ steps.changes.outputs.package-changed }} | |
| docs-changed: ${{ steps.changes.outputs.docs-changed }} | |
| workflow-changed: ${{ steps.changes.outputs.workflow-changed }} | |
| any-code-changed: ${{ steps.changes.outputs.any-code-changed }} | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - name: Detect changes | |
| id: changes | |
| run: node js/scripts/detect-code-changes.mjs | |
| # === FAST CHECKS - run before slow tests for fastest feedback === | |
| # See: hive-mind CI/CD best practices principle #5 (fast-fail job ordering) | |
| # Syntax check all .mjs files with node --check (~7s) | |
| test-compilation: | |
| name: Test Compilation | |
| runs-on: ubuntu-latest | |
| # Typical run: ~4s. Tight cap fails fast on accidental infinite loops. | |
| timeout-minutes: 5 | |
| needs: [detect-changes] | |
| if: | | |
| github.event_name == 'push' || | |
| needs.detect-changes.outputs.mjs-changed == 'true' || | |
| needs.detect-changes.outputs.js-changed == 'true' | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Check .mjs syntax | |
| run: bash js/scripts/check-mjs-syntax.sh | |
| # Enforce 1500-line limit on .mjs files and release.yml | |
| check-file-line-limits: | |
| name: Check File Line Limits | |
| runs-on: ubuntu-latest | |
| # Typical run: ~3s. Just walks the tree counting lines. | |
| timeout-minutes: 5 | |
| needs: [detect-changes] | |
| if: | | |
| github.event_name == 'push' || | |
| needs.detect-changes.outputs.mjs-changed == 'true' || | |
| needs.detect-changes.outputs.js-changed == 'true' || | |
| needs.detect-changes.outputs.workflow-changed == 'true' | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - name: Simulate fresh merge with base branch (PR only) | |
| if: github.event_name == 'pull_request' | |
| env: | |
| BASE_REF: ${{ github.base_ref }} | |
| run: bash js/scripts/simulate-fresh-merge.sh | |
| - name: Check file line limits | |
| run: bash js/scripts/check-file-line-limits.sh | |
| # === VERSION CHANGE CHECK === | |
| # Prohibit manual version changes in package.json - versions should only be changed by CI/CD | |
| version-check: | |
| name: Check for Manual Version Changes | |
| runs-on: ubuntu-latest | |
| # Typical run: ~6s. Read-only diff inspection. | |
| timeout-minutes: 5 | |
| if: github.event_name == 'pull_request' | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - name: Check for version changes in package.json | |
| env: | |
| GITHUB_HEAD_REF: ${{ github.head_ref }} | |
| GITHUB_BASE_REF: ${{ github.base_ref }} | |
| run: node js/scripts/check-version.mjs | |
| # === CHANGESET CHECK - only runs on PRs with code changes === | |
| # Docs-only PRs (./docs folder, markdown files) don't require changesets | |
| changeset-check: | |
| name: Check for Changesets | |
| runs-on: ubuntu-latest | |
| # Typical run: ~13s including npm install. 10min covers cold cache. | |
| timeout-minutes: 10 | |
| needs: [detect-changes] | |
| if: github.event_name == 'pull_request' && needs.detect-changes.outputs.any-code-changed == 'true' | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: '24.x' | |
| - name: Install dependencies | |
| run: npm install | |
| - name: Check for changesets | |
| env: | |
| # Pass PR context to the validation script | |
| GITHUB_BASE_REF: ${{ github.base_ref }} | |
| GITHUB_BASE_SHA: ${{ github.event.pull_request.base.sha }} | |
| GITHUB_HEAD_SHA: ${{ github.event.pull_request.head.sha }} | |
| run: | | |
| # Skip changeset check for automated version PRs | |
| if [[ "${{ github.head_ref }}" == "changeset-release/"* ]]; then | |
| echo "Skipping changeset check for automated release PR" | |
| exit 0 | |
| fi | |
| # Run changeset validation script | |
| # This validates that exactly ONE changeset was ADDED by this PR | |
| # Pre-existing changesets from other merged PRs are ignored | |
| node js/scripts/validate-changeset.mjs | |
| # === LINT AND FORMAT CHECK === | |
| # Lint runs independently of changeset-check - it's a fast check that should always run | |
| # See: https://github.com/link-assistant/hive-mind/pull/1024 for why this dependency was removed | |
| # IMPORTANT: ESLint includes max-lines rule (1500 lines) to ensure files stay maintainable | |
| # See docs/case-studies/issue-23 for why fresh merge simulation is critical | |
| lint: | |
| name: Lint and Format Check | |
| runs-on: ubuntu-latest | |
| # Typical run: ~23s including npm install + ESLint + Prettier + jscpd | |
| # + secretlint. 10min cap protects against a hung lint plugin. | |
| timeout-minutes: 10 | |
| needs: [detect-changes] | |
| if: | | |
| github.event_name == 'push' || | |
| needs.detect-changes.outputs.mjs-changed == 'true' || | |
| needs.detect-changes.outputs.js-changed == 'true' || | |
| needs.detect-changes.outputs.docs-changed == 'true' || | |
| needs.detect-changes.outputs.package-changed == 'true' || | |
| needs.detect-changes.outputs.workflow-changed == 'true' | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| # For PRs, fetch enough history to merge with base branch | |
| fetch-depth: 0 | |
| - name: Simulate fresh merge with base branch (PR only) | |
| if: github.event_name == 'pull_request' | |
| env: | |
| BASE_REF: ${{ github.base_ref }} | |
| run: bash js/scripts/simulate-fresh-merge.sh | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: '24.x' | |
| - name: Install dependencies | |
| run: npm install | |
| - name: Run ESLint | |
| run: npm run lint | |
| - name: Check formatting | |
| run: npm run format:check | |
| - name: Check code duplication | |
| run: npm run check:duplication | |
| - name: Check for secrets | |
| run: npx --yes -p secretlint -p @secretlint/secretlint-rule-preset-recommend secretlint "**/*" | |
| # Test matrix: 3 runtimes (Node.js, Bun, Deno) x 3 OS (Ubuntu, macOS, Windows) | |
| # IMPORTANT: Tests must validate the ACTUAL merge result, not a stale merge preview. | |
| # See docs/case-studies/issue-23 for why this is critical. | |
| # Fast-fail: slow test matrix only runs after fast checks pass (hive-mind principle #5) | |
| test: | |
| name: Test (${{ matrix.runtime }} on ${{ matrix.os }}) | |
| runs-on: ${{ matrix.os }} | |
| # Typical run: 13–55s (deno on Windows can spike to ~2min on cold runners). | |
| # 10min cap surfaces a hung test or flaky network well before the | |
| # 6h GitHub default — the user wants flaky tests to fail fast. | |
| timeout-minutes: 10 | |
| needs: | |
| [ | |
| detect-changes, | |
| changeset-check, | |
| test-compilation, | |
| lint, | |
| check-file-line-limits, | |
| ] | |
| # Use !cancelled() instead of always() so cancellation propagates correctly (hive-mind issue #1278) | |
| # Run if: push event, OR changeset-check succeeded, OR changeset-check was skipped (docs-only PR) | |
| # AND all fast checks passed (or were skipped for irrelevant changes) | |
| if: | | |
| !cancelled() && | |
| (github.event_name == 'push' || needs.changeset-check.result == 'success' || needs.changeset-check.result == 'skipped') && | |
| (needs.test-compilation.result == 'success' || needs.test-compilation.result == 'skipped') && | |
| (needs.lint.result == 'success' || needs.lint.result == 'skipped') && | |
| (needs.check-file-line-limits.result == 'success' || needs.check-file-line-limits.result == 'skipped') | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, macos-latest, windows-latest] | |
| runtime: [node, bun, deno] | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| # For PRs, fetch enough history to merge with base branch | |
| fetch-depth: 0 | |
| - name: Simulate fresh merge with base branch (PR only) | |
| if: github.event_name == 'pull_request' | |
| env: | |
| BASE_REF: ${{ github.base_ref }} | |
| shell: bash | |
| run: bash js/scripts/simulate-fresh-merge.sh | |
| - name: Setup Node.js | |
| if: matrix.runtime == 'node' | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: '24.x' | |
| - name: Install dependencies (Node.js) | |
| if: matrix.runtime == 'node' | |
| run: npm install | |
| - name: Run tests (Node.js) | |
| if: matrix.runtime == 'node' | |
| run: npm test | |
| - name: Setup Bun | |
| if: matrix.runtime == 'bun' | |
| uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| - name: Install dependencies (Bun) | |
| if: matrix.runtime == 'bun' | |
| run: bun install | |
| - name: Run tests (Bun) | |
| if: matrix.runtime == 'bun' | |
| # --timeout caps an individual test at 30s. Default is 5s but a few | |
| # WebRTC / WebSocket scenarios run slower on cold runners; 30s leaves | |
| # headroom while still failing fast on a hung promise. | |
| run: bun test --timeout 30000 | |
| - name: Setup Deno | |
| if: matrix.runtime == 'deno' | |
| uses: denoland/setup-deno@v2 | |
| with: | |
| deno-version: v2.x | |
| - name: Run tests (Deno) | |
| if: matrix.runtime == 'deno' | |
| run: deno test --allow-read --allow-write --allow-env --allow-net --allow-sys js/tests | |
| # === API DOCUMENTATION BUILD === | |
| # Build JS API docs (`npm run docs:api`) and Rust crate docs | |
| # (`cargo doc --manifest-path rust/Cargo.toml --no-deps`) on every push and PR. This catches doc-comment | |
| # errors before release and produces artefacts the `release` job attaches | |
| # to GitHub Releases (R-H3). | |
| docs-build: | |
| name: Build API Docs | |
| runs-on: ubuntu-latest | |
| # Typical run: ~25s. cargo doc dominates and is well-bounded. | |
| timeout-minutes: 15 | |
| needs: [detect-changes] | |
| if: | | |
| github.event_name == 'push' || | |
| needs.detect-changes.outputs.mjs-changed == 'true' || | |
| needs.detect-changes.outputs.js-changed == 'true' || | |
| needs.detect-changes.outputs.docs-changed == 'true' | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: '24.x' | |
| - name: Install dependencies | |
| run: npm install | |
| - name: Build JS API docs | |
| run: npm run docs:api | |
| - name: Setup Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Build Rust crate docs | |
| run: cargo doc --manifest-path rust/Cargo.toml --no-deps --workspace | |
| - name: Upload JS API docs artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: docs-api-js | |
| path: docs/api/ | |
| if-no-files-found: error | |
| retention-days: 30 | |
| - name: Upload Rust crate docs artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: docs-api-rust | |
| path: rust/target/doc/ | |
| if-no-files-found: error | |
| retention-days: 30 | |
| # === DOCUMENTATION VALIDATION === | |
| # Validate documentation files when docs change (hive-mind principle #12) | |
| validate-docs: | |
| name: Validate Documentation | |
| runs-on: ubuntu-latest | |
| # Typical run: <5s. Pure shell file walk. | |
| timeout-minutes: 5 | |
| needs: [detect-changes] | |
| if: | | |
| github.event_name == 'push' || | |
| needs.detect-changes.outputs.docs-changed == 'true' | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Check documentation file sizes | |
| run: | | |
| LIMIT=2500 | |
| FAILURES=() | |
| echo "Checking that documentation files are under ${LIMIT} lines..." | |
| while IFS= read -r -d '' file; do | |
| line_count=$(wc -l < "$file") | |
| if [ "$line_count" -gt "$LIMIT" ]; then | |
| echo "ERROR: $file has $line_count lines (limit: ${LIMIT})" | |
| echo "::error file=$file::Documentation file has $line_count lines (limit: ${LIMIT})" | |
| FAILURES+=("$file") | |
| fi | |
| done < <(find docs -name "*.md" -type f -print0 2>/dev/null) | |
| if [ "${#FAILURES[@]}" -gt 0 ]; then | |
| echo "The following docs exceed the ${LIMIT} line limit:" | |
| printf ' %s\n' "${FAILURES[@]}" | |
| exit 1 | |
| else | |
| echo "All documentation files are within the ${LIMIT} line limit." | |
| fi | |
| - name: Check required documentation files exist | |
| run: | | |
| REQUIRED_FILES=( | |
| "docs/BEST-PRACTICES.md" | |
| "docs/CONTRIBUTING.md" | |
| "docs/ROADMAP.md" | |
| "docs/REQUIREMENTS.md" | |
| "README.md" | |
| "CHANGELOG.md" | |
| ) | |
| MISSING=() | |
| for file in "${REQUIRED_FILES[@]}"; do | |
| if [ ! -f "$file" ]; then | |
| echo "ERROR: Required documentation file missing: $file" | |
| MISSING+=("$file") | |
| else | |
| echo "Found: $file" | |
| fi | |
| done | |
| if [ "${#MISSING[@]}" -gt 0 ]; then | |
| echo "" | |
| echo "Missing required documentation files:" | |
| printf ' %s\n' "${MISSING[@]}" | |
| exit 1 | |
| else | |
| echo "All required documentation files present." | |
| fi | |
| # Release - only runs on main after tests pass (for push events) | |
| release: | |
| name: Release | |
| # Cap publish work (changeset merge, version commit, npm publish, | |
| # GitHub release, doc upload). Typical run is well under 10min; | |
| # 30min covers npm registry retries on a bad day. | |
| timeout-minutes: 30 | |
| needs: [lint, test, docs-build] | |
| # Use !cancelled() instead of always() so cancellation propagates correctly (hive-mind issue #1278) | |
| # This is needed because lint/test jobs have a transitive dependency on changeset-check | |
| if: | | |
| !cancelled() && | |
| github.ref == 'refs/heads/main' && | |
| github.event_name == 'push' && | |
| needs.lint.result == 'success' && | |
| needs.test.result == 'success' && | |
| (needs.docs-build.result == 'success' || needs.docs-build.result == 'skipped') | |
| runs-on: ubuntu-latest | |
| # Permissions required for npm OIDC trusted publishing | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| id-token: write | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: '24.x' | |
| registry-url: 'https://registry.npmjs.org' | |
| - name: Install dependencies | |
| run: npm install | |
| - name: Update npm for OIDC trusted publishing | |
| run: node js/scripts/setup-npm.mjs | |
| - name: Check for changesets | |
| id: check_changesets | |
| run: node js/scripts/check-changesets.mjs | |
| - name: Check if release is needed | |
| id: check_release | |
| env: | |
| HAS_CHANGESETS: ${{ steps.check_changesets.outputs.has_changesets }} | |
| run: node js/scripts/check-release-needed.mjs | |
| - name: Merge multiple changesets | |
| if: steps.check_changesets.outputs.has_changesets == 'true' && steps.check_changesets.outputs.changeset_count > 1 | |
| run: | | |
| echo "Multiple changesets detected, merging..." | |
| node js/scripts/merge-changesets.mjs | |
| - name: Version packages and commit to main | |
| if: steps.check_changesets.outputs.has_changesets == 'true' | |
| id: version | |
| run: node js/scripts/version-and-commit.mjs --mode changeset | |
| - name: Publish to npm | |
| # Run if version was committed, if a previous attempt already committed (for re-runs), | |
| # or if check-release-needed detected an unpublished version (self-healing, issue #36) | |
| if: >- | |
| steps.version.outputs.version_committed == 'true' || | |
| steps.version.outputs.already_released == 'true' || | |
| (steps.check_release.outputs.should_release == 'true' && steps.check_release.outputs.skip_bump == 'true') | |
| id: publish | |
| run: node js/scripts/publish-to-npm.mjs --should-pull | |
| - name: Create GitHub Release | |
| if: steps.publish.outputs.published == 'true' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: node js/scripts/create-github-release.mjs --release-version "${{ steps.publish.outputs.published_version }}" --repository "${{ github.repository }}" | |
| - name: Format GitHub release notes | |
| if: steps.publish.outputs.published == 'true' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: node js/scripts/format-github-release.mjs --release-version "${{ steps.publish.outputs.published_version }}" --repository "${{ github.repository }}" --commit-sha "${{ github.sha }}" | |
| - name: Build JS API docs for release | |
| if: steps.publish.outputs.published == 'true' | |
| run: npm run docs:api | |
| - name: Setup Rust toolchain for release docs | |
| if: steps.publish.outputs.published == 'true' | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Build Rust crate docs for release | |
| if: steps.publish.outputs.published == 'true' | |
| run: cargo doc --manifest-path rust/Cargo.toml --no-deps --workspace | |
| - name: Attach API docs to GitHub Release | |
| if: steps.publish.outputs.published == 'true' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: bash js/scripts/attach-api-docs.sh "v${{ steps.publish.outputs.published_version }}" | |
| # Manual Instant Release - triggered via workflow_dispatch with instant mode | |
| # This job is in release.yml because npm trusted publishing | |
| # only allows one workflow file to be registered as a trusted publisher | |
| instant-release: | |
| name: Instant Release | |
| if: github.event_name == 'workflow_dispatch' && github.event.inputs.release_mode == 'instant' | |
| runs-on: ubuntu-latest | |
| # Same envelope as the automated release path. | |
| timeout-minutes: 30 | |
| # Permissions required for npm OIDC trusted publishing | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| id-token: write | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: '24.x' | |
| registry-url: 'https://registry.npmjs.org' | |
| - name: Install dependencies | |
| run: npm install | |
| - name: Update npm for OIDC trusted publishing | |
| run: node js/scripts/setup-npm.mjs | |
| - name: Version packages and commit to main | |
| id: version | |
| run: node js/scripts/version-and-commit.mjs --mode instant --bump-type "${{ github.event.inputs.bump_type }}" --description "${{ github.event.inputs.description }}" | |
| - name: Publish to npm | |
| # Run if version was committed OR if a previous attempt already committed (for re-runs) | |
| if: steps.version.outputs.version_committed == 'true' || steps.version.outputs.already_released == 'true' | |
| id: publish | |
| run: node js/scripts/publish-to-npm.mjs | |
| - name: Create GitHub Release | |
| if: steps.publish.outputs.published == 'true' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: node js/scripts/create-github-release.mjs --release-version "${{ steps.publish.outputs.published_version }}" --repository "${{ github.repository }}" | |
| - name: Format GitHub release notes | |
| if: steps.publish.outputs.published == 'true' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: node js/scripts/format-github-release.mjs --release-version "${{ steps.publish.outputs.published_version }}" --repository "${{ github.repository }}" --commit-sha "${{ github.sha }}" | |
| - name: Build JS API docs for release | |
| if: steps.publish.outputs.published == 'true' | |
| run: npm run docs:api | |
| - name: Setup Rust toolchain for release docs | |
| if: steps.publish.outputs.published == 'true' | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Build Rust crate docs for release | |
| if: steps.publish.outputs.published == 'true' | |
| run: cargo doc --manifest-path rust/Cargo.toml --no-deps --workspace | |
| - name: Attach API docs to GitHub Release | |
| if: steps.publish.outputs.published == 'true' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: bash js/scripts/attach-api-docs.sh "v${{ steps.publish.outputs.published_version }}" | |
| # Manual Changeset PR - creates a pull request with the changeset for review | |
| changeset-pr: | |
| name: Create Changeset PR | |
| if: github.event_name == 'workflow_dispatch' && github.event.inputs.release_mode == 'changeset-pr' | |
| runs-on: ubuntu-latest | |
| # PR creation only — install + format + open PR. 10min is generous. | |
| timeout-minutes: 10 | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: '24.x' | |
| - name: Install dependencies | |
| run: npm install | |
| - name: Create changeset file | |
| run: node js/scripts/create-manual-changeset.mjs --bump-type "${{ github.event.inputs.bump_type }}" --description "${{ github.event.inputs.description }}" | |
| - name: Format changeset with Prettier | |
| run: | | |
| # Run Prettier on the changeset file to ensure it matches project style | |
| npx prettier --write ".changeset/*.md" || true | |
| echo "Formatted changeset files" | |
| - name: Create Pull Request | |
| uses: peter-evans/create-pull-request@v8 | |
| with: | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| commit-message: 'chore: add changeset for manual ${{ github.event.inputs.bump_type }} release' | |
| branch: changeset-manual-release-${{ github.run_id }} | |
| delete-branch: true | |
| title: 'chore: manual ${{ github.event.inputs.bump_type }} release' | |
| body: | | |
| ## Manual Release Request | |
| This PR was created by a manual workflow trigger to prepare a **${{ github.event.inputs.bump_type }}** release. | |
| ### Release Details | |
| - **Type:** ${{ github.event.inputs.bump_type }} | |
| - **Description:** ${{ github.event.inputs.description || 'Manual release' }} | |
| - **Triggered by:** @${{ github.actor }} | |
| ### Next Steps | |
| 1. Review the changeset in this PR | |
| 2. Merge this PR to main | |
| 3. The automated release workflow will create a version PR | |
| 4. Merge the version PR to publish to npm and create a GitHub release |