Skip to content

Commit 4ee1fc6

Browse files
authored
fix(results): remove selected run publish workflow
1 parent c8d8030 commit 4ee1fc6

13 files changed

Lines changed: 83 additions & 668 deletions

File tree

apps/cli/src/commands/results/remote.ts

Lines changed: 0 additions & 160 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,9 @@ import {
66
type EvaluationResult,
77
type GitListedRun,
88
type ResultsConfig,
9-
ResultsRepoRunExistsError,
109
type ResultsRepoStatus,
1110
directPushResults,
1211
directorySizeBytes,
13-
findResultsRepoRun,
1412
getProject,
1513
getProjectForPath,
1614
getResultsRepoSyncStatus,
@@ -29,7 +27,6 @@ import {
2927
listResultFiles,
3028
listResultFilesFromRunsDir,
3129
} from '../inspect/utils.js';
32-
import { loadManifestResults } from './manifest.js';
3330
import {
3431
type RemoteRunTagState,
3532
assertWritableResultsRepo,
@@ -100,33 +97,6 @@ export interface RemoteResultsStatus extends ResultsRepoStatus {
10097
readonly run_count: number;
10198
}
10299

103-
export interface LocalRunPublishPreview {
104-
readonly sourceRunId: string;
105-
readonly targetRepo: string;
106-
readonly targetPath: string;
107-
readonly targetRunId: string;
108-
readonly remoteExists: boolean;
109-
readonly replaceRequired: boolean;
110-
readonly canPublish: boolean;
111-
readonly blockReason?: string;
112-
readonly remoteStatus: RemoteResultsStatus;
113-
}
114-
115-
export interface LocalRunPublishResult extends LocalRunPublishPreview {
116-
readonly published: boolean;
117-
readonly replaced: boolean;
118-
}
119-
120-
export class LocalRunPublishError extends Error {
121-
readonly status: 400 | 409;
122-
123-
constructor(message: string, status: 400 | 409 = 400) {
124-
super(message);
125-
this.name = 'LocalRunPublishError';
126-
this.status = status;
127-
}
128-
}
129-
130100
const REMOTE_RUN_PREFIX = 'remote::';
131101
const SIZE_WARNING_BYTES = 10 * 1024 * 1024;
132102

@@ -152,136 +122,6 @@ function getRelativeRunPath(cwd: string, runDir: string): string {
152122
return experiment && experiment !== runName ? path.join(experiment, runName) : runName;
153123
}
154124

155-
function toPosixPath(p: string): string {
156-
return p.split(path.sep).join('/');
157-
}
158-
159-
function getPublishStatusBlockReason(status: RemoteResultsStatus): string | undefined {
160-
if (!status.configured) {
161-
return 'Remote results repo is not configured for this project.';
162-
}
163-
164-
if (status.sync_status === 'syncing') {
165-
return 'Project sync is already in progress. Wait for it to finish before publishing a run.';
166-
}
167-
168-
if (status.sync_status && status.sync_status !== 'clean') {
169-
return 'Sync Project before publishing a selected run so pending result metadata is handled first.';
170-
}
171-
172-
if (status.blocked) {
173-
return status.block_reason ?? 'Remote results repo sync is blocked.';
174-
}
175-
176-
return undefined;
177-
}
178-
179-
function getExperimentFromRunId(runId: string): string {
180-
const separatorIndex = runId.lastIndexOf('::');
181-
return separatorIndex === -1 ? 'default' : runId.slice(0, separatorIndex);
182-
}
183-
184-
async function buildLocalRunPublishPreview(params: {
185-
readonly cwd: string;
186-
readonly config: Required<ResultsConfig>;
187-
readonly meta: Pick<SourcedResultFileMeta, 'source' | 'path' | 'raw_filename'>;
188-
readonly projectId?: string;
189-
}): Promise<LocalRunPublishPreview & { readonly relativeRunPath: string }> {
190-
if (params.meta.source !== 'local') {
191-
throw new LocalRunPublishError('Selected run publish is only available for local runs');
192-
}
193-
194-
const runDir = path.dirname(params.meta.path);
195-
const relativeRunPath = toPosixPath(getRelativeRunPath(params.cwd, runDir));
196-
const targetPath = path.posix.join('.agentv/results/runs', relativeRunPath);
197-
const existingRun = await findResultsRepoRun(params.config, params.meta.raw_filename);
198-
const remoteStatus = await getRemoteResultsStatus(params.cwd, params.projectId);
199-
const blockReason = getPublishStatusBlockReason(remoteStatus);
200-
const remoteExists = existingRun !== undefined;
201-
202-
return {
203-
sourceRunId: params.meta.raw_filename,
204-
targetRepo: params.config.repo,
205-
targetPath,
206-
targetRunId: params.meta.raw_filename,
207-
remoteExists,
208-
replaceRequired: remoteExists,
209-
canPublish: !blockReason && !remoteExists,
210-
...(blockReason && { blockReason }),
211-
remoteStatus,
212-
relativeRunPath,
213-
};
214-
}
215-
216-
export async function previewLocalRunPublish(
217-
cwd: string,
218-
meta: Pick<SourcedResultFileMeta, 'source' | 'path' | 'raw_filename'>,
219-
projectId?: string,
220-
): Promise<LocalRunPublishPreview> {
221-
const config = await loadNormalizedResultsConfig(cwd, projectId);
222-
if (!config) {
223-
throw new LocalRunPublishError('Remote results repo is not configured for this project', 409);
224-
}
225-
226-
const { relativeRunPath: _relativeRunPath, ...preview } = await buildLocalRunPublishPreview({
227-
cwd,
228-
config,
229-
meta,
230-
projectId,
231-
});
232-
return preview;
233-
}
234-
235-
export async function publishLocalRun(params: {
236-
readonly cwd: string;
237-
readonly meta: Pick<SourcedResultFileMeta, 'source' | 'path' | 'raw_filename'>;
238-
readonly projectId?: string;
239-
readonly replace?: boolean;
240-
}): Promise<LocalRunPublishResult> {
241-
const config = await loadNormalizedResultsConfig(params.cwd, params.projectId);
242-
if (!config) {
243-
throw new LocalRunPublishError('Remote results repo is not configured for this project', 409);
244-
}
245-
246-
const preview = await buildLocalRunPublishPreview({
247-
cwd: params.cwd,
248-
config,
249-
meta: params.meta,
250-
projectId: params.projectId,
251-
});
252-
if (preview.blockReason) {
253-
throw new LocalRunPublishError(preview.blockReason, 409);
254-
}
255-
if (preview.remoteExists && params.replace !== true) {
256-
throw new ResultsRepoRunExistsError(preview.targetRunId, preview.relativeRunPath);
257-
}
258-
259-
await maybeWarnLargeArtifact(path.dirname(params.meta.path));
260-
const results = loadManifestResults(params.meta.path);
261-
const pushed = await directPushResults({
262-
config,
263-
sourceDir: path.dirname(params.meta.path),
264-
destinationPath: preview.relativeRunPath,
265-
commitMessage: buildCommitTitle({
266-
cwd: params.cwd,
267-
run_dir: path.dirname(params.meta.path),
268-
test_files: [],
269-
results,
270-
eval_summaries: [],
271-
experiment: getExperimentFromRunId(preview.targetRunId),
272-
}),
273-
replaceExisting: params.replace === true,
274-
});
275-
276-
invalidateGitRunsCache(config.path);
277-
const refreshed = await previewLocalRunPublish(params.cwd, params.meta, params.projectId);
278-
return {
279-
...refreshed,
280-
published: pushed,
281-
replaced: preview.remoteExists && params.replace === true,
282-
};
283-
}
284-
285125
function buildCommitTitle(payload: RemoteExportPayload): string {
286126
const passed = payload.results.filter((result) => result.score >= DEFAULT_THRESHOLD).length;
287127
const avgScore =

apps/cli/src/commands/results/serve.ts

Lines changed: 0 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ import { command, flag, number, option, optional, positional, string } from 'cmd
4040
import {
4141
DEFAULT_CATEGORY,
4242
type EvaluationResult,
43-
ResultsRepoRunExistsError,
4443
addProject,
4544
getProject,
4645
loadConfig,
@@ -73,16 +72,12 @@ import {
7372
resolveResultSourcePath,
7473
} from './manifest.js';
7574
import {
76-
LocalRunPublishError,
77-
type LocalRunPublishPreview,
7875
type SourcedResultFileMeta,
7976
clearRemoteRunTags,
8077
ensureRemoteRunAvailable,
8178
findRunById,
8279
getRemoteResultsStatus,
8380
listMergedResultFiles,
84-
previewLocalRunPublish,
85-
publishLocalRun,
8681
readRemoteRunTagState,
8782
setRemoteRunTags,
8883
syncRemoteResults,
@@ -367,34 +362,6 @@ function remoteMetadataErrorStatus(error: unknown): 400 | 409 {
367362
return 400;
368363
}
369364

370-
function localRunPublishToWire(
371-
preview: LocalRunPublishPreview & { published?: boolean; replaced?: boolean },
372-
) {
373-
return {
374-
source_run_id: preview.sourceRunId,
375-
target_repo: preview.targetRepo,
376-
target_path: preview.targetPath,
377-
target_run_id: preview.targetRunId,
378-
remote_exists: preview.remoteExists,
379-
replace_required: preview.replaceRequired,
380-
can_publish: preview.canPublish,
381-
...(preview.blockReason && { block_reason: preview.blockReason }),
382-
remote_status: preview.remoteStatus,
383-
...(preview.published !== undefined && { published: preview.published }),
384-
...(preview.replaced !== undefined && { replaced: preview.replaced }),
385-
};
386-
}
387-
388-
function localRunPublishErrorStatus(error: unknown): 400 | 409 | 500 {
389-
if (error instanceof LocalRunPublishError) {
390-
return error.status;
391-
}
392-
if (error instanceof ResultsRepoRunExistsError) {
393-
return 409;
394-
}
395-
return 500;
396-
}
397-
398365
async function ensureRunReadable(
399366
searchDir: string,
400367
meta: SourcedResultFileMeta,
@@ -1248,52 +1215,6 @@ function validateLocalCompletedRun(
12481215
return { error: 'Run workspace is outside the local results directory', status: 400 };
12491216
}
12501217

1251-
async function handleRunPublishPreview(c: C, { searchDir, projectId }: DataContext) {
1252-
const filename = c.req.param('filename') ?? '';
1253-
const meta = await findRunById(searchDir, filename, projectId);
1254-
if (!meta) return c.json({ error: 'Run not found' }, 404);
1255-
const safe = validateLocalCompletedRun(searchDir, meta, 'Selected run publish');
1256-
if ('error' in safe) return c.json({ error: safe.error }, safe.status);
1257-
1258-
try {
1259-
const preview = await previewLocalRunPublish(searchDir, meta, projectId);
1260-
return c.json(localRunPublishToWire(preview));
1261-
} catch (err) {
1262-
return c.json({ error: (err as Error).message }, localRunPublishErrorStatus(err));
1263-
}
1264-
}
1265-
1266-
async function handleRunPublish(c: C, { searchDir, projectId }: DataContext) {
1267-
const filename = c.req.param('filename') ?? '';
1268-
const meta = await findRunById(searchDir, filename, projectId);
1269-
if (!meta) return c.json({ error: 'Run not found' }, 404);
1270-
const safe = validateLocalCompletedRun(searchDir, meta, 'Selected run publish');
1271-
if ('error' in safe) return c.json({ error: safe.error }, safe.status);
1272-
1273-
let replace = false;
1274-
try {
1275-
const body = (await c.req.json()) as unknown;
1276-
if (body && typeof body === 'object' && !Array.isArray(body)) {
1277-
const value = (body as Record<string, unknown>).replace;
1278-
if (value !== undefined && typeof value !== 'boolean') {
1279-
return c.json({ error: 'replace must be a boolean' }, 400);
1280-
}
1281-
replace = value === true;
1282-
} else if (body !== undefined) {
1283-
return c.json({ error: 'Invalid payload' }, 400);
1284-
}
1285-
} catch {
1286-
return c.json({ error: 'Invalid JSON' }, 400);
1287-
}
1288-
1289-
try {
1290-
const result = await publishLocalRun({ cwd: searchDir, meta, projectId, replace });
1291-
return c.json(localRunPublishToWire(result));
1292-
} catch (err) {
1293-
return c.json({ error: (err as Error).message }, localRunPublishErrorStatus(err));
1294-
}
1295-
}
1296-
12971218
async function handleRunsCombine(c: C, { searchDir, projectId }: DataContext) {
12981219
let body: unknown;
12991220
try {
@@ -1618,13 +1539,6 @@ export function createApp(
16181539
}
16191540
return handleRunsCombine(c, defaultCtx);
16201541
});
1621-
app.get('/api/runs/:filename/publish', (c) => handleRunPublishPreview(c, defaultCtx));
1622-
app.post('/api/runs/:filename/publish', (c) => {
1623-
if (readOnly) {
1624-
return c.json({ error: 'Dashboard is running in read-only mode' }, 403);
1625-
}
1626-
return handleRunPublish(c, defaultCtx);
1627-
});
16281542
app.put('/api/runs/:filename/tags', (c) => {
16291543
if (readOnly) {
16301544
return c.json({ error: 'Dashboard is running in read-only mode' }, 403);
@@ -1766,15 +1680,6 @@ export function createApp(
17661680
}
17671681
return withProject(c, handleRunsCombine);
17681682
});
1769-
app.get('/api/projects/:projectId/runs/:filename/publish', (c) =>
1770-
withProject(c, handleRunPublishPreview),
1771-
);
1772-
app.post('/api/projects/:projectId/runs/:filename/publish', (c) => {
1773-
if (readOnly) {
1774-
return c.json({ error: 'Dashboard is running in read-only mode' }, 403);
1775-
}
1776-
return withProject(c, handleRunPublish);
1777-
});
17781683
app.put('/api/projects/:projectId/runs/:filename/tags', (c) => {
17791684
if (readOnly) {
17801685
return c.json({ error: 'Dashboard is running in read-only mode' }, 403);

0 commit comments

Comments
 (0)