Commit review openclaw/openclaw@f927e532da241c7469c29f857234e06dd9712e34 #13820
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: ClawSweeper Commit Review | |
| run-name: Commit review ${{ github.event.inputs.target_repo || github.event.client_payload.target_repo || 'openclaw/openclaw' }}@${{ github.event.inputs.commit_sha || github.event.client_payload.after_sha || github.event.client_payload.commit_sha || '?' }} | |
| on: | |
| repository_dispatch: | |
| types: [clawsweeper_commit_review] | |
| workflow_dispatch: | |
| inputs: | |
| enabled: | |
| description: "Run commit review" | |
| required: false | |
| default: "true" | |
| target_repo: | |
| description: "Repository containing the main commit" | |
| required: false | |
| default: "openclaw/openclaw" | |
| commit_sha: | |
| description: "Specific commit SHA to review" | |
| required: true | |
| before_sha: | |
| description: "Optional base SHA; defaults to the commit's first parent" | |
| required: false | |
| default: "" | |
| commit_offset: | |
| description: "Internal offset for continuation runs" | |
| required: false | |
| default: "0" | |
| create_checks: | |
| description: "Create/update GitHub Checks on reviewed commits" | |
| required: false | |
| default: "" | |
| additional_prompt: | |
| description: "Optional extra review instruction appended to the prompt" | |
| required: false | |
| default: "" | |
| permissions: | |
| contents: write | |
| actions: write | |
| env: | |
| FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" | |
| CLAWSWEEPER_APP_CLIENT_ID: Iv23liOECG0slfuhz093 | |
| concurrency: | |
| group: commit-review-${{ github.event.inputs.target_repo || github.event.client_payload.target_repo || 'openclaw/openclaw' }}-${{ github.event.inputs.commit_sha || github.event.client_payload.after_sha || github.event.client_payload.commit_sha || github.run_id }} | |
| cancel-in-progress: false | |
| jobs: | |
| disabled-target: | |
| name: Skip disabled target commit review | |
| if: ${{ github.event_name == 'repository_dispatch' && github.event.client_payload.target_repo == 'openclaw/clawhub' && vars.CLAWSWEEPER_ENABLE_CLAWHUB != '1' }} | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| steps: | |
| - name: Explain skipped commit review | |
| run: | | |
| echo "Skipping commit review for ${{ github.event.client_payload.target_repo }}." | |
| echo "Set CLAWSWEEPER_ENABLE_CLAWHUB=1 after installing the ClawSweeper GitHub App on openclaw/clawhub." | |
| plan: | |
| name: Plan commits | |
| if: ${{ !(github.event_name == 'repository_dispatch' && github.event.client_payload.target_repo == 'openclaw/clawhub' && vars.CLAWSWEEPER_ENABLE_CLAWHUB != '1') }} | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 40 | |
| outputs: | |
| create_checks: ${{ steps.mode.outputs.create_checks }} | |
| enabled: ${{ steps.mode.outputs.enabled }} | |
| has_more: ${{ steps.select.outputs.has_more }} | |
| matrix: ${{ steps.select.outputs.matrix }} | |
| next_offset: ${{ steps.select.outputs.next_offset }} | |
| planned_count: ${{ steps.select.outputs.planned_count }} | |
| skipped_count: ${{ steps.select.outputs.skipped_count }} | |
| target_checkout_dir: ${{ steps.target.outputs.target_checkout_dir }} | |
| target_repo: ${{ steps.target.outputs.target_repo }} | |
| target_repo_name: ${{ steps.target.outputs.target_repo_name }} | |
| target_repo_owner: ${{ steps.target.outputs.target_repo_owner }} | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| path: clawsweeper | |
| filter: blob:none | |
| fetch-depth: 1 | |
| - name: Resolve mode | |
| id: mode | |
| run: | | |
| enabled="${{ github.event.inputs.enabled || github.event.client_payload.enabled || 'true' }}" | |
| create_checks="${{ github.event.inputs.create_checks || github.event.client_payload.create_checks || vars.CLAWSWEEPER_COMMIT_REVIEW_CREATE_CHECKS || 'false' }}" | |
| case "$enabled" in | |
| false|FALSE|0|no|NO|off|OFF) | |
| echo "Commit review disabled by input/payload." | |
| echo "enabled=false" >> "$GITHUB_OUTPUT" | |
| echo "create_checks=false" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| ;; | |
| esac | |
| case "$create_checks" in | |
| true|TRUE|1|yes|YES|on|ON) create_checks=true ;; | |
| *) create_checks=false ;; | |
| esac | |
| echo "enabled=true" >> "$GITHUB_OUTPUT" | |
| echo "create_checks=$create_checks" >> "$GITHUB_OUTPUT" | |
| - name: Resolve target repository | |
| id: target | |
| run: | | |
| target_repo="${{ github.event.inputs.target_repo || github.event.client_payload.target_repo || 'openclaw/openclaw' }}" | |
| if ! printf '%s' "$target_repo" | grep -Eq '^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$'; then | |
| echo "Invalid target_repo: $target_repo" >&2 | |
| exit 1 | |
| fi | |
| target_owner="${target_repo%%/*}" | |
| target_name="${target_repo#*/}" | |
| { | |
| echo "target_repo=$target_repo" | |
| echo "target_repo_owner=$target_owner" | |
| echo "target_repo_name=$target_name" | |
| echo "target_checkout_dir=target-$target_name" | |
| } >> "$GITHUB_OUTPUT" | |
| - name: Create target read token | |
| id: target-read-token | |
| uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1 | |
| with: | |
| client-id: ${{ env.CLAWSWEEPER_APP_CLIENT_ID }} | |
| private-key: ${{ secrets.CLAWSWEEPER_APP_PRIVATE_KEY }} | |
| owner: ${{ steps.target.outputs.target_repo_owner }} | |
| repositories: ${{ steps.target.outputs.target_repo_name }} | |
| permission-actions: read | |
| permission-contents: read | |
| permission-issues: read | |
| permission-pull-requests: read | |
| - name: Create state token | |
| id: state-token | |
| uses: ./clawsweeper/.github/actions/create-state-token | |
| with: | |
| client-id: ${{ env.CLAWSWEEPER_APP_CLIENT_ID }} | |
| private-key: ${{ secrets.CLAWSWEEPER_APP_PRIVATE_KEY }} | |
| - uses: ./clawsweeper/.github/actions/setup-state | |
| with: | |
| token: ${{ steps.state-token.outputs.token }} | |
| worktree-path: clawsweeper | |
| fetch-depth: 1 | |
| - uses: ./clawsweeper/.github/actions/setup-pnpm | |
| with: | |
| working-directory: clawsweeper | |
| build-script: build:all | |
| - name: Select commits | |
| id: select | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| TARGET_REPO: ${{ steps.target.outputs.target_repo }} | |
| TARGET_NAME: ${{ steps.target.outputs.target_checkout_dir }} | |
| TARGET_TOKEN: ${{ steps.target-read-token.outputs.token }} | |
| COMMIT_SHA: ${{ github.event.inputs.commit_sha || github.event.client_payload.after_sha || github.event.client_payload.commit_sha || '' }} | |
| BEFORE_SHA: ${{ github.event.inputs.before_sha || github.event.client_payload.before_sha || '' }} | |
| COMMIT_OFFSET: ${{ github.event.inputs.commit_offset || github.event.client_payload.commit_offset || '0' }} | |
| ENABLED: ${{ steps.mode.outputs.enabled }} | |
| SOURCE_REF: ${{ github.event.client_payload.ref || 'refs/heads/main' }} | |
| SETTLE_SECONDS: ${{ vars.CLAWSWEEPER_COMMIT_REVIEW_SETTLE_SECONDS || '60' }} | |
| PAGE_SIZE: ${{ vars.CLAWSWEEPER_COMMIT_REVIEW_PAGE_SIZE || '' }} | |
| run: | | |
| set -euo pipefail | |
| active_runs_json() { | |
| { | |
| for run_status in in_progress pending queued waiting requested; do | |
| gh api "repos/${{ github.repository }}/actions/runs?per_page=100&status=${run_status}" \ | |
| --jq '.workflow_runs[] | {databaseId:.id, workflowName:.name, displayTitle:.display_title, status:.status}' 2>/dev/null \ | |
| || true | |
| done | |
| } | jq -s 'unique_by(.databaseId)' | |
| } | |
| ACTIVE_RUNS_JSON="$(active_runs_json)" | |
| active_run_count() { | |
| printf '%s' "$ACTIVE_RUNS_JSON" \ | |
| | WORKFLOW_NAME="$1" jq '[.[] | select(.workflowName == env.WORKFLOW_NAME) | select(.status == "in_progress" or .status == "pending" or .status == "queued" or .status == "waiting" or .status == "requested")] | length' 2>/dev/null \ | |
| || printf '0' | |
| } | |
| active_sweep_background_workers() { | |
| local runs total id title status active_shards | |
| total=0 | |
| runs="$(printf '%s' "$ACTIVE_RUNS_JSON" \ | |
| | jq -r '.[] | select(.workflowName == "ClawSweeper") | select(.status == "in_progress" or .status == "pending" or .status == "queued" or .status == "waiting" or .status == "requested") | select(.displayTitle == "Review ClawSweeper items" or .displayTitle == "Review hot ClawSweeper items") | [.databaseId, .displayTitle, .status] | @tsv' 2>/dev/null || true)" | |
| while IFS=$'\t' read -r id title status; do | |
| if [ -z "$id" ]; then | |
| continue | |
| fi | |
| active_shards=0 | |
| if [ "$status" = "in_progress" ]; then | |
| active_shards="$(gh run view "$id" --repo "${{ github.repository }}" --json jobs 2>/dev/null \ | |
| | jq '[.jobs[]? | select(.name | startswith("Review shard ")) | select(.status == "in_progress" or .status == "pending" or .status == "queued" or .status == "waiting" or .status == "requested")] | length' 2>/dev/null \ | |
| || printf '0')" | |
| fi | |
| if ! [[ "$active_shards" =~ ^[0-9]+$ ]]; then | |
| active_shards=0 | |
| fi | |
| # Planning, publish, queued, and not-yet-expanded matrix runs have not | |
| # created shard jobs yet. Reserve their quiet lane size so commit review | |
| # does not over-allocate while a sweep matrix is still expanding. | |
| if [ "$active_shards" -lt 1 ]; then | |
| if [ "$title" = "Review hot ClawSweeper items" ]; then | |
| active_shards="$(pnpm --dir clawsweeper run --silent workflow -- limit review_shards.hot_intake_default)" | |
| else | |
| active_shards="$(pnpm --dir clawsweeper run --silent workflow -- limit review_shards.normal_default)" | |
| fi | |
| fi | |
| total=$((total + active_shards)) | |
| done <<< "$runs" | |
| printf '%s' "$total" | |
| } | |
| active_sweep_exact_count() { | |
| printf '%s' "$ACTIVE_RUNS_JSON" \ | |
| | jq '[.[] | select(.workflowName == "ClawSweeper") | select(.status == "in_progress" or .status == "pending" or .status == "queued" or .status == "waiting" or .status == "requested") | select(.displayTitle | startswith("Review event item "))] | length' 2>/dev/null \ | |
| || printf '0' | |
| } | |
| if [ -z "$PAGE_SIZE" ]; then | |
| active_critical_workers="$(( $(active_run_count "repair cluster worker") + $(active_sweep_exact_count) ))" | |
| active_background_workers="$(active_sweep_background_workers)" | |
| PAGE_SIZE="$(pnpm --dir clawsweeper run --silent workflow -- worker-limit commit_review --active-critical "$active_critical_workers" --active-background "$active_background_workers")" | |
| fi | |
| page_size_hard_cap="$(pnpm --dir clawsweeper run --silent workflow -- limit commit_review.page_size_hard_cap)" | |
| if [ "$ENABLED" = "false" ]; then | |
| { | |
| echo "matrix=[]" | |
| echo "has_more=false" | |
| echo "next_offset=0" | |
| echo "planned_count=0" | |
| echo "skipped_count=0" | |
| } >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| if ! printf '%s' "$COMMIT_OFFSET" | grep -Eq '^[0-9]+$'; then | |
| echo "Invalid commit offset: $COMMIT_OFFSET" >&2 | |
| exit 1 | |
| fi | |
| if [ "$SOURCE_REF" != "refs/heads/main" ]; then | |
| echo "Commit review only accepts main branch pushes; got $SOURCE_REF" >&2 | |
| exit 1 | |
| fi | |
| if [ -z "$COMMIT_SHA" ]; then | |
| echo "Missing commit SHA." >&2 | |
| exit 1 | |
| fi | |
| if ! printf '%s' "$COMMIT_SHA" | grep -Eq '^[0-9a-fA-F]{40}$'; then | |
| echo "Invalid commit SHA: $COMMIT_SHA" >&2 | |
| exit 1 | |
| fi | |
| if [ -n "$BEFORE_SHA" ] && ! printf '%s' "$BEFORE_SHA" | grep -Eq '^(0{40}|[0-9a-fA-F]{40})$'; then | |
| echo "Invalid before SHA: $BEFORE_SHA" >&2 | |
| exit 1 | |
| fi | |
| if ! printf '%s' "$SETTLE_SECONDS" | grep -Eq '^[0-9]+$'; then | |
| echo "Invalid settle wait: $SETTLE_SECONDS" >&2 | |
| exit 1 | |
| fi | |
| if ! printf '%s' "$PAGE_SIZE" | grep -Eq '^[0-9]+$'; then | |
| echo "Invalid commit review page size: $PAGE_SIZE" >&2 | |
| exit 1 | |
| fi | |
| if [ "$PAGE_SIZE" -lt 1 ]; then | |
| PAGE_SIZE=1 | |
| fi | |
| if [ "$PAGE_SIZE" -gt "$page_size_hard_cap" ]; then | |
| PAGE_SIZE="$page_size_hard_cap" | |
| fi | |
| if [ "$SETTLE_SECONDS" -gt 0 ]; then | |
| echo "Waiting ${SETTLE_SECONDS}s for target main to settle before selecting commits." | |
| sleep "$SETTLE_SECONDS" | |
| fi | |
| url="https://x-access-token:${TARGET_TOKEN}@github.com/${TARGET_REPO}.git" | |
| git clone --filter=blob:none --no-checkout "$url" "$TARGET_NAME" | |
| git -C "$TARGET_NAME" fetch --no-tags origin main --depth=1000 | |
| git -C "$TARGET_NAME" fetch --no-tags origin "$COMMIT_SHA" --depth=200 | |
| if ! git -C "$TARGET_NAME" merge-base --is-ancestor "$COMMIT_SHA" refs/remotes/origin/main; then | |
| echo "Commit $COMMIT_SHA is not reachable from origin/main in the fetched history." >&2 | |
| exit 1 | |
| fi | |
| if [ -n "$BEFORE_SHA" ] && ! printf '%s' "$BEFORE_SHA" | grep -Eq '^0{40}$'; then | |
| git -C "$TARGET_NAME" fetch --no-tags origin "$BEFORE_SHA" --depth=200 || true | |
| commits="$(git -C "$TARGET_NAME" rev-list --reverse "$BEFORE_SHA..$COMMIT_SHA" || true)" | |
| else | |
| commits="$COMMIT_SHA" | |
| fi | |
| if [ -z "$commits" ]; then | |
| commits="$COMMIT_SHA" | |
| fi | |
| total_count="$(printf '%s\n' "$commits" | sed '/^$/d' | wc -l | tr -d ' ')" | |
| page_size="$PAGE_SIZE" | |
| start_line=$((COMMIT_OFFSET + 1)) | |
| end_line=$((COMMIT_OFFSET + page_size)) | |
| selected_commits="$(printf '%s\n' "$commits" | sed -n "${start_line},${end_line}p")" | |
| selected_count="$(printf '%s\n' "$selected_commits" | sed '/^$/d' | wc -l | tr -d ' ')" | |
| next_offset=$((COMMIT_OFFSET + selected_count)) | |
| has_more=false | |
| if [ "$next_offset" -lt "$total_count" ]; then | |
| has_more=true | |
| fi | |
| node clawsweeper/dist/commit-sweeper.js classify \ | |
| --target-repo "$TARGET_REPO" \ | |
| --target-dir "$TARGET_NAME" \ | |
| --commit-shas "$selected_commits" \ | |
| --artifact-dir skipped-commit-artifacts > classify.json | |
| cat classify.json | |
| node clawsweeper/dist/repair/workflow-utils.js classify-output \ | |
| --classify classify.json \ | |
| --has-more "$has_more" \ | |
| --next-offset "$next_offset" >> "$GITHUB_OUTPUT" | |
| echo "Selected $selected_count/$total_count commits at offset $COMMIT_OFFSET" | |
| printf 'Selected commits:\n%s\n' "$selected_commits" | |
| - uses: actions/upload-artifact@v7 | |
| if: always() | |
| with: | |
| name: skipped-commit-reports | |
| path: skipped-commit-artifacts | |
| if-no-files-found: ignore | |
| review: | |
| name: Review commit ${{ matrix.sha }} | |
| needs: plan | |
| if: ${{ needs.plan.outputs.planned_count != '0' }} | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 45 | |
| permissions: | |
| contents: read | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: ${{ fromJson(needs.plan.outputs.matrix) }} | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| path: clawsweeper | |
| filter: blob:none | |
| fetch-depth: 1 | |
| persist-credentials: false | |
| - name: Create target read token | |
| id: target-read-token | |
| uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1 | |
| with: | |
| client-id: ${{ env.CLAWSWEEPER_APP_CLIENT_ID }} | |
| private-key: ${{ secrets.CLAWSWEEPER_APP_PRIVATE_KEY }} | |
| owner: ${{ needs.plan.outputs.target_repo_owner }} | |
| repositories: ${{ needs.plan.outputs.target_repo_name }} | |
| permission-actions: read | |
| permission-contents: read | |
| permission-issues: read | |
| permission-pull-requests: read | |
| - name: Create state token | |
| id: state-token | |
| uses: ./clawsweeper/.github/actions/create-state-token | |
| with: | |
| client-id: ${{ env.CLAWSWEEPER_APP_CLIENT_ID }} | |
| private-key: ${{ secrets.CLAWSWEEPER_APP_PRIVATE_KEY }} | |
| - uses: ./clawsweeper/.github/actions/setup-state | |
| with: | |
| token: ${{ steps.state-token.outputs.token }} | |
| worktree-path: clawsweeper | |
| fetch-depth: 1 | |
| - uses: ./clawsweeper/.github/actions/setup-pnpm | |
| with: | |
| working-directory: clawsweeper | |
| build-script: build | |
| - uses: ./clawsweeper/.github/actions/setup-codex | |
| env: | |
| OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} | |
| with: | |
| login-status: "true" | |
| - name: Check out target main | |
| env: | |
| TARGET_REPO: ${{ needs.plan.outputs.target_repo }} | |
| TARGET_NAME: ${{ needs.plan.outputs.target_checkout_dir }} | |
| TARGET_TOKEN: ${{ steps.target-read-token.outputs.token }} | |
| COMMIT_SHA: ${{ matrix.sha }} | |
| run: | | |
| set -euo pipefail | |
| url="https://x-access-token:${TARGET_TOKEN}@github.com/${TARGET_REPO}.git" | |
| git clone --filter=blob:none --no-checkout "$url" "$TARGET_NAME" | |
| git -C "$TARGET_NAME" fetch --no-tags origin main --depth=1000 | |
| git -C "$TARGET_NAME" checkout -B main refs/remotes/origin/main | |
| git -C "$TARGET_NAME" fetch --no-tags origin "$COMMIT_SHA" --depth=200 | |
| if ! git -C "$TARGET_NAME" merge-base --is-ancestor "$COMMIT_SHA" HEAD; then | |
| echo "Commit $COMMIT_SHA is not reachable from the checked-out origin/main history." >&2 | |
| exit 1 | |
| fi | |
| if ! git -C "$TARGET_NAME" rev-parse --verify "$COMMIT_SHA^" >/dev/null 2>&1; then | |
| git -C "$TARGET_NAME" fetch --deepen=500 origin main || true | |
| fi | |
| echo "Target main head: $(git -C "$TARGET_NAME" rev-parse --short HEAD)" | |
| echo "Commit under review: $(git -C "$TARGET_NAME" rev-parse --short "$COMMIT_SHA")" | |
| - name: Review commit | |
| working-directory: clawsweeper | |
| env: | |
| GH_TOKEN: ${{ steps.target-read-token.outputs.token }} | |
| COMMIT_SWEEPER_TARGET_GH_TOKEN: ${{ steps.target-read-token.outputs.token }} | |
| COMMIT_SWEEPER_ADDITIONAL_PROMPT: ${{ github.event.inputs.additional_prompt || github.event.client_payload.additional_prompt || '' }} | |
| run: | | |
| node dist/commit-sweeper.js review \ | |
| --target-repo "${{ needs.plan.outputs.target_repo }}" \ | |
| --target-dir "../${{ needs.plan.outputs.target_checkout_dir }}" \ | |
| --commit-sha "${{ matrix.sha }}" \ | |
| --report-dir ../commit-artifacts \ | |
| --artifact-mode \ | |
| --work-dir ../commit-work \ | |
| --codex-model gpt-5.5 \ | |
| --codex-reasoning-effort high \ | |
| --codex-sandbox danger-full-access \ | |
| --codex-timeout-ms 1800000 | |
| - name: Create target checks token | |
| id: target-checks-token | |
| if: ${{ needs.plan.outputs.create_checks == 'true' }} | |
| uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1 | |
| with: | |
| client-id: ${{ env.CLAWSWEEPER_APP_CLIENT_ID }} | |
| private-key: ${{ secrets.CLAWSWEEPER_APP_PRIVATE_KEY }} | |
| owner: ${{ needs.plan.outputs.target_repo_owner }} | |
| repositories: ${{ needs.plan.outputs.target_repo_name }} | |
| permission-checks: write | |
| - name: Publish commit check | |
| if: ${{ needs.plan.outputs.create_checks == 'true' }} | |
| working-directory: clawsweeper | |
| env: | |
| GH_TOKEN: ${{ steps.target-checks-token.outputs.token }} | |
| run: | | |
| set -euo pipefail | |
| test -n "$GH_TOKEN" | |
| report_path="$(find ../commit-artifacts -name '${{ matrix.sha }}.md' -print -quit)" | |
| if [ -z "$report_path" ]; then | |
| echo "Missing report artifact for ${{ matrix.sha }}" >&2 | |
| exit 1 | |
| fi | |
| relative_path="records/${report_path#../commit-artifacts/}" | |
| node dist/commit-sweeper.js publish-check \ | |
| --target-repo "${{ needs.plan.outputs.target_repo }}" \ | |
| --commit-sha "${{ matrix.sha }}" \ | |
| --report-path "$report_path" \ | |
| --report-relative-path "$relative_path" \ | |
| --report-repo "${{ github.repository }}" | |
| - uses: actions/upload-artifact@v7 | |
| if: always() | |
| with: | |
| name: commit-review-${{ matrix.sha }} | |
| path: commit-artifacts | |
| if-no-files-found: ignore | |
| publish: | |
| name: Commit reports | |
| needs: [plan, review] | |
| if: ${{ always() && (needs.plan.outputs.planned_count != '0' || needs.plan.outputs.skipped_count != '0') }} | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| filter: blob:none | |
| fetch-depth: 0 | |
| - name: Create state token | |
| id: state-token | |
| uses: ./.github/actions/create-state-token | |
| with: | |
| client-id: ${{ env.CLAWSWEEPER_APP_CLIENT_ID }} | |
| private-key: ${{ secrets.CLAWSWEEPER_APP_PRIVATE_KEY }} | |
| - uses: ./.github/actions/setup-state | |
| with: | |
| token: ${{ steps.state-token.outputs.token }} | |
| - uses: ./.github/actions/setup-pnpm | |
| with: | |
| build-script: build:all | |
| - uses: actions/download-artifact@v8 | |
| if: ${{ needs.plan.outputs.planned_count != '0' }} | |
| with: | |
| pattern: commit-review-* | |
| path: commit-artifacts | |
| merge-multiple: true | |
| - uses: actions/download-artifact@v8 | |
| if: ${{ needs.plan.outputs.skipped_count != '0' }} | |
| with: | |
| name: skipped-commit-reports | |
| path: commit-artifacts | |
| - name: Commit reports | |
| run: | | |
| set -euo pipefail | |
| git pull --rebase | |
| node dist/commit-sweeper.js copy-artifacts --artifact-dir commit-artifacts --records-dir records | |
| pnpm run repair:publish-main -- \ | |
| --message "chore: update commit review reports" \ | |
| --path records \ | |
| --rebase-strategy theirs | |
| - name: Create repair dispatch token | |
| id: clawsweeper-token | |
| if: ${{ vars.CLAWSWEEPER_COMMIT_FINDINGS_ENABLED != 'false' }} | |
| uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1 | |
| with: | |
| client-id: ${{ env.CLAWSWEEPER_APP_CLIENT_ID }} | |
| private-key: ${{ secrets.CLAWSWEEPER_APP_PRIVATE_KEY }} | |
| owner: openclaw | |
| repositories: clawsweeper | |
| permission-actions: write | |
| permission-contents: write | |
| - name: Dispatch commit findings to repair lane | |
| if: ${{ vars.CLAWSWEEPER_COMMIT_FINDINGS_ENABLED != 'false' }} | |
| env: | |
| GH_TOKEN: ${{ steps.clawsweeper-token.outputs.token }} | |
| ENABLED: ${{ vars.CLAWSWEEPER_COMMIT_FINDINGS_ENABLED || 'true' }} | |
| run: | | |
| set -euo pipefail | |
| node dist/commit-sweeper.js dispatch-findings \ | |
| --artifact-dir commit-artifacts \ | |
| --repair-repo openclaw/clawsweeper \ | |
| --repair-workflow repair-commit-finding-intake.yml \ | |
| --dispatch-mode workflow_dispatch \ | |
| --report-repo "${{ github.repository }}" \ | |
| --enabled "$ENABLED" | |
| - name: Create target checks token | |
| id: target-checks-token | |
| if: ${{ needs.plan.outputs.create_checks == 'true' }} | |
| uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1 | |
| with: | |
| client-id: ${{ env.CLAWSWEEPER_APP_CLIENT_ID }} | |
| private-key: ${{ secrets.CLAWSWEEPER_APP_PRIVATE_KEY }} | |
| owner: ${{ needs.plan.outputs.target_repo_owner }} | |
| repositories: ${{ needs.plan.outputs.target_repo_name }} | |
| permission-checks: write | |
| - name: Publish commit checks | |
| if: ${{ needs.plan.outputs.create_checks == 'true' }} | |
| env: | |
| GH_TOKEN: ${{ steps.target-checks-token.outputs.token }} | |
| run: | | |
| set -euo pipefail | |
| test -n "$GH_TOKEN" | |
| find commit-artifacts -name '*.md' -print0 | while IFS= read -r -d '' report_path; do | |
| sha="$(basename "$report_path" .md)" | |
| relative_path="records/${report_path#commit-artifacts/}" | |
| node dist/commit-sweeper.js publish-check \ | |
| --target-repo "${{ needs.plan.outputs.target_repo }}" \ | |
| --commit-sha "$sha" \ | |
| --report-path "$report_path" \ | |
| --report-relative-path "$relative_path" \ | |
| --report-repo "${{ github.repository }}" | |
| done | |
| - name: Continue commit review range | |
| if: ${{ success() && needs.plan.outputs.has_more == 'true' }} | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| TARGET_REPO: ${{ needs.plan.outputs.target_repo }} | |
| BEFORE_SHA: ${{ github.event.inputs.before_sha || github.event.client_payload.before_sha || '' }} | |
| AFTER_SHA: ${{ github.event.inputs.commit_sha || github.event.client_payload.after_sha || github.event.client_payload.commit_sha || '' }} | |
| NEXT_OFFSET: ${{ needs.plan.outputs.next_offset }} | |
| CREATE_CHECKS: ${{ needs.plan.outputs.create_checks }} | |
| ADDITIONAL_PROMPT: ${{ github.event.inputs.additional_prompt || github.event.client_payload.additional_prompt || '' }} | |
| run: | | |
| set -euo pipefail | |
| payload="$(jq -nc \ | |
| --arg target_repo "$TARGET_REPO" \ | |
| --arg before_sha "$BEFORE_SHA" \ | |
| --arg after_sha "$AFTER_SHA" \ | |
| --arg ref "refs/heads/main" \ | |
| --arg additional_prompt "$ADDITIONAL_PROMPT" \ | |
| --argjson commit_offset "$NEXT_OFFSET" \ | |
| --argjson create_checks "$CREATE_CHECKS" \ | |
| '{event_type:"clawsweeper_commit_review",client_payload:{target_repo:$target_repo,before_sha:$before_sha,after_sha:$after_sha,ref:$ref,commit_offset:$commit_offset,enabled:true,create_checks:$create_checks,additional_prompt:$additional_prompt}}')" | |
| gh api repos/${{ github.repository }}/dispatches \ | |
| --method POST \ | |
| --input - <<< "$payload" |