From 48454ec26bd7aeab1d58cf29f223450120227d40 Mon Sep 17 00:00:00 2001 From: Siarhei Dudko Date: Wed, 6 May 2026 23:33:09 +0400 Subject: [PATCH] ci: restore actions to @v5/@v6 (node24 runtime) --- .github/workflows/autoupdate.yml | 107 ++++++++----------------------- .github/workflows/claude.yml | 28 +++----- .github/workflows/release.yml | 76 +++------------------- .github/workflows/test.yml | 31 ++------- 4 files changed, 49 insertions(+), 193 deletions(-) diff --git a/.github/workflows/autoupdate.yml b/.github/workflows/autoupdate.yml index de9a919..c39cab0 100644 --- a/.github/workflows/autoupdate.yml +++ b/.github/workflows/autoupdate.yml @@ -19,30 +19,17 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 30 steps: - - name: Checkout repo - uses: actions/checkout@v4 - with: - ref: main - token: ${{ secrets.GITHUB_TOKEN }} - fetch-depth: 0 - - - name: Configure git - run: | + - uses: actions/checkout@v5 + with: { ref: main, token: "${{ secrets.GITHUB_TOKEN }}", fetch-depth: 0 } + - run: | git config user.email "siarhei@dudko.dev" git config user.name "Siarhei Dudko" - - - name: Create autoupdate branch - run: | + - run: | git checkout -b "$AUTOUPDATE_BRANCH" git push -u origin "$AUTOUPDATE_BRANCH" - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: 24 - - - name: Autoupdate - id: autoupdate + - uses: actions/setup-node@v6 + with: { node-version: 24 } + - id: autoupdate continue-on-error: true uses: siarheidudko/autoupdater@v6 with: @@ -59,18 +46,14 @@ jobs: debug: "true" ignore-packages: | @types/node - - - name: Persist autoupdater work on failure - if: steps.autoupdate.outcome == 'failure' + - if: steps.autoupdate.outcome == 'failure' run: | if [ -n "$(git status --porcelain)" ]; then git add -A git commit -m "chore(deps): autoupdater partial update" fi git push --force-with-lease origin "HEAD:$AUTOUPDATE_BRANCH" || true - - - name: Fallback baseline update if branch still empty vs main - if: steps.autoupdate.outcome == 'failure' + - if: steps.autoupdate.outcome == 'failure' run: | git fetch origin main if git diff --quiet origin/main; then @@ -82,16 +65,12 @@ jobs: git push origin "HEAD:$AUTOUPDATE_BRANCH" fi fi - - - name: Ensure labels exist - env: + - env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | gh label create autoupdate --color "0e8a16" --description "Automated dependency update PRs" --force || true gh label create needs-claude --color "d4c5f9" --description "Needs Claude GitHub App to fix" --force || true - - - name: Check for diff vs main on remote branch - id: diff + - id: diff if: always() run: | git fetch origin main "$AUTOUPDATE_BRANCH" @@ -100,20 +79,13 @@ jobs: else echo "has_diff=true" >> "$GITHUB_OUTPUT" fi - - - name: Read package version from branch - id: pkg + - id: pkg if: steps.diff.outputs.has_diff == 'true' run: | VERSION=$(git show "origin/$AUTOUPDATE_BRANCH:package.json" | node -e "let s='';process.stdin.on('data',d=>s+=d).on('end',()=>console.log(JSON.parse(s).version))") echo "version=$VERSION" >> "$GITHUB_OUTPUT" - - - name: Open PR (autoupdater succeeded) - id: pr_success - if: | - steps.autoupdate.outcome == 'success' && - steps.autoupdate.outputs.updated == 'true' && - steps.diff.outputs.has_diff == 'true' + - id: pr_success + if: steps.autoupdate.outcome == 'success' && steps.autoupdate.outputs.updated == 'true' && steps.diff.outputs.has_diff == 'true' env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | @@ -126,15 +98,9 @@ jobs: PR-checks (CI workflow) must be green before merge. EOF ) - PR_URL=$(gh pr create \ - --base main \ - --head "$AUTOUPDATE_BRANCH" \ - --title "chore(deps): autoupdate v${{ steps.pkg.outputs.version }}" \ - --body "$BODY") + PR_URL=$(gh pr create --base main --head "$AUTOUPDATE_BRANCH" --title "chore(deps): autoupdate v${{ steps.pkg.outputs.version }}" --body "$BODY") echo "pr_url=$PR_URL" >> "$GITHUB_OUTPUT" - - - name: Open draft PR (autoupdater failed) - id: pr_failure + - id: pr_failure if: steps.autoupdate.outcome == 'failure' && steps.diff.outputs.has_diff == 'true' env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -153,37 +119,21 @@ jobs: npm run build npm test - See **Actions → Claude** for progress. The CI workflow will - re-run on each new commit to confirm a green state before merge. + See **Actions → Claude** for progress. EOF ) - PR_URL=$(gh pr create \ - --base main \ - --head "$AUTOUPDATE_BRANCH" \ - --title "chore(deps): autoupdate (needs claude fix)" \ - --body "$BODY" \ - --draft) + PR_URL=$(gh pr create --base main --head "$AUTOUPDATE_BRANCH" --title "chore(deps): autoupdate (needs claude fix)" --body "$BODY" --draft) echo "pr_url=$PR_URL" >> "$GITHUB_OUTPUT" - - - name: Trigger CI on autoupdate branch (GITHUB_TOKEN can't auto-trigger pull_request) - if: steps.pr_success.outputs.pr_url != '' || steps.pr_failure.outputs.pr_url != '' + - if: steps.pr_success.outputs.pr_url != '' || steps.pr_failure.outputs.pr_url != '' env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - gh workflow run test.yml --ref "$AUTOUPDATE_BRANCH" || true - - - name: Dispatch Claude to fix the failed autoupdate - if: steps.pr_failure.outputs.pr_url != '' + run: gh workflow run test.yml --ref "$AUTOUPDATE_BRANCH" || true + - if: steps.pr_failure.outputs.pr_url != '' env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} - run: | - gh workflow run claude.yml --ref main \ - -f branch="$AUTOUPDATE_BRANCH" \ - -f run_url="$RUN_URL" - - - name: Post info comment on the failure PR - if: steps.pr_failure.outputs.pr_url != '' + run: gh workflow run claude.yml --ref main -f branch="$AUTOUPDATE_BRANCH" -f run_url="$RUN_URL" + - if: steps.pr_failure.outputs.pr_url != '' env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} PR_URL: ${{ steps.pr_failure.outputs.pr_url }} @@ -196,9 +146,7 @@ jobs: EOF ) gh pr comment "$PR_URL" --body "$COMMENT" - - - name: Add labels to PR - if: steps.pr_success.outputs.pr_url != '' || steps.pr_failure.outputs.pr_url != '' + - if: steps.pr_success.outputs.pr_url != '' || steps.pr_failure.outputs.pr_url != '' env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} PR_URL: ${{ steps.pr_success.outputs.pr_url || steps.pr_failure.outputs.pr_url }} @@ -208,8 +156,5 @@ jobs: else gh pr edit "$PR_URL" --add-label autoupdate || true fi - - - name: Cleanup branch when nothing to ship - if: always() && steps.diff.outputs.has_diff != 'true' - run: | - git push origin --delete "$AUTOUPDATE_BRANCH" || true + - if: always() && steps.diff.outputs.has_diff != 'true' + run: git push origin --delete "$AUTOUPDATE_BRANCH" || true diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml index 36dca2a..bace876 100644 --- a/.github/workflows/claude.yml +++ b/.github/workflows/claude.yml @@ -10,14 +10,8 @@ on: types: [opened, assigned] workflow_dispatch: inputs: - branch: - description: "Branch Claude should operate on (used by autoupdate flow)" - required: true - type: string - run_url: - description: "URL of the failing autoupdate run, included in the prompt for context" - required: false - type: string + branch: { required: true, type: string } + run_url: { required: false, type: string } concurrency: group: "${{ github.workflow }} @ ${{ github.event.issue.number || github.event.pull_request.number || github.event.inputs.branch }}" cancel-in-progress: false @@ -38,14 +32,11 @@ jobs: id-token: write actions: read steps: - - name: Checkout repo - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: ref: ${{ github.event.inputs.branch || github.ref }} fetch-depth: 1 - - - name: Prepare autoupdate-fix prompt - if: github.event_name == 'workflow_dispatch' + - if: github.event_name == 'workflow_dispatch' id: prep env: BRANCH: ${{ github.event.inputs.branch }} @@ -72,21 +63,18 @@ jobs: if any of them is red. - If \`npm install\` or \`npm ci\` is needed, run it first with \`--no-audit --no-fund\` and confirm exit 0. - - Limit edits to compatibility shims (types, renamed exports, - breaking-change adjustments). Do NOT change product logic. + - Limit edits to compatibility shims. - Do NOT bump the package version. - Mind the existing CLAUDE.md guardrails: Zod \`z.ZodType\` collection trick, no \`.max()\` on Zod arrays in Anthropic structured output. - - When all are green, push and stop. CI will re-verify on the PR. + - When all are green, push and stop. - See CLAUDE.md in the repo root for the full project conventions. + See CLAUDE.md in the repo root. EOF echo PROMPT_EOF } >> "$GITHUB_OUTPUT" - - - name: Run Claude Code - uses: anthropics/claude-code-action@v1 + - uses: anthropics/claude-code-action@v1 with: claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} allowed_bots: "*" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1323d9f..cf6e2c3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,17 +1,9 @@ name: Release - -# Triggered after CI completes on main. The workflow_run trigger guarantees -# we only publish commits that already passed tests on main, while keeping -# release as a separate workflow file so it can be wired to the npm trusted -# publisher (Settings -> Packages -> Trusted Publishers): point npm at this -# workflow filename (`release.yml`) and the `release` environment below. on: workflow_run: workflows: [CI] branches: [main] types: [completed] - # Manual trigger - publish from a specific tag, branch or commit SHA. - # Leave `ref` empty to publish from main HEAD. workflow_dispatch: inputs: ref: @@ -19,45 +11,27 @@ on: type: string required: false default: '' - permissions: - # Needed to push the version tag back to the repository. contents: write - # Required for npm provenance + npm trusted-publisher OIDC exchange. id-token: write - jobs: release: name: Publish to npm runs-on: ubuntu-latest - # Skip when CI failed; workflow_dispatch has no workflow_run context, so - # the second clause lets manual runs through. if: >- github.event_name == 'workflow_dispatch' || (github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success') environment: release steps: - - name: Checkout - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: - # Resolution order: - # 1. workflow_dispatch input (manual republish at a specific ref) - # 2. workflow_run head SHA (the commit that just passed CI) - # 3. github.ref (defensive default; should not be hit) ref: ${{ inputs.ref != '' && inputs.ref || github.event.workflow_run.head_sha || github.ref }} - # Full history so `git push origin ` succeeds. fetch-depth: 0 - - - name: Setup Node.js - uses: actions/setup-node@v4 + - uses: actions/setup-node@v6 with: - node-version: '22' - - - name: Install dependencies - run: npm ci - - - name: Resolve package metadata - id: meta + node-version: '24' + - run: npm ci + - id: meta run: | set -euo pipefail NAME=$(node -p "require('./package.json').name") @@ -68,9 +42,7 @@ jobs: echo "version=$VERSION" echo "tag=$TAG" } >>"$GITHUB_OUTPUT" - - - name: Skip if version already on npm - id: check + - id: check run: | set -euo pipefail if npm view "${{ steps.meta.outputs.name }}@${{ steps.meta.outputs.version }}" version >/dev/null 2>&1; then @@ -80,63 +52,31 @@ jobs: echo "publish=true" >>"$GITHUB_OUTPUT" echo "::notice::Will publish ${{ steps.meta.outputs.name }}@${{ steps.meta.outputs.version }}." fi - - # `npm publish` runs `prepublishOnly` (typecheck && test && build), so - # we don't pre-build here. - # - # We publish via `npx -y npm@11.5.1` rather than the system npm: - # Trusted Publishing requires npm >= 11.5.1, and Node 22 LTS still - # bundles npm 10.x. corepack-based shims have proven flaky on hosted - # runners (the activate step doesn't always land first in PATH), so - # we pin npm explicitly for this single command. - # - # Auth strategy: - # - Preferred: npm Trusted Publishing (OIDC). No secret needed; npm - # verifies this workflow + environment against the package's - # Trusted Publisher config on npmjs.com. - # - Bootstrap / fallback: NPM_TOKEN repo secret. Used automatically - # when present (NODE_AUTH_TOKEN empty -> OIDC is attempted; - # non-empty -> classic token wins). Set NPM_TOKEN as a Granular - # Access Token if TP is not yet configured. - - name: Publish to npm - if: steps.check.outputs.publish == 'true' + - if: steps.check.outputs.publish == 'true' run: | set -euo pipefail - echo "Publishing with:" npx -y npm@11.5.1 --version npx -y npm@11.5.1 publish --provenance env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - - - name: Create git tag and GitHub release - if: steps.check.outputs.publish == 'true' + - if: steps.check.outputs.publish == 'true' env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | set -euo pipefail TAG="${{ steps.meta.outputs.tag }}" - - # Idempotency: a previous publish that succeeded on npm but failed - # to push the tag (or a manual republish at the same ref) should - # not crash the job - just reuse the existing tag/release. if gh release view "$TAG" >/dev/null 2>&1; then echo "::notice::GitHub release $TAG already exists; skipping tag/release creation." exit 0 fi - git config user.name "Siarhei Dudko" git config user.email "siarhei@dudko.dev" - if git rev-parse --verify "refs/tags/$TAG" >/dev/null 2>&1; then echo "::notice::Git tag $TAG already exists locally; reusing without re-tagging." else git tag -a "$TAG" -m "Release $TAG" git push origin "$TAG" fi - - # Auto-generated notes diff against the previous release tag - on - # the first run for a repo there's no prior tag, so gh falls back - # to the full commit history; both cases are handled internally. gh release create "$TAG" \ --title "$TAG" \ --generate-notes \ diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8822b20..76a798b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -5,8 +5,6 @@ on: branches: [main] push: branches: [main] - # Lets a maintainer re-run the suite from the Actions tab without pushing, - # e.g. to verify a flaky test passes against the current main HEAD. workflow_dispatch: jobs: @@ -19,28 +17,13 @@ jobs: matrix: node-version: ['22', '24'] steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v4 + - uses: actions/checkout@v5 + - uses: actions/setup-node@v6 with: node-version: ${{ matrix.node-version }} cache: npm - - - name: Install dependencies - run: npm ci - - - name: Typecheck - run: npm run typecheck - - - name: Format check - run: npm run format:check - - # Build before tests so the dist-loadable suite can verify both the - # CJS and ESM bundles actually load (it skips itself on a clean tree). - - name: Build - run: npm run build - - - name: Test - run: npm test + - run: npm ci + - run: npm run typecheck + - run: npm run format:check + - run: npm run build + - run: npm test