mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-02 13:11:38 +00:00
* feat(ci): weekly Codex sweep for date-carrying to-dos Mondays 06:23 UTC (plus default-branch-only manual dispatch with dry_run): a deterministic prefilter collects candidate lines where to-do markers co-occur with date tokens, plus every deprecated compat record from the plugin registry; a pinned openai/codex-action step judges each candidate in context (genuine dated commitment vs historical date or fixture) and writes an OVERDUE / DUE-30-days / FUTURE report; a separate privileged job validates the report (tracked file:line locations, date shape, inert text) and upserts one marker-tagged tracking issue via the Barnacle app token, commenting only when items newly become due. The app token is minted on a fresh runner and checkout — never beside Codex or its child processes; only the validated report artifact crosses jobs. No permission-* subsets on token minting (installations reject explicit subsets; see pr-ci-sweeper). * chore(ci): localize upsert helpers with no external consumers
157 lines
5.7 KiB
YAML
157 lines
5.7 KiB
YAML
name: Dated TODO sweep
|
|
|
|
on:
|
|
schedule:
|
|
- cron: "23 6 * * 1"
|
|
workflow_dispatch:
|
|
inputs:
|
|
dry_run:
|
|
description: Log the fresh report without creating or updating the tracking issue.
|
|
required: false
|
|
default: false
|
|
type: boolean
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
concurrency:
|
|
group: dated-todo-sweep
|
|
cancel-in-progress: false
|
|
|
|
env:
|
|
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
|
|
|
jobs:
|
|
analyze:
|
|
# Manual runs may select a ref; secrets are available only when that ref is
|
|
# the trusted default branch. Scheduled runs already target that branch.
|
|
if: github.event_name != 'workflow_dispatch' || github.ref == format('refs/heads/{0}', github.event.repository.default_branch)
|
|
outputs:
|
|
sweep-date: ${{ steps.sweep-date.outputs.date }}
|
|
runs-on: ubuntu-24.04
|
|
timeout-minutes: 20
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
|
with:
|
|
ref: ${{ github.sha }}
|
|
persist-credentials: false
|
|
|
|
- name: Setup Node environment
|
|
uses: ./.github/actions/setup-node-env
|
|
with:
|
|
node-version: "24.x"
|
|
install-bun: "false"
|
|
|
|
- name: Collect dated TODO candidates
|
|
run: node scripts/dated-todo-scan.mjs
|
|
|
|
- name: Capture sweep date
|
|
id: sweep-date
|
|
run: echo "date=$(date -u +%F)" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Run Codex dated TODO sweep
|
|
uses: openai/codex-action@52fe01ec70a42f454c9d2ebd47598f9fd6893d56
|
|
env:
|
|
DATED_TODO_SWEEP_DATE: ${{ steps.sweep-date.outputs.date }}
|
|
with:
|
|
openai-api-key: ${{ secrets.OPENAI_API_KEY }}
|
|
prompt-file: .github/codex/prompts/dated-todo-sweep.md
|
|
model: ${{ vars.OPENCLAW_CI_OPENAI_MODEL_BARE }}
|
|
effort: medium
|
|
sandbox: workspace-write
|
|
safety-strategy: drop-sudo
|
|
|
|
# Only the report crosses into the privileged job. The app token is minted
|
|
# on a fresh runner and checkout, never beside Codex or its child processes.
|
|
- name: Upload dated TODO report
|
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
with:
|
|
name: dated-todo-report
|
|
path: .artifacts/dated-todo-report.md
|
|
if-no-files-found: error
|
|
include-hidden-files: true
|
|
retention-days: 7
|
|
|
|
upsert:
|
|
if: github.event_name != 'workflow_dispatch' || github.ref == format('refs/heads/{0}', github.event.repository.default_branch)
|
|
needs: analyze
|
|
runs-on: ubuntu-24.04
|
|
timeout-minutes: 10
|
|
steps:
|
|
- name: Checkout trusted workflow code
|
|
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
|
with:
|
|
ref: ${{ github.sha }}
|
|
persist-credentials: false
|
|
|
|
- name: Download dated TODO report
|
|
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
|
|
with:
|
|
name: dated-todo-report
|
|
path: .artifacts
|
|
|
|
- name: Validate dated TODO report
|
|
env:
|
|
DATED_TODO_SWEEP_DATE: ${{ needs.analyze.outputs.sweep-date }}
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
node --input-type=module <<'NODE'
|
|
import fs from "node:fs";
|
|
import { pathToFileURL } from "node:url";
|
|
|
|
const reportPath = ".artifacts/dated-todo-report.md";
|
|
const report = fs.readFileSync(reportPath, "utf8");
|
|
const moduleUrl = pathToFileURL(
|
|
`${process.env.GITHUB_WORKSPACE}/scripts/github/dated-todo-upsert.mjs`,
|
|
);
|
|
const { validateDatedTodoReport } = await import(moduleUrl.href);
|
|
validateDatedTodoReport(report, {
|
|
expectedDate: process.env.DATED_TODO_SWEEP_DATE,
|
|
repoRoot: process.env.GITHUB_WORKSPACE,
|
|
});
|
|
NODE
|
|
|
|
- name: Log dry-run report
|
|
if: github.event_name == 'workflow_dispatch' && inputs.dry_run
|
|
run: cat .artifacts/dated-todo-report.md
|
|
|
|
# No permission-* subset here: requesting a permission the installation
|
|
# does not grant fails token minting outright. No inputs uses the app's
|
|
# full granted set, matching the proven Barnacle fallback workflow.
|
|
- name: Create Barnacle app token
|
|
if: github.event_name != 'workflow_dispatch' || !inputs.dry_run
|
|
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # zizmor: ignore[github-app] v3
|
|
id: app-token
|
|
continue-on-error: true
|
|
with:
|
|
app-id: "2729701"
|
|
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
|
|
|
|
- name: Create fallback Barnacle app token
|
|
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # zizmor: ignore[github-app] v3
|
|
id: app-token-fallback
|
|
if: (github.event_name != 'workflow_dispatch' || !inputs.dry_run) && steps.app-token.outcome == 'failure'
|
|
with:
|
|
app-id: "2971289"
|
|
private-key: ${{ secrets.GH_APP_PRIVATE_KEY_FALLBACK }}
|
|
|
|
- name: Upsert dated TODO tracking issue
|
|
if: github.event_name != 'workflow_dispatch' || !inputs.dry_run
|
|
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
|
|
with:
|
|
github-token: ${{ steps.app-token.outputs.token || steps.app-token-fallback.outputs.token }}
|
|
script: |
|
|
const { pathToFileURL } = require("node:url");
|
|
const moduleUrl = pathToFileURL(
|
|
`${process.env.GITHUB_WORKSPACE}/scripts/github/dated-todo-upsert.mjs`,
|
|
);
|
|
const { runDatedTodoUpsert } = await import(moduleUrl.href);
|
|
|
|
await runDatedTodoUpsert({
|
|
github,
|
|
context,
|
|
core,
|
|
});
|