Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 38 additions & 33 deletions .github/workflows/e2e-advisor.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,18 @@ on:
required: false
type: string
default: main
run_pi:
description: Run Pi semantic analysis
run_analysis:
description: Run E2E recommendation analysis
required: false
type: boolean
default: true
pi_provider:
description: Pi provider name for PI_E2E_ADVISOR_API_KEY
provider:
description: Provider name for the advisor API key
required: false
type: string
default: anthropic
pi_model:
description: Optional Pi model pattern, for example aws/anthropic/bedrock-claude-opus-4-7 or openai/openai/gpt-5.5
model:
description: Optional model pattern, for example aws/anthropic/bedrock-claude-opus-4-7 or openai/openai/gpt-5.5
required: false
type: string
default: ""
Expand All @@ -69,29 +69,29 @@ concurrency:

jobs:
advise:
name: Pi semantic E2E recommendation
name: E2E recommendation
if: ${{ github.repository == 'NVIDIA/NemoClaw' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'NVIDIA/NemoClaw') }}
runs-on: ubuntu-latest
timeout-minutes: 20
env:
# Pin the Pi coding agent to a known-good version. Updates should go through
# Pin the Pi SDK to a known-good version. Updates should go through
# the normal dependency-review path (e.g. Dependabot) so a compromised
# upstream release cannot execute automatically in this secret-bearing job.
PI_AGENT_VERSION: "0.73.1"
# Keep Pi's own timeout shorter than the GitHub job timeout so the
PI_SDK_VERSION: "0.74.0"
# Keep the advisor timeout shorter than the GitHub job timeout so the
# analyzer can write failure artifacts, summaries, and PR comments.
PI_E2E_ADVISOR_TIMEOUT_MS: "900000"
PI_E2E_ADVISOR_HEARTBEAT_MS: "60000"
E2E_ADVISOR_TIMEOUT_MS: "900000"
E2E_ADVISOR_HEARTBEAT_MS: "60000"
# Cap automatic fan-out from noisy/flaky advisor recommendations until
# the dispatcher has enough production history to justify a higher limit.
E2E_ADVISOR_AUTO_DISPATCH_MAX_JOBS: "6"
# The trusted checkout always lives at this path and is the only source
# of code executed in this job. The PR content, if any, is mounted as
# read-only analysis data under PR_WORKDIR.
# of advisor implementation code executed in this job. The PR content,
# if any, is mounted as read-only analysis data under PR_WORKDIR.
ADVISOR_DIR: ${{ github.workspace }}/advisor
steps:
# Trusted-code boundary: the advisor implementation (pi-analyze.mjs,
# dispatch.mts, comment.mts, schema.json, pi-models.template.json) is always fetched
# Trusted-code boundary: the advisor implementation (analyze.mts,
# dispatch.mts, comment.mts, schema.json, models.template.json) is always fetched
# from the main branch of this repo, regardless of what the PR changed.
# This prevents a future PR from modifying advisor code and executing
# arbitrary Node in a job that holds API keys and a write-scoped token.
Expand Down Expand Up @@ -153,31 +153,36 @@ jobs:
git -C "$TARGET_DIR" checkout --detach "refs/remotes/target/pr-${TARGET_PR}"
echo "ADVISOR_WORKDIR=$TARGET_DIR" >> "$GITHUB_ENV"

# Pinned install. The version is held in PI_AGENT_VERSION above so
# Pinned SDK install. The version is held in PI_SDK_VERSION above so
# the pin is reviewed as a code change, not silently inherited from
# whatever @latest points to at runtime.
- name: Install Pi
run: npm install -g "@mariozechner/pi-coding-agent@${PI_AGENT_VERSION}"
# whatever @latest points to at runtime. Install into an isolated temp
# prefix, then expose that dependency tree to the trusted advisor script.
- name: Install Pi SDK
run: |
PI_SDK_DIR="$RUNNER_TEMP/pi-sdk"
npm install --prefix "$PI_SDK_DIR" --ignore-scripts --no-save --package-lock=false "@earendil-works/pi-coding-agent@${PI_SDK_VERSION}"
rm -rf "$ADVISOR_DIR/node_modules"
ln -s "$PI_SDK_DIR/node_modules" "$ADVISOR_DIR/node_modules"

- name: Run Pi semantic E2E advisor
id: pi-analysis
- name: Run E2E recommendation advisor
id: analysis
continue-on-error: true
env:
BASE_REF: ${{ github.event_name == 'pull_request' && format('origin/{0}', github.base_ref) || (github.event_name == 'workflow_dispatch' && inputs.target_repo != '' && inputs.target_pr != '' && format('target/{0}', inputs.target_base) || inputs.base_ref) }}
HEAD_REF: ${{ github.event_name == 'pull_request' && 'HEAD' || (github.event_name == 'workflow_dispatch' && inputs.target_repo != '' && inputs.target_pr != '' && 'HEAD' || inputs.head_ref) }}
PI_E2E_ADVISOR_RUN_PI: ${{ github.event_name == 'workflow_dispatch' && inputs.run_pi == false && '0' || '1' }}
PI_E2E_ADVISOR_PROVIDER: ${{ github.event_name == 'workflow_dispatch' && inputs.pi_provider || 'anthropic' }}
PI_E2E_ADVISOR_MODEL: ${{ github.event_name == 'workflow_dispatch' && inputs.pi_model || '' }}
E2E_ADVISOR_RUN_ANALYSIS: ${{ github.event_name == 'workflow_dispatch' && inputs.run_analysis == false && '0' || '1' }}
E2E_ADVISOR_PROVIDER: ${{ github.event_name == 'workflow_dispatch' && inputs.provider || 'anthropic' }}
E2E_ADVISOR_MODEL: ${{ github.event_name == 'workflow_dispatch' && inputs.model || '' }}
# Preferred E2E advisor secret. The script maps this generic key to the selected provider's
# expected env var before invoking pi, matching how local pi can be run with --api-key.
PI_E2E_ADVISOR_API_KEY: ${{ secrets.PI_E2E_ADVISOR_API_KEY }}
# Also support standard Pi provider env vars for future upstream/external-advisor use.
# expected env var before creating the SDK session.
E2E_ADVISOR_API_KEY: ${{ secrets.PI_E2E_ADVISOR_API_KEY }}
# Also support standard provider env vars for future upstream/external-advisor use.
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
run: |
cd "$ADVISOR_WORKDIR"
node "$ADVISOR_DIR/tools/e2e-advisor/pi-analyze.mjs" \
node --experimental-strip-types "$ADVISOR_DIR/tools/e2e-advisor/analyze.mts" \
--base "$BASE_REF" \
--head "$HEAD_REF" \
--schema "$ADVISOR_DIR/tools/e2e-advisor/schema.json" \
Expand All @@ -186,10 +191,10 @@ jobs:
- name: Publish job summary
if: always()
run: |
if [ -f "$GITHUB_WORKSPACE/artifacts/e2e-advisor/e2e-advisor-pi-summary.md" ]; then
cat "$GITHUB_WORKSPACE/artifacts/e2e-advisor/e2e-advisor-pi-summary.md" >> "$GITHUB_STEP_SUMMARY"
if [ -f "$GITHUB_WORKSPACE/artifacts/e2e-advisor/e2e-advisor-summary.md" ]; then
cat "$GITHUB_WORKSPACE/artifacts/e2e-advisor/e2e-advisor-summary.md" >> "$GITHUB_STEP_SUMMARY"
else
printf '# Pi Semantic E2E Advisor\n\nPi analysis did not produce a summary. See raw artifacts/logs.\n' >> "$GITHUB_STEP_SUMMARY"
printf '# E2E Recommendation Advisor\n\nAdvisor analysis did not produce a summary. See raw artifacts/logs.\n' >> "$GITHUB_STEP_SUMMARY"
fi

- name: Auto-dispatch required E2E jobs
Expand Down Expand Up @@ -229,7 +234,7 @@ jobs:
COMMENT_ARGS=(
--repo "$GITHUB_REPOSITORY"
--pr "$PR_NUMBER"
--summary "$GITHUB_WORKSPACE/artifacts/e2e-advisor/e2e-advisor-pi-summary.md"
--summary "$GITHUB_WORKSPACE/artifacts/e2e-advisor/e2e-advisor-summary.md"
--result "$GITHUB_WORKSPACE/artifacts/e2e-advisor/e2e-advisor-final-result.json"
--dispatch "$GITHUB_WORKSPACE/artifacts/e2e-advisor/e2e-advisor-dispatch-result.json"
)
Expand Down
Loading
Loading