From 3dc8e5af49508577bf19052c18eaf2ada253f920 Mon Sep 17 00:00:00 2001 From: Siarhei Dudko Date: Thu, 7 May 2026 01:19:03 +0400 Subject: [PATCH 1/2] ci(autoupdate): cron Sat 03:00 Tbilisi (Fri 23:00 UTC) --- .github/workflows/autoupdate.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/autoupdate.yml b/.github/workflows/autoupdate.yml index c39cab0..e422483 100644 --- a/.github/workflows/autoupdate.yml +++ b/.github/workflows/autoupdate.yml @@ -1,7 +1,7 @@ name: Autoupdate on: schedule: - - cron: "0 6 * * 1" + - cron: "0 23 * * 5" workflow_dispatch: workflow_call: concurrency: From 5261fec5df2c83f3f600fe7f1e45f1eb49fe42ff Mon Sep 17 00:00:00 2001 From: Siarhei Dudko Date: Thu, 7 May 2026 01:44:48 +0400 Subject: [PATCH 2/2] =?UTF-8?q?ci:=20unify=20workflow=20yaml=20structure?= =?UTF-8?q?=20(uniform=20job/step=20names=20+=20Claude=20must=20comment=20?= =?UTF-8?q?+=20rename=20test.yml=E2=86=92pr-checks.yml=20+=20release.yml?= =?UTF-8?q?=20workflow=5Frun=20=E2=86=92=20[PR=20checks])?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/autoupdate.yml | 104 ++++++++++++++++++++----------- .github/workflows/claude.yml | 61 +++++++++++++----- .github/workflows/pr-checks.yml | 77 +++++++++++++++++++++++ .github/workflows/release.yml | 2 +- 4 files changed, 190 insertions(+), 54 deletions(-) create mode 100644 .github/workflows/pr-checks.yml diff --git a/.github/workflows/autoupdate.yml b/.github/workflows/autoupdate.yml index e422483..3f572b3 100644 --- a/.github/workflows/autoupdate.yml +++ b/.github/workflows/autoupdate.yml @@ -16,20 +16,32 @@ env: AUTOUPDATE_BRANCH: chore/autoupdate-${{ github.run_id }} jobs: update: + name: Autoupdate dependencies runs-on: ubuntu-latest timeout-minutes: 30 + steps: - - uses: actions/checkout@v5 - with: { ref: main, token: "${{ secrets.GITHUB_TOKEN }}", fetch-depth: 0 } - - run: | + - name: Checkout repo + uses: actions/checkout@v5 + with: + ref: main + token: ${{ secrets.GITHUB_TOKEN }} + fetch-depth: 0 + - name: Configure git + run: | git config user.email "siarhei@dudko.dev" git config user.name "Siarhei Dudko" - - run: | + - name: Create autoupdate branch + run: | git checkout -b "$AUTOUPDATE_BRANCH" git push -u origin "$AUTOUPDATE_BRANCH" - - uses: actions/setup-node@v6 - with: { node-version: 24 } - - id: autoupdate + - name: Setup Node.js + uses: actions/setup-node@v6 + with: + node-version: 24 + + - name: Run autoupdater + id: autoupdate continue-on-error: true uses: siarheidudko/autoupdater@v6 with: @@ -46,14 +58,16 @@ jobs: debug: "true" ignore-packages: | @types/node - - if: steps.autoupdate.outcome == 'failure' + - name: Persist autoupdater work on 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 - - if: steps.autoupdate.outcome == 'failure' + - name: Fallback baseline update if branch still empty vs main + if: steps.autoupdate.outcome == 'failure' run: | git fetch origin main if git diff --quiet origin/main; then @@ -65,12 +79,14 @@ jobs: git push origin "HEAD:$AUTOUPDATE_BRANCH" fi fi - - env: + - name: Ensure labels exist + 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 - - id: diff + - name: Detect diff vs main + id: diff if: always() run: | git fetch origin main "$AUTOUPDATE_BRANCH" @@ -79,13 +95,18 @@ jobs: else echo "has_diff=true" >> "$GITHUB_OUTPUT" fi - - id: pkg + - name: Read package version from branch + 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" - - id: pr_success - if: steps.autoupdate.outcome == 'success' && steps.autoupdate.outputs.updated == 'true' && steps.diff.outputs.has_diff == 'true' + - name: Open PR (autoupdater succeeded) + 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: | @@ -95,12 +116,17 @@ jobs: - autoupdater outcome: success - target version: v${{ steps.pkg.outputs.version }} - PR-checks (CI workflow) must be green before merge. + PR-checks 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" - - id: pr_failure + - name: Open draft PR (autoupdater failed) + id: pr_failure if: steps.autoupdate.outcome == 'failure' && steps.diff.outputs.has_diff == 'true' env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -119,34 +145,36 @@ jobs: npm run build npm test - See **Actions → Claude** for progress. + Claude will leave a status comment on this PR when it finishes. + PR-checks will re-run on each new commit. 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" - - if: steps.pr_success.outputs.pr_url != '' || steps.pr_failure.outputs.pr_url != '' + - name: Trigger PR checks (GITHUB_TOKEN can't auto-trigger pull_request) + 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 - - 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" - - if: steps.pr_failure.outputs.pr_url != '' + run: | + gh workflow run pr-checks.yml --ref "$AUTOUPDATE_BRANCH" || true + - name: Dispatch Claude to fix the failed autoupdate + if: steps.pr_failure.outputs.pr_url != '' env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} PR_URL: ${{ steps.pr_failure.outputs.pr_url }} RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} run: | - COMMENT=$(cat <" + + The comment must state plainly: + - Which command(s) failed initially (or "all green on first run"). + - What changes you made (or "no fix needed"). + - Whether you pushed any commits, and the SHA(s) if so. + + Do NOT exit without posting this comment. The maintainer relies + on it to know what happened without reading the action log. - See CLAUDE.md in the repo root. + See CLAUDE.md in the repo root for the full project conventions. EOF echo PROMPT_EOF } >> "$GITHUB_OUTPUT" - - uses: anthropics/claude-code-action@v1 + - name: Run Claude Code + uses: anthropics/claude-code-action@v1 with: claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} allowed_bots: "*" prompt: ${{ steps.prep.outputs.prompt }} claude_args: | - --allowedTools "Edit,Write,MultiEdit,Bash(git:*),Bash(npm:*),Bash(npx:*),Bash(node:*),Bash(rm:*),Bash(mkdir:*),Bash(cat:*),Bash(ls:*),Bash(echo:*),Bash(grep:*),Bash(find:*),Bash(sed:*),Bash(awk:*),Bash(head:*),Bash(tail:*),Bash(diff:*),Bash(mv:*),Bash(cp:*),Bash(touch:*)" + --allowedTools "Edit,Write,MultiEdit,Bash(git:*),Bash(gh:*),Bash(npm:*),Bash(npx:*),Bash(node:*),Bash(rm:*),Bash(mkdir:*),Bash(cat:*),Bash(ls:*),Bash(echo:*),Bash(grep:*),Bash(find:*),Bash(sed:*),Bash(awk:*),Bash(head:*),Bash(tail:*),Bash(diff:*),Bash(mv:*),Bash(cp:*),Bash(touch:*)" diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml new file mode 100644 index 0000000..7684478 --- /dev/null +++ b/.github/workflows/pr-checks.yml @@ -0,0 +1,77 @@ +name: PR checks +on: + pull_request: + branches: [main] + workflow_dispatch: +concurrency: + group: "${{ github.workflow }} @ ${{ github.ref }}" + cancel-in-progress: true +permissions: + contents: read +jobs: + build: + name: Build + runs-on: ubuntu-latest + timeout-minutes: 5 + env: + NODE_VERSION: 24 + steps: + - name: Checkout repo + uses: actions/checkout@v5 + - name: Use Node.js ${{ env.NODE_VERSION }} + uses: actions/setup-node@v6 + with: + node-version: ${{ env.NODE_VERSION }} + - name: Cache node modules + uses: actions/cache@v4 + with: + path: ~/.npm + key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-node- + - name: Install dependencies + run: npm ci + - name: Typecheck + run: npm run typecheck + - name: Format check + run: npm run format:check + - name: Run builder + run: npm run build + - name: Archive build artifact + uses: actions/upload-artifact@v4 + with: + name: dist + path: ${{ github.workspace }}/dist + test: + name: Test (Node ${{ matrix.node-version }}) + runs-on: ubuntu-latest + timeout-minutes: 15 + needs: build + strategy: + matrix: + node-version: [22, 24] + + steps: + - name: Checkout repo + uses: actions/checkout@v5 + - name: Download build artifact + uses: actions/download-artifact@v4 + with: + name: dist + path: ${{ github.workspace }}/dist + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v6 + with: + node-version: ${{ matrix.node-version }} + - name: Cache node modules + uses: actions/cache@v4 + with: + path: ~/.npm + key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-node- + - name: Install dependencies + run: npm ci + + - name: Run test + run: npm test diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index cf6e2c3..05ff0d5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,7 +1,7 @@ name: Release on: workflow_run: - workflows: [CI] + workflows: [PR checks] branches: [main] types: [completed] workflow_dispatch: