Skip to content

feat(ci): polish nightly scorecard Slack rendering#4783

Merged
cv merged 19 commits into
mainfrom
feat/update-slack-report-message
Jun 5, 2026
Merged

feat(ci): polish nightly scorecard Slack rendering#4783
cv merged 19 commits into
mainfrom
feat/update-slack-report-message

Conversation

@hunglp6d

@hunglp6d hunglp6d commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Summary

Polish the nightly E2E scorecard Slack message: rename routing secrets, inject mode + actor into the title and run-mode line, and switch failed-job names + counts to the GitHub Actions API for reliable hyperlinks and accurate listings on re-runs.

Related Issue

(none — incremental polish on top of #4308)

Changes

  • Rename Slack channel tags + secrets to event-type names (SITUATION_ROOM / CIDAILY / FULLRUN) (due to just pushing notification to a unified channel as requirement)
  • Append (by *<actor>*) to the run-mode line for Manual full run / Selective dispatch. Schedule runs skip it (actor reflects file committer, not trigger).
  • Inject mode + actor into the title (top-level fallback text).
  • Use listJobsForWorkflowRun (paginated) as source of truth for failed jobs and counts. Strips / <suffix> so reusable-workflow names match caller IDs and hyperlinks render. Last-write-wins dedup so re-runs reflect final conclusion. Falls back to needs context on API failure.

Type of Change

  • Code change (feature, bug fix, or refactor)
  • Code change with doc updates
  • Doc only (prose changes, no code sample modifications)
  • Doc only (includes code sample changes)

Verification

  • npx prek run --all-files passes
  • npm test passes
  • Tests added or updated for new or changed behavior
  • No secrets, API keys, or credentials committed
  • Docs updated for user-facing behavior changes
  • npm run docs builds without warnings (doc changes only)
  • Doc pages follow the style guide (doc changes only)
  • New doc pages include SPDX header and frontmatter (new pages only)

Signed-off-by: Hung Le hple@nvidia.com

Summary by CodeRabbit

  • Chores

    • Improved nightly scorecard reliability by deriving a canonical job set (with API-based fallback) and improving failed-job reporting; scorecard output now includes the workflow actor.
    • Reorganized Slack routing to use separate webhooks for daily vs full runs while preserving preview gating.
  • New Features

    • Slack notifications can show the workflow initiator for clearer run context; fallback titles are richer.
  • Tests

    • Updated tests for new routing and actor-suffix behavior.

@copy-pr-bot

copy-pr-bot Bot commented Jun 4, 2026

Copy link
Copy Markdown

Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

@coderabbitai

coderabbitai Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Linter diff in the way? Review this PR in Change Stack to focus on meaningful changes and expand context only when needed.

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The nightly E2E scorecard now derives job status from the Actions API (canonical job set with fallback), includes actor in exported scorecardData, and remaps Slack routing to daily/fullrun/preview while adding conditional actor attribution in messages.

Changes

Nightly E2E Scorecard Actor Attribution & Routing

Layer / File(s) Summary
Workflow scorecard data and API-backed job canonical set
.github/workflows/nightly-e2e.yaml, scripts/scorecard/build-slack-blocks.ts, test/scorecard-blocks.test.ts
Scorecard generation switches from needs-only to an API-backed canonical job set with deduplication and fallback; failedJobs list uses API metadata when available. scorecardData now includes actor and tests add default actor: "".
Slack channel routing refactor: ci/situation-room → daily/fullrun/preview
.github/workflows/nightly-e2e.yaml, scripts/scorecard/build-slack-blocks.ts, test/scorecard-blocks.test.ts
SlackChannel type and getSlackChannel mapping updated to `"daily"
Actor attribution in Slack message content
scripts/scorecard/build-slack-blocks.ts, test/scorecard-blocks.test.ts
buildBlocks and buildFallbackText conditionally append actor attribution for non-scheduled runs; fallback title uses runMode-driven emoji segments. Tests cover actor-present and actor-empty cases across run modes.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

Possibly related PRs

  • NVIDIA/NemoClaw#4308: Prior Slack/scorecard integration changes; this PR continues the Slack routing and scorecard payload work begun there.

Suggested labels

enhancement: integration, CI/CD, E2E, area: e2e

Suggested reviewers

  • jyaunches
  • cv

Poem

🐰 I hopped through jobs and fetched their state,
From GitHub's API I tallied fate.
Daily, fullrun, preview — routes anew,
Who hit dispatch now shows in view.
A rabbit nudges CI with a tiny carrot cue.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(ci): polish nightly scorecard Slack rendering' accurately summarizes the main change: refactoring Slack message routing and rendering for the nightly E2E scorecard. It directly reflects the primary objectives of renaming channel tags, updating Slack routing, and improving message content.
Docstring Coverage ✅ Passed Docstring coverage is 80.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/update-slack-report-message

Comment @coderabbitai help to get the list of available commands and usage tips.

@hunglp6d hunglp6d marked this pull request as ready for review June 4, 2026 21:53
@github-actions

github-actions Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

E2E Advisor Recommendation

Required E2E: None
Optional E2E: None

Workflow run

Full advisor summary

E2E Recommendation Advisor

Failed: Could not parse JSON from advisor output; see /home/runner/work/NemoClaw/NemoClaw/artifacts/e2e-advisor/e2e-advisor-raw-output.txt

@github-actions

github-actions Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

E2E Scenario Advisor Recommendation

Required scenario E2E: None
Optional scenario E2E: None

Workflow run

Full scenario advisor summary

E2E Scenario Advisor

Failed: Could not parse JSON from advisor output; see /home/runner/work/NemoClaw/NemoClaw/artifacts/e2e-advisor/e2e-scenario-advisor-raw-output.txt

@github-actions

github-actions Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor

Findings: 0 needs attention, 12 worth checking, 0 nice ideas
Since last review: 6 prior items resolved, 5 still apply, 2 new items found

Review findings

🛠️ Needs attention

  • None.

🔎 Worth checking

  • Source-of-truth review needed: .github/workflows/nightly-e2e.yaml canonical job source: The advisor marked localized patch analysis as needs_followup.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: The workflow documents `Source: listJobsForWorkflowRun (paginated)` and derives `canonicalJobs` from `github.paginate(...)`.
  • Source-of-truth review needed: .github/workflows/nightly-e2e.yaml API failure fallback: The advisor marked localized patch analysis as needs_followup.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: The catch block warns and leaves `canonicalJobs` null; later logic uses `entries` from `needs`.
  • Source-of-truth review needed: .github/workflows/nightly-e2e.yaml reusable-workflow suffix normalization: The advisor marked localized patch analysis as needs_followup.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: `const name = j.name.replace(/ \/ [^/]+$/, '')` strips a final reusable-workflow suffix.
  • Source-of-truth review needed: .github/workflows/nightly-e2e.yaml duplicate normalized job dedupe: The advisor marked localized patch analysis as needs_followup.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: Dedupe now compares `run_attempt` and `completed_at`, but equal or missing metadata still has no stable tie-breaker.
  • Source-of-truth review needed: .github/workflows/nightly-e2e.yaml unknown terminal conclusion handling: The advisor marked localized patch analysis as needs_followup.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: Counts use a catch-all `else failure++;`, but failed job listing still filters only exact `failure` conclusions.
  • Guard Slack webhook secrets from branch-controlled scorecard code (.github/workflows/nightly-e2e.yaml:2767): The Slack posting step injects live webhook secrets and then loads `scripts/scorecard/build-slack-blocks.ts` from the checked-out workspace. For workflow_dispatch runs on a non-default workflow ref, that means branch-controlled repo code can execute in the same process as the Slack webhook secrets. This PR changes the Slack secret routing boundary, and there is overlapping security work in PR ci(e2e): withhold live messaging secrets from target refs #4862 about withholding live messaging secrets from target refs.
    • Recommendation: Only expose Slack webhook secrets to trusted workflow refs, or pin the scorecard-builder checkout to a trusted default-branch SHA before loading it. Consider gating Slack posting on trusted refs and coordinating with the live-secret withholding work.
    • Evidence: The scorecard job checks out `scripts/scorecard` without an explicit trusted `ref`, then the Slack step sets `SLACK_WEBHOOK_URL_DAILY`, `SLACK_WEBHOOK_URL_FULLRUN`, and `SLACK_WEBHOOK_URL_PREVIEW` and calls `require(path.join(process.env.GITHUB_WORKSPACE, 'scripts/scorecard/build-slack-blocks.ts'))`.
  • Unknown terminal job conclusions are counted as failures but omitted from failed jobs (.github/workflows/nightly-e2e.yaml:2630): The count loop now correctly maps terminal non-success conclusions such as `timed_out`, `action_required`, `neutral`, `stale`, or future values to `failure`, but the failed job list still includes only exact `j.conclusion === 'failure'`. A timed-out job can therefore produce `❌ 1 failed` without a corresponding failed-job name or hyperlink.
    • Recommendation: Use the same terminal non-success classification for `failedJobs` that is used for counts, or add an explicit anomalous/failed jobs bucket that includes non-success completed conclusions with their URLs.
    • Evidence: Counts use a catch-all `else failure++;`, but `failedJobs` is built with `.filter((j) => j.conclusion === 'failure')`.
  • API-derived scorecard construction and fallback still lack runtime coverage (.github/workflows/nightly-e2e.yaml:2571): The highest-risk behavior now lives in inline GitHub Actions script: paginated `listJobsForWorkflowRun`, suffix normalization, duplicate dedupe, conclusion classification, URL preservation, and fallback to `needs`. The added tests exercise only the Slack block builder after `ScorecardData` has already been produced.
    • Recommendation: Extract the scorecard-data construction into a testable helper or add a workflow-script harness that covers the API success path, pagination, fallback branch, normalization, dedupe, non-standard conclusions, and failed-job URL preservation.
    • Evidence: The workflow calls `github.paginate(github.rest.actions.listJobsForWorkflowRun, ...)` and catches API errors by falling back to `entries`; `test/scorecard-blocks.test.ts` imports only `scripts/scorecard/build-slack-blocks.ts`.
  • Duplicate job dedupe still has an API-order tie case (.github/workflows/nightly-e2e.yaml:2586): The dedupe logic is much better than last-write-wins because it prefers higher `run_attempt` and later `completed_at`, but if those fields are equal or missing the selected duplicate still depends on the order returned by the Jobs API.
    • Recommendation: Add a stable final tie-breaker such as `started_at` and numeric job `id`, or sort the API jobs before deduping. Add a regression test that shuffles duplicate jobs and proves the same final attempt is selected.
    • Evidence: `isNewer` compares only `(j.run_attempt ?? 0)` and `(j.completed_at ?? '')`; no tie-breaker is applied when both compare equal.
  • Prior-day API error text is still rendered into summary and Slack (.github/workflows/nightly-e2e.yaml:2688): The Slack webhook and current-run Jobs API warnings were truncated, but the prior-day trend catch still embeds raw `e.message` in `trendLine`. That value is written to the GitHub summary and included in Slack data, so an external API diagnostic can leak operational details or break display formatting.
    • Recommendation: Sanitize and truncate the prior-day error just like the other external error paths, preferably logging only status and a short safe reason.
    • Evidence: `trendLine = `Trend: ⊘ Could not fetch prior-day data (${e.message})`;` is later placed in `scorecardData` and rendered by the Slack builder.
  • Slack webhook secret routing is not tested at the workflow boundary (.github/workflows/nightly-e2e.yaml:2794): Unit tests cover `getSlackChannel`, but they do not verify that the workflow maps the returned tag to the intended secret env var or that selective dispatches skip posting unless explicitly opted in.
    • Recommendation: Add a small extracted helper or workflow-script harness that verifies `daily -> SLACK_WEBHOOK_URL_DAILY`, `fullrun -> SLACK_WEBHOOK_URL_FULLRUN`, `preview -> SLACK_WEBHOOK_URL_PREVIEW`, and that preview returns before posting when `post_to_slack` is not true.
    • Evidence: The workflow defines `envByChannel = { daily: 'SLACK_WEBHOOK_URL_DAILY', fullrun: 'SLACK_WEBHOOK_URL_FULLRUN', preview: 'SLACK_WEBHOOK_URL_PREVIEW' }`; tests only assert `getSlackChannel(...)` return values.
  • Slack mrkdwn fields are assembled without escaping (scripts/scorecard/build-slack-blocks.ts:90): Actor, requested job names, failed job names, and failed job URLs are interpolated directly into Slack mrkdwn. Most current sources are GitHub-controlled or maintainer-dispatch-controlled, but the builder accepts arbitrary `ScorecardData`, and malformed values can alter Slack rendering or produce confusing links.
    • Recommendation: Add Slack mrkdwn escaping for text fields and validate/allowlist URLs before rendering `<url|text>` links. Cover actor, requested jobs, failed job names, and failed job URLs in tests.
    • Evidence: `runModeText` includes `*${data.actor}*`; requested jobs are wrapped in backticks; failed jobs render as `<${job.url}|${job.name}>` without escaping.

🌱 Nice ideas

  • None.
Consider writing more tests for
  • **Runtime validation** — Workflow scorecard data builder counts paginated `listJobsForWorkflowRun` results and preserves `html_url` in `failedJobs`.. The changed pure Slack builder has useful unit coverage, but the higher-risk behavior is inline workflow runtime code that talks to GitHub APIs, handles fallbacks, maps secrets, and posts to Slack.
  • **Runtime validation** — Workflow scorecard normalizes `cloud-e2e / run` to `cloud-e2e` before dedupe and failed-job rendering.. The changed pure Slack builder has useful unit coverage, but the higher-risk behavior is inline workflow runtime code that talks to GitHub APIs, handles fallbacks, maps secrets, and posts to Slack.
  • **Runtime validation** — Workflow scorecard selects duplicate normalized jobs by `run_attempt`, `completed_at`, and a stable tie-breaker independent of API page order.. The changed pure Slack builder has useful unit coverage, but the higher-risk behavior is inline workflow runtime code that talks to GitHub APIs, handles fallbacks, maps secrets, and posts to Slack.
  • **Runtime validation** — Workflow scorecard treats `timed_out`, `action_required`, `neutral`, and unknown completed conclusions as non-perfect and includes them in the failed/anomalous jobs list.. The changed pure Slack builder has useful unit coverage, but the higher-risk behavior is inline workflow runtime code that talks to GitHub APIs, handles fallbacks, maps secrets, and posts to Slack.
  • **Runtime validation** — Workflow scorecard falls back to `needs` counts and `failedJobs` entries with `url: null` when `listJobsForWorkflowRun` throws.. The changed pure Slack builder has useful unit coverage, but the higher-risk behavior is inline workflow runtime code that talks to GitHub APIs, handles fallbacks, maps secrets, and posts to Slack.
  • **API-derived scorecard construction and fallback still lack runtime coverage** — Extract the scorecard-data construction into a testable helper or add a workflow-script harness that covers the API success path, pagination, fallback branch, normalization, dedupe, non-standard conclusions, and failed-job URL preservation.
  • **Slack webhook secret routing is not tested at the workflow boundary** — Add a small extracted helper or workflow-script harness that verifies `daily -> SLACK_WEBHOOK_URL_DAILY`, `fullrun -> SLACK_WEBHOOK_URL_FULLRUN`, `preview -> SLACK_WEBHOOK_URL_PREVIEW`, and that preview returns before posting when `post_to_slack` is not true.
  • **Acceptance clause:** Rename Slack channel tags + secrets to event-type names (`SITUATION_ROOM` / `CI` → `DAILY` / `FULLRUN`) (due to just pushing notification to a unified channel as requirement) — add test evidence or identify existing coverage. `getSlackChannel` now returns `daily` and `fullrun`, workflow env vars use `SLACK_WEBHOOK_URL_DAILY` and `SLACK_WEBHOOK_URL_FULLRUN`, and tests cover helper return values. The workflow env-var mapping and preview skip gate are not covered by tests.
Since last review details

Current findings:

  • Source-of-truth review needed: .github/workflows/nightly-e2e.yaml canonical job source: The advisor marked localized patch analysis as needs_followup.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: The workflow documents `Source: listJobsForWorkflowRun (paginated)` and derives `canonicalJobs` from `github.paginate(...)`.
  • Source-of-truth review needed: .github/workflows/nightly-e2e.yaml API failure fallback: The advisor marked localized patch analysis as needs_followup.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: The catch block warns and leaves `canonicalJobs` null; later logic uses `entries` from `needs`.
  • Source-of-truth review needed: .github/workflows/nightly-e2e.yaml reusable-workflow suffix normalization: The advisor marked localized patch analysis as needs_followup.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: `const name = j.name.replace(/ \/ [^/]+$/, '')` strips a final reusable-workflow suffix.
  • Source-of-truth review needed: .github/workflows/nightly-e2e.yaml duplicate normalized job dedupe: The advisor marked localized patch analysis as needs_followup.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: Dedupe now compares `run_attempt` and `completed_at`, but equal or missing metadata still has no stable tie-breaker.
  • Source-of-truth review needed: .github/workflows/nightly-e2e.yaml unknown terminal conclusion handling: The advisor marked localized patch analysis as needs_followup.
    • Recommendation: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
    • Evidence: Counts use a catch-all `else failure++;`, but failed job listing still filters only exact `failure` conclusions.
  • Guard Slack webhook secrets from branch-controlled scorecard code (.github/workflows/nightly-e2e.yaml:2767): The Slack posting step injects live webhook secrets and then loads `scripts/scorecard/build-slack-blocks.ts` from the checked-out workspace. For workflow_dispatch runs on a non-default workflow ref, that means branch-controlled repo code can execute in the same process as the Slack webhook secrets. This PR changes the Slack secret routing boundary, and there is overlapping security work in PR ci(e2e): withhold live messaging secrets from target refs #4862 about withholding live messaging secrets from target refs.
    • Recommendation: Only expose Slack webhook secrets to trusted workflow refs, or pin the scorecard-builder checkout to a trusted default-branch SHA before loading it. Consider gating Slack posting on trusted refs and coordinating with the live-secret withholding work.
    • Evidence: The scorecard job checks out `scripts/scorecard` without an explicit trusted `ref`, then the Slack step sets `SLACK_WEBHOOK_URL_DAILY`, `SLACK_WEBHOOK_URL_FULLRUN`, and `SLACK_WEBHOOK_URL_PREVIEW` and calls `require(path.join(process.env.GITHUB_WORKSPACE, 'scripts/scorecard/build-slack-blocks.ts'))`.
  • Unknown terminal job conclusions are counted as failures but omitted from failed jobs (.github/workflows/nightly-e2e.yaml:2630): The count loop now correctly maps terminal non-success conclusions such as `timed_out`, `action_required`, `neutral`, `stale`, or future values to `failure`, but the failed job list still includes only exact `j.conclusion === 'failure'`. A timed-out job can therefore produce `❌ 1 failed` without a corresponding failed-job name or hyperlink.
    • Recommendation: Use the same terminal non-success classification for `failedJobs` that is used for counts, or add an explicit anomalous/failed jobs bucket that includes non-success completed conclusions with their URLs.
    • Evidence: Counts use a catch-all `else failure++;`, but `failedJobs` is built with `.filter((j) => j.conclusion === 'failure')`.
  • API-derived scorecard construction and fallback still lack runtime coverage (.github/workflows/nightly-e2e.yaml:2571): The highest-risk behavior now lives in inline GitHub Actions script: paginated `listJobsForWorkflowRun`, suffix normalization, duplicate dedupe, conclusion classification, URL preservation, and fallback to `needs`. The added tests exercise only the Slack block builder after `ScorecardData` has already been produced.
    • Recommendation: Extract the scorecard-data construction into a testable helper or add a workflow-script harness that covers the API success path, pagination, fallback branch, normalization, dedupe, non-standard conclusions, and failed-job URL preservation.
    • Evidence: The workflow calls `github.paginate(github.rest.actions.listJobsForWorkflowRun, ...)` and catches API errors by falling back to `entries`; `test/scorecard-blocks.test.ts` imports only `scripts/scorecard/build-slack-blocks.ts`.
  • Duplicate job dedupe still has an API-order tie case (.github/workflows/nightly-e2e.yaml:2586): The dedupe logic is much better than last-write-wins because it prefers higher `run_attempt` and later `completed_at`, but if those fields are equal or missing the selected duplicate still depends on the order returned by the Jobs API.
    • Recommendation: Add a stable final tie-breaker such as `started_at` and numeric job `id`, or sort the API jobs before deduping. Add a regression test that shuffles duplicate jobs and proves the same final attempt is selected.
    • Evidence: `isNewer` compares only `(j.run_attempt ?? 0)` and `(j.completed_at ?? '')`; no tie-breaker is applied when both compare equal.
  • Prior-day API error text is still rendered into summary and Slack (.github/workflows/nightly-e2e.yaml:2688): The Slack webhook and current-run Jobs API warnings were truncated, but the prior-day trend catch still embeds raw `e.message` in `trendLine`. That value is written to the GitHub summary and included in Slack data, so an external API diagnostic can leak operational details or break display formatting.
    • Recommendation: Sanitize and truncate the prior-day error just like the other external error paths, preferably logging only status and a short safe reason.
    • Evidence: `trendLine = `Trend: ⊘ Could not fetch prior-day data (${e.message})`;` is later placed in `scorecardData` and rendered by the Slack builder.
  • Slack webhook secret routing is not tested at the workflow boundary (.github/workflows/nightly-e2e.yaml:2794): Unit tests cover `getSlackChannel`, but they do not verify that the workflow maps the returned tag to the intended secret env var or that selective dispatches skip posting unless explicitly opted in.
    • Recommendation: Add a small extracted helper or workflow-script harness that verifies `daily -> SLACK_WEBHOOK_URL_DAILY`, `fullrun -> SLACK_WEBHOOK_URL_FULLRUN`, `preview -> SLACK_WEBHOOK_URL_PREVIEW`, and that preview returns before posting when `post_to_slack` is not true.
    • Evidence: The workflow defines `envByChannel = { daily: 'SLACK_WEBHOOK_URL_DAILY', fullrun: 'SLACK_WEBHOOK_URL_FULLRUN', preview: 'SLACK_WEBHOOK_URL_PREVIEW' }`; tests only assert `getSlackChannel(...)` return values.
  • Slack mrkdwn fields are assembled without escaping (scripts/scorecard/build-slack-blocks.ts:90): Actor, requested job names, failed job names, and failed job URLs are interpolated directly into Slack mrkdwn. Most current sources are GitHub-controlled or maintainer-dispatch-controlled, but the builder accepts arbitrary `ScorecardData`, and malformed values can alter Slack rendering or produce confusing links.
    • Recommendation: Add Slack mrkdwn escaping for text fields and validate/allowlist URLs before rendering `<url|text>` links. Cover actor, requested jobs, failed job names, and failed job URLs in tests.
    • Evidence: `runModeText` includes `*${data.actor}*`; requested jobs are wrapped in backticks; failed jobs render as `<${job.url}|${job.name}>` without escaping.

Workflow run details

This is an automated advisory review. A human maintainer must make the final merge decision.

@hunglp6d hunglp6d self-assigned this Jun 5, 2026
@hunglp6d hunglp6d added VRDC Issues and PRs submitted by NVIDIA VRDC test team. v0.0.60 Release target area: ci CI workflows, checks, release automation, or GitHub Actions labels Jun 5, 2026
@hunglp6d

hunglp6d commented Jun 5, 2026

Copy link
Copy Markdown
Contributor Author

Addressed advisor findings (commits on this PR):

  • BtoJSON()-wrap inputs.jobs to safely embed dispatch input as a JS literal.
  • C1 — catch-all bucket: count unknown completed conclusions (timed_out, action_required, etc.) as failure so perfect stays false on anomalies.
  • C2 — dedupe by run_attempt (then completed_at) instead of API page order.
  • D1 — expanded the canonical-job-set comment into a contract block (source, why needs is insufficient, authoritative fields, fallback semantics, removal condition).
  • D2 — updated the scorecard job header to list all 3 run modes (schedule / manual full / selective).
  • F — truncated external API + Slack webhook error bodies in core.warning logs.

@github-actions

github-actions Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Selective E2E Results — ✅ All requested jobs passed

Run: 27038151770
Target ref: feat/update-slack-report-message
Requested jobs: overlayfs-autofix-e2e
Summary: 1 passed, 0 failed, 0 skipped

Job Result
overlayfs-autofix-e2e ✅ success

@cv cv merged commit 3090c4d into main Jun 5, 2026
97 checks passed
@cv cv deleted the feat/update-slack-report-message branch June 5, 2026 20:40
@wscurran wscurran added area: messaging Messaging channels, bridges, manifests, or channel lifecycle feature PR adds or expands user-visible functionality labels Jun 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: ci CI workflows, checks, release automation, or GitHub Actions area: messaging Messaging channels, bridges, manifests, or channel lifecycle feature PR adds or expands user-visible functionality v0.0.60 Release target VRDC Issues and PRs submitted by NVIDIA VRDC test team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants