Files
Dotta 9ecd93a54d test(e2e): link runner campaign summaries (#12927)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Paperclip uses a paid full-stack campaign to verify runner behavior
across providers and environments.
> - The campaign already creates an interactive report, workflow logs,
and retained evidence artifacts.
> - The merge job summary shows result totals but does not link to those
resources.
> - Reviewers must search several workflow jobs and artifacts to find
the executed cells.
> - This pull request adds direct and safe links to the exact campaign,
each cell, the workflow logs, and the artifacts.
> - The benefit is that a reviewer can inspect a result from the Actions
summary with one click.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

This improves the `Merge and enforce campaign result` summary in the
`Runner Full-Stack E2E` workflow.

**Subsystem affected**

The runner E2E report generator and its GitHub Actions workflow are
affected.

**Current behavior**

The summary lists each selected cell and its result. It does not link to
the published campaign report, the workflow logs, or the evidence
artifacts.

**Proposed behavior**

The summary includes a `View results` section. It links to the exact
immutable campaign report, the workflow logs, and the artifacts. Each
cell name links to its stable section in the campaign report.

**Reason and benefit**

The current summary does not show reviewers where to inspect the run.
Direct links make the result evidence discoverable without manual URL
construction or artifact searches.

**Breaking changes**

None. This change only adds links and stable HTML anchors to existing
report output.

**Additional context**

Related: #12904. The cited successful campaign is [run
34026735033](https://github.com/paperclipai/paperclip/actions/runs/34026735033).

## What Changed

- Add a safe URL builder for public campaign, workflow, and artifact
links.
- Add a `View results` section to the GitHub Actions campaign summary.
- Link each summary table cell to its exact section in the immutable
campaign report.
- Add stable execution anchors to the generated dashboard.
- Reject non-HTTPS, credential-bearing, malformed, and ambiguous link
destinations.
- Document the new links and their retention or publication timing.

## Verification

- `pnpm test:e2e:runner:unit` — 116 tests passed.
- `pnpm test:e2e:runner:typecheck` — passed.
- `pnpm typecheck` — passed, including migration safety.
- `pnpm build` — passed.
- `pnpm exec prettier --check ...` for all changed files — passed.
- `git diff --check origin/master...HEAD` — passed.
- The full local server suite also ran. One unrelated macOS
workspace-runtime file passed 157 tests and failed 4 existing path and
port assumptions. Two failures compare `/var` with `/private/var`. Two
failures cannot reserve a port outside a hard-coded range. This PR does
not change that file or its dependencies.

## Risks

- The immutable campaign link becomes available after the history
publisher completes. The workflow and artifact links remain available
while publication runs.
- The artifact link requires GitHub access and follows the existing
30-day retention period.
- Invalid configured URLs are omitted instead of being rendered into the
summary.

> For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and
discuss it in `#dev` before opening the PR. Feature PRs that overlap
with planned core work may need to be redirected — check the roadmap
first. See `CONTRIBUTING.md`.

## Model Used

OpenAI Codex desktop agent with GPT-5. The runtime does not expose the
context-window size. The agent used repository inspection, agentic
reasoning, code execution, and GitHub CLI tools.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g.
`docs/no-internal-issue-references`, `fix/sandbox-secret-resolution`,
`feat/adapter-retry-backoff`) and contains no internal Paperclip ticket
id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge
2026-09-06 09:09:51 -05:00

74 lines
2.0 KiB
TypeScript

import {
runnerE2ECampaignPublicUrl,
validateHistoryPublicDestination,
} from "./history-destination.js";
export interface RunnerE2ESummaryLink {
kind: "campaign" | "workflow" | "artifacts";
label: string;
url: string;
note?: string;
}
function safeHttpsUrl(value: string | null | undefined) {
const input = value?.trim();
if (!input) return null;
try {
const url = new URL(input);
if (
url.protocol !== "https:" ||
url.username ||
url.password ||
url.search ||
url.hash
) {
return null;
}
return url;
} catch {
return null;
}
}
export function runnerE2ESummaryLinks(input: {
campaignId: string;
workflowRunUrl: string | null | undefined;
historyPublicBaseUrl: string | null | undefined;
historyPrefix: string | null | undefined;
}): RunnerE2ESummaryLink[] {
const links: RunnerE2ESummaryLink[] = [];
if (/^[A-Za-z0-9][A-Za-z0-9._-]{0,199}$/.test(input.campaignId)) {
try {
const destination = validateHistoryPublicDestination({
publicBaseUrl: input.historyPublicBaseUrl?.trim() ?? "",
prefix: input.historyPrefix?.trim() ?? "",
});
links.push({
kind: "campaign",
label: "Open the exact interactive campaign report",
url: runnerE2ECampaignPublicUrl(destination, input.campaignId),
note: "available after the history publisher finishes",
});
} catch {
// Invalid or absent history configuration must not prevent report merging.
}
}
const workflowRun = safeHttpsUrl(input.workflowRunUrl);
if (workflowRun) {
links.push({
kind: "workflow",
label: "Open the workflow run and per-cell job logs",
url: workflowRun.href,
});
workflowRun.hash = "artifacts";
links.push({
kind: "artifacts",
label: "Download the merged report and per-cell evidence",
url: workflowRun.href,
note: "GitHub access required; retained for 30 days",
});
}
return links;
}