mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-10-08 03:10:26 +00:00
Make run provenance and creators total
This commit is contained in:
parent
04d6587276
commit
e3bfa60ac4
85 changed files with 458 additions and 224 deletions
|
|
@ -52,10 +52,15 @@ function cellAfterLabel(
|
|||
|
||||
function makeRun(overrides: Record<string, any> = {}) {
|
||||
return {
|
||||
id: "run_1",
|
||||
created_by: null,
|
||||
diff: null,
|
||||
billing: null,
|
||||
id: "run_1",
|
||||
created_by: {
|
||||
kind: "user",
|
||||
identity: { issuer: "fabro:test", subject: "test-user" },
|
||||
login: "test",
|
||||
auth_method: "dev_token",
|
||||
},
|
||||
diff: null,
|
||||
billing: null,
|
||||
...overrides,
|
||||
} as any;
|
||||
}
|
||||
|
|
@ -71,9 +76,8 @@ describe("RunSummaryPanelView", () => {
|
|||
}
|
||||
});
|
||||
|
||||
test("shows unavailable copy for missing run fields after load", () => {
|
||||
test("shows unavailable copy for missing optional run fields after load", () => {
|
||||
const tree = render({ run: makeRun() });
|
||||
expect(instanceText(cellAfterLabel(tree, "Created by"))).toBe(EMPTY_VALUE);
|
||||
expect(instanceText(cellAfterLabel(tree, "Changes"))).toBe(EMPTY_VALUE);
|
||||
expect(instanceText(cellAfterLabel(tree, "Cost"))).toBe(EMPTY_VALUE);
|
||||
});
|
||||
|
|
@ -226,7 +230,7 @@ describe("RunSummaryPanelView", () => {
|
|||
kind: "user",
|
||||
identity: { issuer: "github", subject: "1" },
|
||||
login: "brynary",
|
||||
auth_method: "oauth",
|
||||
auth_method: "github",
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
|
@ -240,7 +244,7 @@ describe("RunSummaryPanelView", () => {
|
|||
kind: "user",
|
||||
identity: { issuer: "github", subject: "1" },
|
||||
login: "brynary",
|
||||
auth_method: "oauth",
|
||||
auth_method: "github",
|
||||
avatar_url: "https://example.com/brynary.png",
|
||||
},
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ export function RunSummaryPanelView({
|
|||
artifactsCount,
|
||||
artifactsLoading,
|
||||
}: RunSummaryPanelViewProps) {
|
||||
const created = run?.created_by ? principalDisplay(run.created_by) : null;
|
||||
const created = run == null ? null : principalDisplay(run.created_by);
|
||||
const diff = run?.diff ?? null;
|
||||
const cost = formatUsdMicros(run?.billing?.total_usd_micros);
|
||||
const sandboxKind = sandboxLifecycleKind(run?.sandbox);
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ export function RunTableRow({
|
|||
</td>
|
||||
{show("created_by") && (
|
||||
<td className="relative z-10 w-8 whitespace-nowrap px-3 py-2.5">
|
||||
{run.createdBy && (() => {
|
||||
{(() => {
|
||||
const display = principalDisplay(run.createdBy);
|
||||
return (
|
||||
<Tooltip label={display.label}>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { describe, expect, test } from "bun:test";
|
||||
import type { Run, RunStatus as ApiRunStatus } from "@qltysh/fabro-api-client";
|
||||
import type { Principal, Run, RunStatus as ApiRunStatus } from "@qltysh/fabro-api-client";
|
||||
import {
|
||||
columnForStatus,
|
||||
columnStatusDisplay,
|
||||
|
|
@ -9,6 +9,15 @@ import {
|
|||
runStatusDisplay,
|
||||
} from "./runs";
|
||||
|
||||
function testPrincipal(): Principal {
|
||||
return {
|
||||
kind: "user",
|
||||
identity: { issuer: "fabro:test", subject: "test-user" },
|
||||
login: "test",
|
||||
auth_method: "dev_token",
|
||||
};
|
||||
}
|
||||
|
||||
function makeRun(overrides: Partial<Run> = {}): Run {
|
||||
return {
|
||||
id: "01ABC",
|
||||
|
|
@ -17,7 +26,7 @@ function makeRun(overrides: Partial<Run> = {}): Run {
|
|||
workflow: { slug: "fix_build", name: "Fix Build", graph_name: "FixBuild", node_count: 0, edge_count: 0 },
|
||||
automation: null,
|
||||
repository: { name: "myrepo", origin_url: null, provider: "unknown" },
|
||||
created_by: null,
|
||||
created_by: testPrincipal(),
|
||||
origin: { kind: "api" },
|
||||
labels: {},
|
||||
lifecycle: {
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ export interface RunItem {
|
|||
sandboxWorkingDirectory?: string;
|
||||
sourceDirectory?: string;
|
||||
createdAt?: string;
|
||||
createdBy?: Principal | null;
|
||||
createdBy: Principal;
|
||||
lastEventAt?: string;
|
||||
size?: RunSize;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,13 @@ import {
|
|||
} from "./run-actions";
|
||||
import { generatedAxios } from "./api-client";
|
||||
|
||||
const TEST_PRINCIPAL = {
|
||||
kind: "user",
|
||||
identity: { issuer: "fabro:test", subject: "test-user" },
|
||||
login: "test",
|
||||
auth_method: "dev_token",
|
||||
};
|
||||
|
||||
type StubResponseInit = {
|
||||
status: number;
|
||||
body?: unknown;
|
||||
|
|
@ -47,7 +54,7 @@ function makeRun(status: RunStatus, archived = false): Run {
|
|||
workflow: { slug: "fix_build", name: "Fix Build", graph_name: null, node_count: 0, edge_count: 0 },
|
||||
automation: null,
|
||||
repository: null,
|
||||
created_by: null,
|
||||
created_by: TEST_PRINCIPAL,
|
||||
origin: { kind: "api" },
|
||||
labels: {},
|
||||
lifecycle: {
|
||||
|
|
|
|||
|
|
@ -101,6 +101,13 @@ mock.module("swr", () => ({
|
|||
const { default: AutomationsNew } = await import("./automations-new");
|
||||
mock.restore();
|
||||
|
||||
const TEST_PRINCIPAL = {
|
||||
kind: "user",
|
||||
identity: { issuer: "fabro:test", subject: "test-user" },
|
||||
login: "test",
|
||||
auth_method: "dev_token",
|
||||
};
|
||||
|
||||
function makeRun(overrides: Record<string, unknown> = {}) {
|
||||
return {
|
||||
id: "run_1",
|
||||
|
|
@ -120,7 +127,7 @@ function makeRun(overrides: Record<string, unknown> = {}) {
|
|||
origin_url: "https://github.com/fallback/repo.git",
|
||||
provider: "github",
|
||||
},
|
||||
created_by: null,
|
||||
created_by: TEST_PRINCIPAL,
|
||||
origin: { kind: "api" },
|
||||
labels: {},
|
||||
lifecycle: {
|
||||
|
|
|
|||
|
|
@ -20,6 +20,13 @@ let currentQuestions: any[] = [];
|
|||
let deleteRunApiResult: Promise<unknown> | null = null;
|
||||
const mountedRenderers: TestRenderer.ReactTestRenderer[] = [];
|
||||
|
||||
const TEST_PRINCIPAL = {
|
||||
kind: "user",
|
||||
identity: { issuer: "fabro:test", subject: "test-user" },
|
||||
login: "test",
|
||||
auth_method: "dev_token",
|
||||
};
|
||||
|
||||
const deleteRunApiMock = mock((_id: string) =>
|
||||
deleteRunApiResult ?? Promise.resolve({}),
|
||||
);
|
||||
|
|
@ -221,7 +228,7 @@ function makeRunSummary({
|
|||
workflow: { slug: "default", name: "Default", graph_name: null, node_count: 0, edge_count: 0 },
|
||||
automation,
|
||||
repository: { name: "fabro", origin_url: null, provider: "unknown" },
|
||||
created_by: null,
|
||||
created_by: TEST_PRINCIPAL,
|
||||
origin: { kind: "api" },
|
||||
labels: {},
|
||||
lifecycle: {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,13 @@ import { toast as sonnerToast } from "sonner";
|
|||
|
||||
import { ToastProvider } from "../components/toast";
|
||||
|
||||
const TEST_PRINCIPAL = {
|
||||
kind: "user",
|
||||
identity: { issuer: "fabro:test", subject: "test-user" },
|
||||
login: "test",
|
||||
auth_method: "dev_token",
|
||||
};
|
||||
|
||||
let currentFilesPayload: any = null;
|
||||
let currentCommitsPayload: any = null;
|
||||
let currentRunStatus = "succeeded";
|
||||
|
|
@ -51,7 +58,7 @@ mock.module("../lib/queries", () => ({
|
|||
workflow: { slug: "default", name: "Default", graph_name: null, node_count: 0, edge_count: 0 },
|
||||
automation: null,
|
||||
repository: { name: "fabro", origin_url: null, provider: "unknown" },
|
||||
created_by: null,
|
||||
created_by: TEST_PRINCIPAL,
|
||||
origin: { kind: "api" },
|
||||
labels: {},
|
||||
lifecycle: {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
|
||||
import TestRenderer, { act } from "react-test-renderer";
|
||||
import { createMemoryRouter, RouterProvider } from "react-router";
|
||||
import type { PaginatedRunList, Run } from "@qltysh/fabro-api-client";
|
||||
import type { PaginatedRunList, Principal, Run } from "@qltysh/fabro-api-client";
|
||||
|
||||
import { ToastProvider } from "../components/toast";
|
||||
import { CHILD_RUNS_LIST_PREFERENCES_STORAGE_KEY } from "../components/runs-list/preferences";
|
||||
|
|
@ -27,6 +27,15 @@ let previousElement: unknown;
|
|||
let hadElement = false;
|
||||
const mountedRenderers: TestRenderer.ReactTestRenderer[] = [];
|
||||
|
||||
function testPrincipal(): Principal {
|
||||
return {
|
||||
kind: "user",
|
||||
identity: { issuer: "fabro:test", subject: "test-user" },
|
||||
login: "test",
|
||||
auth_method: "dev_token",
|
||||
};
|
||||
}
|
||||
|
||||
function run(id: string, repo = "qlty/fabro", workflow = "release"): Run {
|
||||
return {
|
||||
id,
|
||||
|
|
@ -35,7 +44,7 @@ function run(id: string, repo = "qlty/fabro", workflow = "release"): Run {
|
|||
workflow: { slug: workflow, name: workflow, graph_name: null, node_count: 0, edge_count: 0 },
|
||||
automation: null,
|
||||
repository: { name: repo, origin_url: null, provider: "github" },
|
||||
created_by: null,
|
||||
created_by: testPrincipal(),
|
||||
origin: { kind: "api" },
|
||||
labels: {},
|
||||
lifecycle: {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { describe, expect, test } from "bun:test";
|
||||
import type { BoardColumn, Run } from "@qltysh/fabro-api-client";
|
||||
import type { BoardColumn, Principal, Run } from "@qltysh/fabro-api-client";
|
||||
|
||||
import {
|
||||
buildBoardColumns,
|
||||
|
|
@ -12,6 +12,15 @@ import {
|
|||
} from "./runs";
|
||||
import { summarizeBatchLifecycleAction } from "../components/runs-list/batch-lifecycle";
|
||||
|
||||
function testPrincipal(): Principal {
|
||||
return {
|
||||
kind: "user",
|
||||
identity: { issuer: "fabro:test", subject: "test-user" },
|
||||
login: "test",
|
||||
auth_method: "dev_token",
|
||||
};
|
||||
}
|
||||
|
||||
function boardRun(id: string, column: BoardColumn, questionText?: string): Run {
|
||||
const status =
|
||||
column === "blocked"
|
||||
|
|
@ -34,7 +43,7 @@ function boardRun(id: string, column: BoardColumn, questionText?: string): Run {
|
|||
workflow: { slug: "test", name: "Test", graph_name: null, node_count: 0, edge_count: 0 },
|
||||
automation: null,
|
||||
repository: { name: "repo", origin_url: null, provider: "unknown" },
|
||||
created_by: null,
|
||||
created_by: testPrincipal(),
|
||||
origin: { kind: "api" },
|
||||
labels: {},
|
||||
lifecycle: {
|
||||
|
|
|
|||
|
|
@ -8992,6 +8992,8 @@ components:
|
|||
|
||||
RunProvenance:
|
||||
type: object
|
||||
required:
|
||||
- subject
|
||||
properties:
|
||||
server:
|
||||
oneOf:
|
||||
|
|
@ -9002,9 +9004,7 @@ components:
|
|||
- $ref: "#/components/schemas/RunClientProvenance"
|
||||
- type: "null"
|
||||
subject:
|
||||
oneOf:
|
||||
- $ref: "#/components/schemas/Principal"
|
||||
- type: "null"
|
||||
$ref: "#/components/schemas/Principal"
|
||||
|
||||
Principal:
|
||||
oneOf:
|
||||
|
|
@ -10239,6 +10239,7 @@ components:
|
|||
- run_id
|
||||
- settings
|
||||
- graph
|
||||
- provenance
|
||||
properties:
|
||||
run_id:
|
||||
type: string
|
||||
|
|
@ -10262,9 +10263,7 @@ components:
|
|||
additionalProperties:
|
||||
type: string
|
||||
provenance:
|
||||
oneOf:
|
||||
- $ref: "#/components/schemas/RunProvenance"
|
||||
- type: "null"
|
||||
$ref: "#/components/schemas/RunProvenance"
|
||||
manifest_blob:
|
||||
type: ["string", "null"]
|
||||
definition_blob:
|
||||
|
|
@ -10576,9 +10575,7 @@ components:
|
|||
- $ref: "#/components/schemas/RepositoryRef"
|
||||
- type: "null"
|
||||
created_by:
|
||||
oneOf:
|
||||
- $ref: "#/components/schemas/Principal"
|
||||
- type: "null"
|
||||
$ref: "#/components/schemas/Principal"
|
||||
origin:
|
||||
$ref: "#/components/schemas/RunOrigin"
|
||||
labels:
|
||||
|
|
|
|||
|
|
@ -34,3 +34,6 @@ serde_json = "1"
|
|||
serde_yaml = "0.9"
|
||||
prettyplease = "0.2"
|
||||
syn = "2"
|
||||
|
||||
[dev-dependencies]
|
||||
fabro-types = { path = "../fabro-types", features = ["test-support"] }
|
||||
|
|
|
|||
|
|
@ -139,9 +139,9 @@ fn run_provenance_subject_round_trips_as_principal() {
|
|||
name: Some("fabro-cli".to_string()),
|
||||
version: Some("0.1.0".to_string()),
|
||||
}),
|
||||
subject: Some(Principal::Worker {
|
||||
subject: Principal::Worker {
|
||||
run_id: fixtures::RUN_1,
|
||||
}),
|
||||
},
|
||||
};
|
||||
let json = serde_json::to_value(&provenance).unwrap();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::any::{TypeId, type_name};
|
||||
|
||||
use fabro_api::types::RunEvent as ApiRunEvent;
|
||||
use fabro_types::{Graph, RunEvent, WorkflowSettings, fixtures};
|
||||
use fabro_types::{Graph, RunEvent, WorkflowSettings, fixtures, test_support};
|
||||
use serde_json::{Value, json};
|
||||
|
||||
#[test]
|
||||
|
|
@ -20,7 +20,8 @@ fn run_event_round_trips_run_created() {
|
|||
"settings": WorkflowSettings::default(),
|
||||
"graph": Graph::new("test"),
|
||||
"run_dir": "/tmp/fabro/run-1",
|
||||
"source_directory": "/tmp/fabro/run-1"
|
||||
"source_directory": "/tmp/fabro/run-1",
|
||||
"provenance": test_support::test_run_provenance()
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -39,7 +40,8 @@ fn run_event_round_trips_run_created_with_web_url() {
|
|||
"graph": Graph::new("test"),
|
||||
"run_dir": "/tmp/fabro/run-1",
|
||||
"source_directory": "/tmp/fabro/run-1",
|
||||
"web_url": format!("http://localhost:3000/runs/{}", fixtures::RUN_1)
|
||||
"web_url": format!("http://localhost:3000/runs/{}", fixtures::RUN_1),
|
||||
"provenance": test_support::test_run_provenance()
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ fn run_spec_json() -> serde_json::Value {
|
|||
automation: None,
|
||||
source_directory: None,
|
||||
labels: std::collections::HashMap::new(),
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
git: None,
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ use fabro_types::{
|
|||
AskFabro, AskFabroUnavailableReason, AutomationRef, DiffSummary, PullRequestLink,
|
||||
RepositoryProvider, RepositoryRef, Run, RunApproval, RunApprovalState, RunBillingSummary,
|
||||
RunId, RunLifecycle, RunLinks, RunOrigin, RunRunnableSource, RunSize, RunTimestamps, RunTiming,
|
||||
WorkflowRef, fixtures,
|
||||
WorkflowRef, fixtures, test_support,
|
||||
};
|
||||
use serde_json::json;
|
||||
|
||||
|
|
@ -88,7 +88,7 @@ fn run_summary_json_matches_openapi_shape() {
|
|||
origin_url: None,
|
||||
provider: RepositoryProvider::Unknown,
|
||||
}),
|
||||
created_by: None,
|
||||
created_by: test_support::test_principal(),
|
||||
origin: RunOrigin::default(),
|
||||
labels: HashMap::from([("team".to_string(), "core".to_string())]),
|
||||
lifecycle: RunLifecycle {
|
||||
|
|
@ -161,7 +161,15 @@ fn run_summary_json_matches_openapi_shape() {
|
|||
"origin_url": null,
|
||||
"provider": "unknown"
|
||||
},
|
||||
"created_by": null,
|
||||
"created_by": {
|
||||
"kind": "user",
|
||||
"identity": {
|
||||
"issuer": "fabro:test",
|
||||
"subject": "test-user"
|
||||
},
|
||||
"login": "test",
|
||||
"auth_method": "dev_token"
|
||||
},
|
||||
"origin": {
|
||||
"kind": "api"
|
||||
},
|
||||
|
|
@ -238,6 +246,15 @@ fn run_summary_deserializes_when_optional_fields_are_absent() {
|
|||
"name": null,
|
||||
"graph_name": "GraphName"
|
||||
},
|
||||
"created_by": {
|
||||
"kind": "user",
|
||||
"identity": {
|
||||
"issuer": "fabro:test",
|
||||
"subject": "test-user"
|
||||
},
|
||||
"login": "test",
|
||||
"auth_method": "dev_token"
|
||||
},
|
||||
"origin": {
|
||||
"kind": "api"
|
||||
},
|
||||
|
|
@ -275,6 +292,7 @@ fn run_summary_deserializes_when_optional_fields_are_absent() {
|
|||
assert_eq!(summary.workflow.edge_count, 0);
|
||||
assert_eq!(summary.goal, "ship it");
|
||||
assert_eq!(summary.title, "ship it");
|
||||
assert_eq!(summary.created_by, test_support::test_principal());
|
||||
assert_eq!(summary.labels, HashMap::new());
|
||||
assert_eq!(summary.source_directory, None);
|
||||
assert_eq!(
|
||||
|
|
@ -300,6 +318,50 @@ fn run_summary_deserializes_when_optional_fields_are_absent() {
|
|||
assert_eq!(summary.pull_request, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn run_summary_requires_created_by() {
|
||||
let created_at = Utc.with_ymd_and_hms(2026, 4, 20, 12, 0, 0).unwrap();
|
||||
let run_id = RunId::with_timestamp(created_at, 7);
|
||||
|
||||
let result = serde_json::from_value::<Run>(json!({
|
||||
"id": run_id.to_string(),
|
||||
"goal": "ship it",
|
||||
"title": "ship it",
|
||||
"workflow": {
|
||||
"slug": null,
|
||||
"name": null,
|
||||
"graph_name": "GraphName"
|
||||
},
|
||||
"origin": {
|
||||
"kind": "api"
|
||||
},
|
||||
"labels": {},
|
||||
"lifecycle": {
|
||||
"status": {
|
||||
"kind": "running"
|
||||
},
|
||||
"archived": false
|
||||
},
|
||||
"repository": {
|
||||
"name": "fabro",
|
||||
"origin_url": null,
|
||||
"provider": "unknown"
|
||||
},
|
||||
"models": [],
|
||||
"timestamps": {
|
||||
"created_at": "2026-04-20T12:00:00Z",
|
||||
"started_at": null,
|
||||
"last_event_at": null,
|
||||
"completed_at": null
|
||||
},
|
||||
"links": {
|
||||
"web": null
|
||||
}
|
||||
}));
|
||||
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn run_summary_rejects_legacy_flat_json() {
|
||||
let created_at = Utc.with_ymd_and_hms(2026, 4, 20, 12, 0, 0).unwrap();
|
||||
|
|
|
|||
|
|
@ -119,6 +119,7 @@ assert_cmd = "2"
|
|||
fabro-acp = { path = "../fabro-acp", features = ["test-support"] }
|
||||
fabro-build-support = { path = "../build-support" }
|
||||
fabro-server = { path = "../fabro-server", features = ["test-support"] }
|
||||
fabro-types = { path = "../fabro-types", features = ["test-support"] }
|
||||
insta = { workspace = true, features = ["filters"] }
|
||||
paste = "1"
|
||||
predicates = "3"
|
||||
|
|
|
|||
|
|
@ -841,7 +841,7 @@ mod tests {
|
|||
automation: None,
|
||||
source_directory: None,
|
||||
labels: std::collections::HashMap::default(),
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
git: None,
|
||||
|
|
|
|||
|
|
@ -221,7 +221,18 @@ fn inspect_resolves_selector_via_server_endpoint() {
|
|||
"attrs": {}
|
||||
},
|
||||
"workflow_slug": "remote-workflow",
|
||||
"source_directory": "/srv/repo"
|
||||
"source_directory": "/srv/repo",
|
||||
"provenance": {
|
||||
"subject": {
|
||||
"kind": "user",
|
||||
"identity": {
|
||||
"issuer": "fabro:test",
|
||||
"subject": "test-user"
|
||||
},
|
||||
"login": "test",
|
||||
"auth_method": "dev_token"
|
||||
}
|
||||
}
|
||||
},
|
||||
"start_record": null,
|
||||
"conclusion": null,
|
||||
|
|
|
|||
|
|
@ -177,6 +177,15 @@ pub(crate) fn remote_run_summary_json(
|
|||
"origin_url": null,
|
||||
"provider": "unknown"
|
||||
},
|
||||
"created_by": {
|
||||
"kind": "user",
|
||||
"identity": {
|
||||
"issuer": "fabro:test",
|
||||
"subject": "test-user"
|
||||
},
|
||||
"login": "test",
|
||||
"auth_method": "dev_token"
|
||||
},
|
||||
"origin": {
|
||||
"kind": "api"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ pub(crate) fn run_projection_json(run_id: &str, status: &serde_json::Value) -> s
|
|||
automation: None,
|
||||
source_directory: Some("/srv/repo".to_string()),
|
||||
labels: std::collections::HashMap::default(),
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
git: None,
|
||||
|
|
|
|||
|
|
@ -476,6 +476,7 @@ mod tests {
|
|||
Checkpoint, CheckpointRecord, Conclusion, RunDiff, RunSandbox, RunSandboxInstance,
|
||||
RunSandboxPlan, RunStatus, SandboxProviderKind, StageCompletion, StageModelUsage,
|
||||
StageOutcome, StartRecord, SuccessReason, WorkflowSettings, first_event_seq, fixtures,
|
||||
test_support,
|
||||
};
|
||||
use futures::executor;
|
||||
|
||||
|
|
@ -498,7 +499,7 @@ mod tests {
|
|||
push_outcome: fabro_types::PreRunPushOutcome::NotAttempted,
|
||||
}),
|
||||
labels: HashMap::from([("team".to_string(), "platform".to_string())]),
|
||||
provenance: None,
|
||||
provenance: test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
fork_source_ref: None,
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
reason = "Demo fixture data favors literal fidelity over pedantic style lints."
|
||||
)]
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::sync::{Arc, LazyLock};
|
||||
|
||||
use axum::Json;
|
||||
use axum::extract::{Path, Query, State};
|
||||
|
|
@ -23,7 +23,9 @@ use fabro_api::types::{
|
|||
RunFilesMeta, RunFilesMetaScope, RunFilesMetaSource, SandboxService,
|
||||
SandboxServiceListResponse,
|
||||
};
|
||||
use fabro_types::{SandboxServiceDiscoverySource, SandboxServiceListMeta};
|
||||
use fabro_types::{
|
||||
AuthMethod, IdpIdentity, Principal, SandboxServiceDiscoverySource, SandboxServiceListMeta,
|
||||
};
|
||||
use serde_json::json;
|
||||
|
||||
use crate::error::ApiError;
|
||||
|
|
@ -31,6 +33,14 @@ use crate::principal_middleware::RequiredUser;
|
|||
use crate::run_selector::{ResolveRunError, resolve_run_by_selector};
|
||||
use crate::server::{AppState, EventListParams, PaginationParams, parse_stage_id_path};
|
||||
|
||||
static DEMO_PRINCIPAL: LazyLock<Principal> = LazyLock::new(|| {
|
||||
Principal::user(
|
||||
IdpIdentity::new("fabro:demo", "demo").expect("demo identity should be valid"),
|
||||
"demo".to_string(),
|
||||
AuthMethod::DevToken,
|
||||
)
|
||||
});
|
||||
|
||||
fn paginated_response<T: serde::Serialize>(
|
||||
items: Vec<T>,
|
||||
pagination: &PaginationParams,
|
||||
|
|
@ -1096,7 +1106,7 @@ mod runs {
|
|||
RunSize, RunTimestamps, StageId, WorkflowRef, WorkflowSettings,
|
||||
};
|
||||
|
||||
use super::ts;
|
||||
use super::{DEMO_PRINCIPAL, ts};
|
||||
use crate::server::run_stage_from_stage_id;
|
||||
|
||||
fn labels(entries: &[(&str, &str)]) -> HashMap<String, String> {
|
||||
|
|
@ -1171,7 +1181,7 @@ mod runs {
|
|||
repo_origin_url,
|
||||
source_directory.as_deref(),
|
||||
)),
|
||||
created_by: None,
|
||||
created_by: DEMO_PRINCIPAL.clone(),
|
||||
origin: RunOrigin::default(),
|
||||
labels: labels(entries),
|
||||
lifecycle: RunLifecycle {
|
||||
|
|
|
|||
|
|
@ -2389,7 +2389,7 @@ index 1111111..2222222 160000
|
|||
automation: None,
|
||||
source_directory: None,
|
||||
labels: HashMap::default(),
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
git: None,
|
||||
|
|
|
|||
|
|
@ -27,7 +27,9 @@ use fabro_static::EnvVars;
|
|||
use fabro_types::settings::cli::OutputVerbosity;
|
||||
use fabro_types::settings::interp::InterpString;
|
||||
use fabro_types::settings::run::{EnvironmentProvider, RunGoal, RunNamespace};
|
||||
use fabro_types::{ManifestPath, RunId, SandboxProviderKind, ServerSettings, WorkflowSettings};
|
||||
use fabro_types::{
|
||||
ManifestPath, RunId, RunProvenance, SandboxProviderKind, ServerSettings, WorkflowSettings,
|
||||
};
|
||||
use fabro_util::check_report::{CheckDetail, CheckReport, CheckResult, CheckSection, CheckStatus};
|
||||
use fabro_validate::Severity;
|
||||
use fabro_workflow::Error as WorkflowError;
|
||||
|
|
@ -194,6 +196,7 @@ pub(crate) fn create_run_input(
|
|||
prepared: PreparedManifest,
|
||||
configured_providers: Vec<ProviderId>,
|
||||
web_url: Option<String>,
|
||||
provenance: RunProvenance,
|
||||
) -> CreateRunInput {
|
||||
CreateRunInput {
|
||||
workflow: WorkflowInput::Bundled(prepared.workflow_input),
|
||||
|
|
@ -209,7 +212,7 @@ pub(crate) fn create_run_input(
|
|||
git: prepared.git,
|
||||
fork_source_ref: None,
|
||||
parent_id: prepared.parent_id,
|
||||
provenance: None,
|
||||
provenance,
|
||||
configured_providers,
|
||||
web_url,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -570,7 +570,7 @@ mod stage_events_tests {
|
|||
workflow_slug: None,
|
||||
automation: None,
|
||||
db_prefix: None,
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
git: None,
|
||||
fork_source_ref: None,
|
||||
|
|
|
|||
|
|
@ -894,7 +894,7 @@ async fn retry_run(
|
|||
let input = operations::RetryRunInput {
|
||||
source_run_id: id,
|
||||
new_run_id,
|
||||
provenance: Some(run_provenance(&headers, &actor)),
|
||||
provenance: run_provenance(&headers, &actor),
|
||||
web_url: state.run_web_url(&new_run_id),
|
||||
};
|
||||
match Box::pin(operations::retry_run(&state.store, &input)).await {
|
||||
|
|
|
|||
|
|
@ -1024,7 +1024,7 @@ mod tests {
|
|||
workflow_slug: None,
|
||||
automation: None,
|
||||
db_prefix: None,
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
git: None,
|
||||
fork_source_ref: None,
|
||||
|
|
|
|||
|
|
@ -687,13 +687,14 @@ pub(crate) async fn create_run_from_manifest(
|
|||
.as_ref()
|
||||
.map(LlmClientResult::provider_ids)
|
||||
.unwrap_or_default();
|
||||
let provenance = run_provenance(&headers, &actor);
|
||||
let mut create_input = run_manifest::create_run_input(
|
||||
prepared.clone(),
|
||||
ready_provider_ids.clone(),
|
||||
web_url.clone(),
|
||||
provenance,
|
||||
);
|
||||
create_input.run_id = Some(run_id);
|
||||
create_input.provenance = Some(run_provenance(&headers, &actor));
|
||||
create_input.submitted_manifest_bytes = Some(submitted_manifest_bytes);
|
||||
create_input.automation = automation;
|
||||
|
||||
|
|
@ -864,7 +865,7 @@ pub(super) fn run_provenance(headers: &HeaderMap, subject: &Principal) -> RunPro
|
|||
version: FABRO_VERSION.to_string(),
|
||||
}),
|
||||
client: run_client_provenance(headers),
|
||||
subject: Some(subject.clone()),
|
||||
subject: subject.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1339,6 +1339,7 @@ mod retrieve_sandbox_tests {
|
|||
"settings": WorkflowSettings::default(),
|
||||
"graph": Graph::new("test"),
|
||||
"run_dir": "/tmp/test",
|
||||
"provenance": fabro_types::test_support::test_run_provenance(),
|
||||
},
|
||||
}),
|
||||
run_id,
|
||||
|
|
|
|||
|
|
@ -1700,7 +1700,7 @@ mod tests {
|
|||
automation: None,
|
||||
source_directory: None,
|
||||
labels: HashMap::default(),
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
git: None,
|
||||
|
|
|
|||
|
|
@ -4022,7 +4022,7 @@ async fn append_default_run_created(run_store: &fabro_store::RunDatabase, run_id
|
|||
workflow_slug: None,
|
||||
automation: None,
|
||||
db_prefix: None,
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
git: None,
|
||||
fork_source_ref: None,
|
||||
|
|
@ -4076,7 +4076,7 @@ async fn create_slack_notification_run(
|
|||
workflow_slug: workflow_slug.map(str::to_string),
|
||||
automation: None,
|
||||
db_prefix: None,
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
git: None,
|
||||
fork_source_ref: None,
|
||||
|
|
@ -5083,7 +5083,7 @@ async fn list_run_stages_distinguishes_visits() {
|
|||
workflow_slug: Some("test".to_string()),
|
||||
automation: None,
|
||||
db_prefix: None,
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
git: None,
|
||||
fork_source_ref: None,
|
||||
|
|
@ -6140,7 +6140,7 @@ async fn create_completed_run_ready_for_pull_request(
|
|||
source_directory: Some("/tmp/project".to_string()),
|
||||
git: git.clone(),
|
||||
labels: HashMap::new(),
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
fork_source_ref: None,
|
||||
|
|
@ -9943,15 +9943,10 @@ async fn run_tool_worker_token_can_use_client_backend_routes_across_runs() {
|
|||
.unwrap()
|
||||
.expect("created run should be cached");
|
||||
assert_eq!(
|
||||
cached
|
||||
.projection
|
||||
.spec
|
||||
.provenance
|
||||
.as_ref()
|
||||
.and_then(|provenance| provenance.subject.as_ref()),
|
||||
Some(&Principal::Worker {
|
||||
cached.projection.spec.provenance.subject,
|
||||
Principal::Worker {
|
||||
run_id: parent_run_id,
|
||||
}),
|
||||
},
|
||||
);
|
||||
|
||||
let response = app
|
||||
|
|
@ -12310,7 +12305,7 @@ async fn create_preserved_local_sandbox_run(state: &Arc<AppState>, run_id: RunId
|
|||
workflow_slug: Some("test".to_string()),
|
||||
automation: None,
|
||||
db_prefix: None,
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
git: None,
|
||||
fork_source_ref: None,
|
||||
|
|
@ -13062,7 +13057,7 @@ async fn delete_run_retry_after_missing_provider_resource_removes_metadata() {
|
|||
workflow_slug: Some("test".to_string()),
|
||||
automation: None,
|
||||
db_prefix: None,
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
git: None,
|
||||
fork_source_ref: None,
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ async fn append_completed_run_with_final_patch(
|
|||
workflow_slug: None,
|
||||
automation: None,
|
||||
db_prefix: None,
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
git: None,
|
||||
fork_source_ref: None,
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ futures.workspace = true
|
|||
uuid.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
fabro-types = { path = "../fabro-types", features = ["test-support"] }
|
||||
tokio = { workspace = true, features = ["test-util", "macros"] }
|
||||
tempfile = "3"
|
||||
ulid.workspace = true
|
||||
|
|
|
|||
|
|
@ -922,11 +922,7 @@ pub(crate) fn build_summary(state: &RunProjection, run_id: &RunId) -> Run {
|
|||
})
|
||||
.map(|(_, record)| record.question.clone());
|
||||
let models = run_models(state);
|
||||
let created_by = state
|
||||
.spec
|
||||
.provenance
|
||||
.as_ref()
|
||||
.and_then(|provenance| provenance.subject.clone());
|
||||
let created_by = state.spec.provenance.subject.clone();
|
||||
let source_directory = state.spec.source_directory.clone();
|
||||
let repo_origin_url = state.spec.git.as_ref().map(|git| git.origin_url.clone());
|
||||
let start_time = state.start.as_ref().map(|start| start.start_time);
|
||||
|
|
@ -1276,7 +1272,7 @@ mod tests {
|
|||
StageContextWindowBreakdownItem, StageContextWindowCategory, StageContextWindowCountMethod,
|
||||
StageContextWindowProjection, StageContextWindowStaleness, StageContextWindowWarning,
|
||||
StageModelUsage, StageOutcome, StageState, SubAgentStatus, SuccessReason, WorkflowSettings,
|
||||
first_event_seq, fixtures,
|
||||
first_event_seq, fixtures, test_support,
|
||||
};
|
||||
use serde_json::json;
|
||||
|
||||
|
|
@ -1358,7 +1354,7 @@ mod tests {
|
|||
automation: None,
|
||||
source_directory: None,
|
||||
labels: HashMap::new(),
|
||||
provenance: None,
|
||||
provenance: test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
git: None,
|
||||
|
|
@ -1439,7 +1435,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn legacy_run_created_projects_retried_from_none() {
|
||||
fn run_created_without_retried_from_projects_none() {
|
||||
let event = test_raw_event(
|
||||
1,
|
||||
"run.created",
|
||||
|
|
@ -1447,7 +1443,8 @@ mod tests {
|
|||
"settings": WorkflowSettings::default(),
|
||||
"graph": Graph::new("test"),
|
||||
"labels": {},
|
||||
"run_dir": "/tmp/run"
|
||||
"run_dir": "/tmp/run",
|
||||
"provenance": test_support::test_run_provenance()
|
||||
}),
|
||||
None,
|
||||
);
|
||||
|
|
@ -1475,7 +1472,8 @@ mod tests {
|
|||
"graph": Graph::new("test"),
|
||||
"automation": automation,
|
||||
"labels": {},
|
||||
"run_dir": "/tmp/run"
|
||||
"run_dir": "/tmp/run",
|
||||
"provenance": test_support::test_run_provenance()
|
||||
}),
|
||||
None,
|
||||
);
|
||||
|
|
@ -1498,7 +1496,8 @@ mod tests {
|
|||
"settings": WorkflowSettings::default(),
|
||||
"graph": Graph::new("test"),
|
||||
"labels": {},
|
||||
"run_dir": "/tmp/run"
|
||||
"run_dir": "/tmp/run",
|
||||
"provenance": test_support::test_run_provenance()
|
||||
}),
|
||||
None,
|
||||
)])
|
||||
|
|
@ -1520,7 +1519,8 @@ mod tests {
|
|||
"settings": WorkflowSettings::default(),
|
||||
"graph": Graph::new("test"),
|
||||
"labels": {},
|
||||
"run_dir": "/tmp/run"
|
||||
"run_dir": "/tmp/run",
|
||||
"provenance": test_support::test_run_provenance()
|
||||
}),
|
||||
None,
|
||||
)])
|
||||
|
|
@ -1597,7 +1597,8 @@ mod tests {
|
|||
"settings": WorkflowSettings::default(),
|
||||
"graph": Graph::new("test"),
|
||||
"labels": {},
|
||||
"run_dir": "/tmp/run"
|
||||
"run_dir": "/tmp/run",
|
||||
"provenance": test_support::test_run_provenance()
|
||||
}),
|
||||
None,
|
||||
),
|
||||
|
|
@ -1822,7 +1823,7 @@ mod tests {
|
|||
"repo_origin_url": null,
|
||||
"base_branch": null,
|
||||
"labels": {},
|
||||
"provenance": null,
|
||||
"provenance": test_support::test_run_provenance(),
|
||||
"manifest_blob": null,
|
||||
"definition_blob": null,
|
||||
"git": null,
|
||||
|
|
@ -2851,7 +2852,7 @@ mod tests {
|
|||
source_directory: Some("/tmp/repo".to_string()),
|
||||
git: None,
|
||||
labels: HashMap::new(),
|
||||
provenance: None,
|
||||
provenance: test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
fork_source_ref: None,
|
||||
|
|
@ -2877,7 +2878,7 @@ mod tests {
|
|||
source_directory: Some("/tmp/repo".to_string()),
|
||||
git: None,
|
||||
labels: HashMap::new(),
|
||||
provenance: None,
|
||||
provenance: test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
fork_source_ref: None,
|
||||
|
|
@ -2916,7 +2917,8 @@ mod tests {
|
|||
"attrs": { "goal": { "String": "Goal title" } }
|
||||
},
|
||||
"labels": {},
|
||||
"run_dir": "/tmp/run"
|
||||
"run_dir": "/tmp/run",
|
||||
"provenance": test_support::test_run_provenance()
|
||||
}),
|
||||
None,
|
||||
);
|
||||
|
|
@ -2930,7 +2932,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn legacy_run_created_without_title_infers_projection_title() {
|
||||
fn run_created_without_title_infers_projection_title() {
|
||||
let event = test_raw_event(
|
||||
1,
|
||||
"run.created",
|
||||
|
|
@ -2943,7 +2945,8 @@ mod tests {
|
|||
"attrs": { "goal": { "String": "## Plan: Legacy title\n\nDetails" } }
|
||||
},
|
||||
"labels": {},
|
||||
"run_dir": "/tmp/run"
|
||||
"run_dir": "/tmp/run",
|
||||
"provenance": test_support::test_run_provenance()
|
||||
}),
|
||||
None,
|
||||
);
|
||||
|
|
@ -2972,7 +2975,8 @@ mod tests {
|
|||
"attrs": { "goal": { "String": "Goal title" } }
|
||||
},
|
||||
"labels": {},
|
||||
"run_dir": "/tmp/run"
|
||||
"run_dir": "/tmp/run",
|
||||
"provenance": test_support::test_run_provenance()
|
||||
}),
|
||||
None,
|
||||
),
|
||||
|
|
@ -3016,7 +3020,8 @@ mod tests {
|
|||
"labels": {},
|
||||
"run_dir": "/tmp/run",
|
||||
"source_directory": "/tmp/run",
|
||||
"manifest_blob": manifest_blob
|
||||
"manifest_blob": manifest_blob,
|
||||
"provenance": test_support::test_run_provenance()
|
||||
}
|
||||
}))
|
||||
.unwrap(),
|
||||
|
|
|
|||
|
|
@ -472,7 +472,7 @@ mod tests {
|
|||
use chrono::{DateTime, Utc};
|
||||
use fabro_types::{
|
||||
AttrValue, FailureReason, Graph, RunControlAction, RunSpec, RunStatus, StageId,
|
||||
SuccessReason, WorkflowSettings,
|
||||
SuccessReason, WorkflowSettings, test_support,
|
||||
};
|
||||
use futures::TryStreamExt;
|
||||
use object_store::memory::InMemory;
|
||||
|
|
@ -542,7 +542,7 @@ mod tests {
|
|||
automation: None,
|
||||
source_directory: Some(format!("/tmp/{label}")),
|
||||
labels: std::collections::HashMap::from([("team".to_string(), "infra".to_string())]),
|
||||
provenance: None,
|
||||
provenance: test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
git: Some(fabro_types::GitContext {
|
||||
|
|
@ -601,6 +601,7 @@ mod tests {
|
|||
"run_dir": format!("/tmp/{label}"),
|
||||
"git": run_spec.git,
|
||||
"labels": run_spec.labels,
|
||||
"provenance": run_spec.provenance,
|
||||
}),
|
||||
))
|
||||
.await
|
||||
|
|
@ -627,6 +628,7 @@ mod tests {
|
|||
"git": run_spec.git,
|
||||
"labels": run_spec.labels,
|
||||
"parent_id": parent_id,
|
||||
"provenance": run_spec.provenance,
|
||||
}),
|
||||
))
|
||||
.await
|
||||
|
|
@ -1300,6 +1302,7 @@ mod tests {
|
|||
"run_dir": "/tmp/run-2",
|
||||
"git": run_spec["git"],
|
||||
"labels": run_spec["labels"],
|
||||
"provenance": run_spec["provenance"],
|
||||
},
|
||||
}))
|
||||
.unwrap(),
|
||||
|
|
|
|||
|
|
@ -667,7 +667,7 @@ mod tests {
|
|||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use fabro_types::{Graph, RunId, SessionId, StageId, WorkflowSettings};
|
||||
use fabro_types::{Graph, RunId, SessionId, StageId, WorkflowSettings, test_support};
|
||||
use object_store::memory::InMemory;
|
||||
use serde_json::json;
|
||||
|
||||
|
|
@ -723,6 +723,7 @@ mod tests {
|
|||
"settings": WorkflowSettings::default(),
|
||||
"graph": Graph::new("test"),
|
||||
"run_dir": "/tmp/test",
|
||||
"provenance": test_support::test_run_provenance(),
|
||||
},
|
||||
}),
|
||||
run_id,
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use fabro_types::{
|
|||
BilledModelUsage, BilledTokenCounts, Checkpoint, CheckpointRecord, InterviewQuestionRecord,
|
||||
QuestionType, RunDiff, RunSandbox, RunSandboxInstance, RunSandboxPlan, RunSandboxRuntime,
|
||||
RunStatus, SandboxProviderKind, StageCompletion, StageModelUsage, StageOutcome, StartRecord,
|
||||
WorkflowSettings, first_event_seq, fixtures,
|
||||
WorkflowSettings, first_event_seq, fixtures, test_support,
|
||||
};
|
||||
use serde_json::json;
|
||||
|
||||
|
|
@ -22,7 +22,7 @@ fn sample_run_spec() -> RunSpec {
|
|||
automation: None,
|
||||
source_directory: Some("/tmp/project".to_string()),
|
||||
labels: HashMap::from([("team".to_string(), "platform".to_string())]),
|
||||
provenance: None,
|
||||
provenance: test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
git: Some(fabro_types::GitContext {
|
||||
|
|
|
|||
|
|
@ -29,4 +29,5 @@ tokio.workspace = true
|
|||
toml.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
fabro-types = { path = "../fabro-types", features = ["test-support"] }
|
||||
tempfile = "3"
|
||||
|
|
|
|||
|
|
@ -307,7 +307,9 @@ fn format_tool_error(err: &anyhow::Error) -> String {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use chrono::{TimeZone, Utc};
|
||||
use fabro_types::{RunLifecycle, RunLinks, RunOrigin, RunStatus, RunTimestamps, WorkflowRef};
|
||||
use fabro_types::{
|
||||
RunLifecycle, RunLinks, RunOrigin, RunStatus, RunTimestamps, WorkflowRef, test_support,
|
||||
};
|
||||
|
||||
use super::*;
|
||||
|
||||
|
|
@ -413,7 +415,7 @@ mod tests {
|
|||
},
|
||||
automation: None,
|
||||
repository: None,
|
||||
created_by: None,
|
||||
created_by: test_support::test_principal(),
|
||||
origin: RunOrigin::default(),
|
||||
labels: HashMap::new(),
|
||||
lifecycle: RunLifecycle {
|
||||
|
|
|
|||
|
|
@ -508,7 +508,7 @@ mod tests {
|
|||
use fabro_api::types;
|
||||
use fabro_types::{
|
||||
EventEnvelope, Run, RunLifecycle, RunLinks, RunOrigin, RunProjection, RunStatus,
|
||||
RunTimestamps, WorkflowRef,
|
||||
RunTimestamps, WorkflowRef, test_support,
|
||||
};
|
||||
use schemars::SchemaGenerator;
|
||||
use serde_json::json;
|
||||
|
|
@ -902,7 +902,7 @@ mod tests {
|
|||
},
|
||||
automation: None,
|
||||
repository: None,
|
||||
created_by: None,
|
||||
created_by: test_support::test_principal(),
|
||||
origin: RunOrigin::default(),
|
||||
labels: HashMap::new(),
|
||||
lifecycle: RunLifecycle {
|
||||
|
|
|
|||
|
|
@ -453,7 +453,7 @@ mod tests {
|
|||
use chrono::{TimeZone, Utc};
|
||||
use fabro_types::{
|
||||
EventEnvelope, FailureReason, Run, RunId, RunLifecycle, RunLinks, RunOrigin, RunProjection,
|
||||
RunStatus, RunTimestamps, WorkflowRef,
|
||||
RunStatus, RunTimestamps, WorkflowRef, test_support,
|
||||
};
|
||||
use serde_json::json;
|
||||
|
||||
|
|
@ -690,7 +690,7 @@ mod tests {
|
|||
},
|
||||
automation: None,
|
||||
repository: None,
|
||||
created_by: None,
|
||||
created_by: test_support::test_principal(),
|
||||
origin: RunOrigin::default(),
|
||||
labels: HashMap::new(),
|
||||
lifecycle: RunLifecycle {
|
||||
|
|
|
|||
|
|
@ -293,7 +293,9 @@ mod tests {
|
|||
use std::collections::HashMap;
|
||||
|
||||
use chrono::{TimeZone, Utc};
|
||||
use fabro_types::{RunLifecycle, RunLinks, RunOrigin, RunStatus, RunTimestamps, WorkflowRef};
|
||||
use fabro_types::{
|
||||
RunLifecycle, RunLinks, RunOrigin, RunStatus, RunTimestamps, WorkflowRef, test_support,
|
||||
};
|
||||
|
||||
use super::*;
|
||||
|
||||
|
|
@ -444,7 +446,7 @@ mod tests {
|
|||
},
|
||||
automation: None,
|
||||
repository: None,
|
||||
created_by: None,
|
||||
created_by: test_support::test_principal(),
|
||||
origin: RunOrigin::default(),
|
||||
labels: HashMap::from([("group".to_string(), group.to_string())]),
|
||||
lifecycle: RunLifecycle {
|
||||
|
|
|
|||
|
|
@ -44,6 +44,8 @@ pub mod start;
|
|||
pub mod status;
|
||||
pub mod steering;
|
||||
pub mod system_integrations;
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub mod test_support;
|
||||
pub mod timing;
|
||||
pub mod todo;
|
||||
pub mod transcript;
|
||||
|
|
|
|||
|
|
@ -24,14 +24,13 @@ pub struct RunClientProvenance {
|
|||
pub version: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct RunProvenance {
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub server: Option<RunServerProvenance>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub client: Option<RunClientProvenance>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub subject: Option<Principal>,
|
||||
pub subject: Principal,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
|
|
@ -93,8 +92,7 @@ pub struct RunSpec {
|
|||
pub source_directory: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "HashMap::is_empty")]
|
||||
pub labels: HashMap<String, String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub provenance: Option<RunProvenance>,
|
||||
pub provenance: RunProvenance,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub manifest_blob: Option<RunBlobId>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
|
|
|
|||
|
|
@ -933,7 +933,7 @@ mod tests {
|
|||
use super::*;
|
||||
use crate::{
|
||||
AuthMethod, Edge, Graph, IdpIdentity, Node, PendingReason, RunBlobId, WorkflowSettings,
|
||||
fixtures,
|
||||
fixtures, test_support,
|
||||
};
|
||||
|
||||
fn user_principal(login: &str) -> Principal {
|
||||
|
|
@ -1017,7 +1017,8 @@ mod tests {
|
|||
"graph": graph,
|
||||
"labels": {},
|
||||
"run_dir": "/tmp/run",
|
||||
"source_directory": "/tmp/run"
|
||||
"source_directory": "/tmp/run",
|
||||
"provenance": test_support::test_run_provenance()
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -1038,7 +1039,8 @@ mod tests {
|
|||
"labels": {},
|
||||
"run_dir": "/tmp/run",
|
||||
"source_directory": "/tmp/run",
|
||||
"manifest_blob": RunBlobId::new(br#"{"version":1}"#).to_string()
|
||||
"manifest_blob": RunBlobId::new(br#"{"version":1}"#).to_string(),
|
||||
"provenance": test_support::test_run_provenance()
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -30,8 +30,7 @@ pub struct RunCreatedProps {
|
|||
pub automation: Option<AutomationRef>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub db_prefix: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub provenance: Option<RunProvenance>,
|
||||
pub provenance: RunProvenance,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub manifest_blob: Option<RunBlobId>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
|
|
|
|||
|
|
@ -681,7 +681,7 @@ mod title_tests {
|
|||
|
||||
use chrono::Utc;
|
||||
|
||||
use crate::{AttrValue, Graph, RunId, RunProjection, RunSpec, WorkflowSettings};
|
||||
use crate::{AttrValue, Graph, RunId, RunProjection, RunSpec, WorkflowSettings, test_support};
|
||||
|
||||
fn projection_with_goal(goal: Option<&str>) -> RunProjection {
|
||||
let mut graph = Graph::new("test");
|
||||
|
|
@ -700,7 +700,7 @@ mod title_tests {
|
|||
automation: None,
|
||||
source_directory: None,
|
||||
labels: HashMap::new(),
|
||||
provenance: None,
|
||||
provenance: test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
git: None,
|
||||
|
|
@ -752,7 +752,7 @@ mod iter_stages_tests {
|
|||
use serde_json::json;
|
||||
|
||||
use super::RunProjection;
|
||||
use crate::{Graph, RunId, RunSpec, StageProjection, WorkflowSettings};
|
||||
use crate::{Graph, RunId, RunSpec, StageProjection, WorkflowSettings, test_support};
|
||||
|
||||
fn seq(n: u32) -> NonZeroU32 {
|
||||
NonZeroU32::new(n).unwrap()
|
||||
|
|
@ -770,7 +770,7 @@ mod iter_stages_tests {
|
|||
automation: None,
|
||||
source_directory: None,
|
||||
labels: HashMap::default(),
|
||||
provenance: None,
|
||||
provenance: test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
git: None,
|
||||
|
|
|
|||
|
|
@ -52,8 +52,7 @@ pub struct Run {
|
|||
pub automation: Option<AutomationRef>,
|
||||
#[serde(default)]
|
||||
pub repository: Option<RepositoryRef>,
|
||||
#[serde(default)]
|
||||
pub created_by: Option<Principal>,
|
||||
pub created_by: Principal,
|
||||
pub origin: RunOrigin,
|
||||
pub labels: HashMap<String, String>,
|
||||
pub lifecycle: RunLifecycle,
|
||||
|
|
|
|||
19
lib/crates/fabro-types/src/test_support.rs
Normal file
19
lib/crates/fabro-types/src/test_support.rs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
use crate::{AuthMethod, IdpIdentity, Principal, RunProvenance};
|
||||
|
||||
#[must_use]
|
||||
pub fn test_principal() -> Principal {
|
||||
Principal::user(
|
||||
IdpIdentity::new("fabro:test", "test-user").expect("test identity should be valid"),
|
||||
"test".to_string(),
|
||||
AuthMethod::DevToken,
|
||||
)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn test_run_provenance() -> RunProvenance {
|
||||
RunProvenance {
|
||||
server: None,
|
||||
client: None,
|
||||
subject: test_principal(),
|
||||
}
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@ use fabro_types::run_event::run::{RunCreatedProps, RunParentLinkedProps, RunPare
|
|||
use fabro_types::run_event::{RunSessionTurnFailedCode, RunSessionTurnFailedProps};
|
||||
use fabro_types::settings::InterpString;
|
||||
use fabro_types::settings::run::RunGoal;
|
||||
use fabro_types::{AutomationRef, EventBody, TurnId, WorkflowSettings, fixtures};
|
||||
use fabro_types::{AutomationRef, EventBody, TurnId, WorkflowSettings, fixtures, test_support};
|
||||
|
||||
fn templated_settings() -> WorkflowSettings {
|
||||
let mut settings = WorkflowSettings::default();
|
||||
|
|
@ -32,7 +32,7 @@ fn run_created_props_round_trip_templated_settings() {
|
|||
trigger_id: Some("schedule_1".to_string()),
|
||||
}),
|
||||
db_prefix: Some("run_".to_string()),
|
||||
provenance: None,
|
||||
provenance: test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
git: Some(GitContext {
|
||||
origin_url: "https://github.com/fabro-sh/fabro.git".to_string(),
|
||||
|
|
@ -97,7 +97,7 @@ fn run_created_props_omits_web_url_when_absent() {
|
|||
workflow_slug: None,
|
||||
automation: None,
|
||||
db_prefix: None,
|
||||
provenance: None,
|
||||
provenance: test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
git: None,
|
||||
fork_source_ref: None,
|
||||
|
|
@ -128,21 +128,36 @@ fn run_created_props_omits_web_url_when_absent() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn run_created_props_defaults_additive_fields_for_legacy_events() {
|
||||
fn run_created_props_defaults_optional_additive_fields_when_absent() {
|
||||
let json = serde_json::json!({
|
||||
"title": null,
|
||||
"settings": WorkflowSettings::default(),
|
||||
"graph": Graph::new("ship"),
|
||||
"labels": {},
|
||||
"run_dir": "/tmp/run"
|
||||
"run_dir": "/tmp/run",
|
||||
"provenance": test_support::test_run_provenance(),
|
||||
});
|
||||
|
||||
let props: RunCreatedProps =
|
||||
serde_json::from_value(json).expect("legacy props should deserialize");
|
||||
let props: RunCreatedProps = serde_json::from_value(json).expect("props should deserialize");
|
||||
assert_eq!(props.retried_from, None);
|
||||
assert_eq!(props.automation, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn run_created_props_requires_total_provenance() {
|
||||
let mut missing = serde_json::json!({
|
||||
"title": null,
|
||||
"settings": WorkflowSettings::default(),
|
||||
"graph": Graph::new("ship"),
|
||||
"labels": {},
|
||||
"run_dir": "/tmp/run",
|
||||
});
|
||||
assert!(serde_json::from_value::<RunCreatedProps>(missing.clone()).is_err());
|
||||
|
||||
missing["provenance"] = serde_json::Value::Null;
|
||||
assert!(serde_json::from_value::<RunCreatedProps>(missing).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn run_parent_events_round_trip_parent_ids() {
|
||||
let linked = EventBody::RunParentLinked(RunParentLinkedProps {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use std::collections::HashMap;
|
|||
use fabro_types::graph::Graph;
|
||||
use fabro_types::run::{DirtyStatus, GitContext, PreRunPushOutcome, RunSpec};
|
||||
use fabro_types::settings::{ProjectNamespace, WorkflowNamespace};
|
||||
use fabro_types::{WorkflowSettings, fixtures};
|
||||
use fabro_types::{WorkflowSettings, fixtures, test_support};
|
||||
|
||||
fn sample_run_spec() -> RunSpec {
|
||||
let settings = WorkflowSettings {
|
||||
|
|
@ -27,7 +27,7 @@ fn sample_run_spec() -> RunSpec {
|
|||
automation: None,
|
||||
source_directory: Some("/Users/client/project".to_string()),
|
||||
labels: HashMap::from([("team".to_string(), "platform".to_string())]),
|
||||
provenance: None,
|
||||
provenance: test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
git: Some(GitContext {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use fabro_types::graph::Graph;
|
|||
use fabro_types::run::{DirtyStatus, ForkSourceRef, GitContext, PreRunPushOutcome, RunSpec};
|
||||
use fabro_types::settings::InterpString;
|
||||
use fabro_types::settings::run::RunGoal;
|
||||
use fabro_types::{AutomationRef, WorkflowSettings, fixtures};
|
||||
use fabro_types::{AutomationRef, RunProvenance, WorkflowSettings, fixtures, test_support};
|
||||
|
||||
fn templated_settings() -> WorkflowSettings {
|
||||
let mut settings = WorkflowSettings::default();
|
||||
|
|
@ -27,7 +27,7 @@ fn run_spec_round_trips_templated_settings() {
|
|||
}),
|
||||
source_directory: Some("/Users/client/project".to_string()),
|
||||
labels: HashMap::from([("team".to_string(), "platform".to_string())]),
|
||||
provenance: None,
|
||||
provenance: test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
git: Some(GitContext {
|
||||
|
|
@ -75,15 +75,47 @@ fn run_spec_round_trips_templated_settings() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn run_spec_defaults_automation_for_legacy_specs() {
|
||||
fn run_spec_defaults_automation_when_absent() {
|
||||
let provenance = test_support::test_run_provenance();
|
||||
let json = serde_json::json!({
|
||||
"run_id": fixtures::RUN_1,
|
||||
"settings": WorkflowSettings::default(),
|
||||
"graph": Graph::new("ship"),
|
||||
"labels": {}
|
||||
"labels": {},
|
||||
"provenance": provenance,
|
||||
});
|
||||
|
||||
let record: RunSpec = serde_json::from_value(json).expect("legacy spec should deserialize");
|
||||
let record: RunSpec = serde_json::from_value(json).expect("spec should deserialize");
|
||||
|
||||
assert_eq!(record.automation, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn run_spec_requires_total_provenance() {
|
||||
let mut missing = serde_json::json!({
|
||||
"run_id": fixtures::RUN_1,
|
||||
"settings": WorkflowSettings::default(),
|
||||
"graph": Graph::new("ship"),
|
||||
"labels": {},
|
||||
});
|
||||
assert!(serde_json::from_value::<RunSpec>(missing.clone()).is_err());
|
||||
|
||||
missing["provenance"] = serde_json::Value::Null;
|
||||
assert!(serde_json::from_value::<RunSpec>(missing).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn run_provenance_requires_total_subject() {
|
||||
let mut provenance =
|
||||
serde_json::to_value(test_support::test_run_provenance()).expect("provenance serializes");
|
||||
provenance
|
||||
.as_object_mut()
|
||||
.expect("provenance is an object")
|
||||
.remove("subject");
|
||||
assert!(serde_json::from_value::<RunProvenance>(provenance).is_err());
|
||||
|
||||
let null_subject = serde_json::json!({
|
||||
"subject": null,
|
||||
});
|
||||
assert!(serde_json::from_value::<RunProvenance>(null_subject).is_err());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -353,7 +353,7 @@ mod tests {
|
|||
automation: None,
|
||||
source_directory: None,
|
||||
labels: HashMap::new(),
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
git: None,
|
||||
|
|
|
|||
|
|
@ -2339,7 +2339,7 @@ mod tests {
|
|||
let provenance = RunProvenance {
|
||||
server: None,
|
||||
client: None,
|
||||
subject: Some(user_principal("alice")),
|
||||
subject: user_principal("alice"),
|
||||
};
|
||||
let automation = AutomationRef {
|
||||
id: "nightly".to_string(),
|
||||
|
|
@ -2348,25 +2348,25 @@ mod tests {
|
|||
};
|
||||
|
||||
let stored = to_run_event(&fixtures::RUN_1, &Event::RunCreated {
|
||||
run_id: fixtures::RUN_1,
|
||||
title: None,
|
||||
settings: serde_json::to_value(WorkflowSettings::default()).unwrap(),
|
||||
graph: serde_json::to_value(Graph::new("test")).unwrap(),
|
||||
workflow_source: None,
|
||||
workflow_config: None,
|
||||
labels: BTreeMap::default(),
|
||||
run_dir: "/tmp/run".to_string(),
|
||||
run_id: fixtures::RUN_1,
|
||||
title: None,
|
||||
settings: serde_json::to_value(WorkflowSettings::default()).unwrap(),
|
||||
graph: serde_json::to_value(Graph::new("test")).unwrap(),
|
||||
workflow_source: None,
|
||||
workflow_config: None,
|
||||
labels: BTreeMap::default(),
|
||||
run_dir: "/tmp/run".to_string(),
|
||||
source_directory: Some("/tmp/run".to_string()),
|
||||
workflow_slug: None,
|
||||
automation: Some(automation.clone()),
|
||||
db_prefix: None,
|
||||
provenance: Some(provenance),
|
||||
manifest_blob: None,
|
||||
git: None,
|
||||
fork_source_ref: None,
|
||||
retried_from: None,
|
||||
parent_id: None,
|
||||
web_url: None,
|
||||
workflow_slug: None,
|
||||
automation: Some(automation.clone()),
|
||||
db_prefix: None,
|
||||
provenance,
|
||||
manifest_blob: None,
|
||||
git: None,
|
||||
fork_source_ref: None,
|
||||
retried_from: None,
|
||||
parent_id: None,
|
||||
web_url: None,
|
||||
});
|
||||
let actor = stored.actor.as_ref().expect("actor set");
|
||||
assert_eq!(actor, &user_principal("alice"));
|
||||
|
|
|
|||
|
|
@ -41,8 +41,7 @@ pub enum Event {
|
|||
automation: Option<AutomationRef>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
db_prefix: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
provenance: Option<RunProvenance>,
|
||||
provenance: RunProvenance,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
manifest_blob: Option<RunBlobId>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
|
|
|
|||
|
|
@ -244,7 +244,7 @@ mod tests {
|
|||
workflow_slug: None,
|
||||
automation: None,
|
||||
db_prefix: None,
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
git: None,
|
||||
fork_source_ref: None,
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ pub(super) fn stored_event_fields(event: &Event, scope: Option<&StageScope>) ->
|
|||
fn stored_event_fields_for_variant(event: &Event) -> StoredEventFields {
|
||||
match event {
|
||||
Event::RunCreated { provenance, .. } => StoredEventFields {
|
||||
actor: provenance.as_ref().and_then(|p| p.subject.clone()),
|
||||
actor: Some(provenance.subject.clone()),
|
||||
..StoredEventFields::default()
|
||||
},
|
||||
Event::RunCancelRequested { actor }
|
||||
|
|
|
|||
|
|
@ -469,7 +469,7 @@ mod tests {
|
|||
workflow_slug: None,
|
||||
automation: None,
|
||||
db_prefix: None,
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
git: None,
|
||||
fork_source_ref: None,
|
||||
|
|
|
|||
|
|
@ -484,7 +484,7 @@ mod tests {
|
|||
workflow_slug: None,
|
||||
automation: None,
|
||||
db_prefix: None,
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
git: None,
|
||||
fork_source_ref: None,
|
||||
|
|
|
|||
|
|
@ -256,7 +256,7 @@ mod tests {
|
|||
automation: None,
|
||||
source_directory: None,
|
||||
labels: std::collections::HashMap::default(),
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
git: None,
|
||||
|
|
@ -357,7 +357,7 @@ mod tests {
|
|||
workflow_slug: None,
|
||||
automation: None,
|
||||
db_prefix: None,
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
git: None,
|
||||
fork_source_ref: None,
|
||||
|
|
|
|||
|
|
@ -2133,7 +2133,7 @@ reasoning = false
|
|||
},
|
||||
automation: None,
|
||||
repository: None,
|
||||
created_by: None,
|
||||
created_by: fabro_types::test_support::test_principal(),
|
||||
origin: RunOrigin::default(),
|
||||
labels: HashMap::new(),
|
||||
lifecycle: RunLifecycle {
|
||||
|
|
|
|||
|
|
@ -728,7 +728,7 @@ mod tests {
|
|||
workflow_slug: None,
|
||||
automation: None,
|
||||
db_prefix: None,
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
git: None,
|
||||
fork_source_ref: None,
|
||||
|
|
|
|||
|
|
@ -283,7 +283,7 @@ mod tests {
|
|||
workflow_slug: None,
|
||||
automation: None,
|
||||
db_prefix: None,
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
git: None,
|
||||
fork_source_ref: None,
|
||||
|
|
|
|||
|
|
@ -736,7 +736,7 @@ mod tests {
|
|||
workflow_slug: Some("metadata".to_string()),
|
||||
automation: None,
|
||||
db_prefix: None,
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
git: None,
|
||||
fork_source_ref: None,
|
||||
|
|
|
|||
|
|
@ -226,7 +226,7 @@ mod tests {
|
|||
workflow_slug: None,
|
||||
automation: None,
|
||||
db_prefix: None,
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
git: None,
|
||||
fork_source_ref: None,
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ pub struct CreateRunInput {
|
|||
pub git: Option<GitContext>,
|
||||
pub fork_source_ref: Option<ForkSourceRef>,
|
||||
pub parent_id: Option<RunId>,
|
||||
pub provenance: Option<RunProvenance>,
|
||||
pub provenance: RunProvenance,
|
||||
pub configured_providers: Vec<ProviderId>,
|
||||
/// Public URL where this run can be viewed in the web UI, when the server
|
||||
/// has the web UI enabled. Recorded on the `run.created` event so attach
|
||||
|
|
@ -72,7 +72,7 @@ struct PersistCreateOptions {
|
|||
automation: Option<AutomationRef>,
|
||||
git: Option<GitContext>,
|
||||
fork_source_ref: Option<ForkSourceRef>,
|
||||
provenance: Option<RunProvenance>,
|
||||
provenance: RunProvenance,
|
||||
configured_providers: Vec<ProviderId>,
|
||||
catalog: Arc<Catalog>,
|
||||
}
|
||||
|
|
@ -1115,7 +1115,7 @@ mod tests {
|
|||
git: None,
|
||||
fork_source_ref: None,
|
||||
parent_id: None,
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
configured_providers: Vec::new(),
|
||||
web_url: None,
|
||||
},
|
||||
|
|
@ -1183,7 +1183,7 @@ mod tests {
|
|||
}),
|
||||
fork_source_ref: None,
|
||||
parent_id: None,
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
configured_providers: Vec::new(),
|
||||
web_url: None,
|
||||
},
|
||||
|
|
@ -1295,7 +1295,7 @@ mod tests {
|
|||
git: None,
|
||||
fork_source_ref: None,
|
||||
parent_id: None,
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
configured_providers: Vec::new(),
|
||||
web_url: None,
|
||||
},
|
||||
|
|
@ -1341,7 +1341,7 @@ mod tests {
|
|||
}),
|
||||
fork_source_ref: None,
|
||||
parent_id: None,
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
configured_providers: Vec::new(),
|
||||
web_url: None,
|
||||
},
|
||||
|
|
@ -1414,7 +1414,7 @@ mod tests {
|
|||
git: None,
|
||||
fork_source_ref: None,
|
||||
parent_id: None,
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
configured_providers: Vec::new(),
|
||||
web_url: None,
|
||||
},
|
||||
|
|
@ -1467,7 +1467,7 @@ mod tests {
|
|||
git: None,
|
||||
fork_source_ref: None,
|
||||
parent_id: None,
|
||||
provenance: Some(fabro_types::RunProvenance {
|
||||
provenance: fabro_types::RunProvenance {
|
||||
server: Some(fabro_types::RunServerProvenance {
|
||||
version: "0.9.0".to_string(),
|
||||
}),
|
||||
|
|
@ -1476,12 +1476,12 @@ mod tests {
|
|||
name: Some("fabro-cli".to_string()),
|
||||
version: Some("0.9.0".to_string()),
|
||||
}),
|
||||
subject: Some(fabro_types::Principal::user(
|
||||
subject: fabro_types::Principal::user(
|
||||
fabro_types::IdpIdentity::new("https://github.com", "12345").unwrap(),
|
||||
"octocat".to_string(),
|
||||
fabro_types::AuthMethod::Github,
|
||||
)),
|
||||
}),
|
||||
),
|
||||
},
|
||||
configured_providers: Vec::new(),
|
||||
web_url: None,
|
||||
},
|
||||
|
|
@ -1494,7 +1494,7 @@ mod tests {
|
|||
let run_store = store.open_run_reader(&created.run_id).await.unwrap();
|
||||
let state = run_store.state().await.unwrap();
|
||||
let run = state.spec;
|
||||
let provenance = run.provenance.expect("provenance should be projected");
|
||||
let provenance = run.provenance;
|
||||
|
||||
assert_eq!(provenance.server.unwrap().version, "0.9.0");
|
||||
assert_eq!(
|
||||
|
|
@ -1502,7 +1502,7 @@ mod tests {
|
|||
Some("fabro-cli")
|
||||
);
|
||||
assert_eq!(
|
||||
provenance.subject.unwrap(),
|
||||
provenance.subject,
|
||||
fabro_types::Principal::user(
|
||||
fabro_types::IdpIdentity::new("https://github.com", "12345").unwrap(),
|
||||
"octocat".to_string(),
|
||||
|
|
|
|||
|
|
@ -383,7 +383,7 @@ mod tests {
|
|||
workflow_slug: Some("fork-source".to_string()),
|
||||
automation: None,
|
||||
db_prefix: None,
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
git: Some(fabro_types::GitContext {
|
||||
origin_url: "https://github.com/example/repo.git".to_string(),
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ use crate::event::{self, Event};
|
|||
pub struct RetryRunInput {
|
||||
pub source_run_id: RunId,
|
||||
pub new_run_id: RunId,
|
||||
pub provenance: Option<RunProvenance>,
|
||||
pub provenance: RunProvenance,
|
||||
pub web_url: Option<String>,
|
||||
}
|
||||
|
||||
|
|
@ -152,7 +152,7 @@ mod tests {
|
|||
version: "test".to_string(),
|
||||
}),
|
||||
client: None,
|
||||
subject: Some(actor(login)),
|
||||
subject: actor(login),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -191,7 +191,7 @@ mod tests {
|
|||
workflow_slug: Some("retry-source".to_string()),
|
||||
automation: None,
|
||||
db_prefix: None,
|
||||
provenance: Some(provenance("source-user")),
|
||||
provenance: provenance("source-user"),
|
||||
manifest_blob,
|
||||
git: Some(git_context()),
|
||||
fork_source_ref,
|
||||
|
|
@ -368,7 +368,7 @@ mod tests {
|
|||
let outcome = retry_run(&store, &RetryRunInput {
|
||||
source_run_id,
|
||||
new_run_id: RunId::new(),
|
||||
provenance: Some(provenance("retry-user")),
|
||||
provenance: provenance("retry-user"),
|
||||
web_url: Some("http://localhost:3000/runs/retry".to_string()),
|
||||
})
|
||||
.await
|
||||
|
|
@ -402,14 +402,7 @@ mod tests {
|
|||
assert_eq!(retry_state.spec.manifest_blob, manifest_blob);
|
||||
assert_eq!(retry_state.spec.definition_blob, definition_blob);
|
||||
assert_eq!(retry_state.spec.fork_source_ref, Some(fork_source_ref));
|
||||
assert_eq!(
|
||||
retry_state
|
||||
.spec
|
||||
.provenance
|
||||
.as_ref()
|
||||
.and_then(|provenance| provenance.subject.as_ref()),
|
||||
Some(&actor("retry-user"))
|
||||
);
|
||||
assert_eq!(retry_state.spec.provenance.subject, actor("retry-user"));
|
||||
assert_eq!(
|
||||
retry_state.web_url.as_deref(),
|
||||
Some("http://localhost:3000/runs/retry")
|
||||
|
|
@ -463,7 +456,7 @@ mod tests {
|
|||
let outcome = retry_run(&store, &RetryRunInput {
|
||||
source_run_id,
|
||||
new_run_id: RunId::new(),
|
||||
provenance: Some(provenance("retry-user")),
|
||||
provenance: provenance("retry-user"),
|
||||
web_url: None,
|
||||
})
|
||||
.await
|
||||
|
|
@ -517,7 +510,7 @@ mod tests {
|
|||
let err = retry_run(&store, &RetryRunInput {
|
||||
source_run_id: run_id,
|
||||
new_run_id: RunId::new(),
|
||||
provenance: None,
|
||||
provenance: provenance("retry-user"),
|
||||
web_url: None,
|
||||
})
|
||||
.await
|
||||
|
|
@ -535,7 +528,7 @@ mod tests {
|
|||
let err = retry_run(&store, &RetryRunInput {
|
||||
source_run_id: fixtures::RUN_1,
|
||||
new_run_id: RunId::new(),
|
||||
provenance: None,
|
||||
provenance: provenance("retry-user"),
|
||||
web_url: None,
|
||||
})
|
||||
.await
|
||||
|
|
|
|||
|
|
@ -1438,7 +1438,7 @@ reasoning = false
|
|||
git: None,
|
||||
fork_source_ref: None,
|
||||
parent_id: None,
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
configured_providers: Vec::new(),
|
||||
web_url: None,
|
||||
},
|
||||
|
|
@ -1860,7 +1860,7 @@ reasoning = false
|
|||
git: None,
|
||||
fork_source_ref: None,
|
||||
parent_id: None,
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
configured_providers: Vec::new(),
|
||||
web_url: None,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -248,7 +248,7 @@ mod tests {
|
|||
automation: None,
|
||||
source_directory: None,
|
||||
labels: HashMap::new(),
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
git: None,
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ fn persisted_workflow(graph: Graph, source: String, run_dir: &Path, run_id: RunI
|
|||
push_outcome: fabro_types::PreRunPushOutcome::NotAttempted,
|
||||
}),
|
||||
labels: HashMap::new(),
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
fork_source_ref: None,
|
||||
|
|
@ -208,7 +208,7 @@ async fn seed_created_and_starting(
|
|||
workflow_slug: run_options.workflow_slug.clone(),
|
||||
automation: None,
|
||||
db_prefix: None,
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
git: run_options.pre_run_git.clone(),
|
||||
fork_source_ref: run_options.fork_source_ref.clone(),
|
||||
|
|
|
|||
|
|
@ -739,7 +739,7 @@ mod tests {
|
|||
workflow_slug: Some("metadata".to_string()),
|
||||
automation: None,
|
||||
db_prefix: None,
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
git: None,
|
||||
fork_source_ref: None,
|
||||
|
|
@ -856,7 +856,7 @@ mod tests {
|
|||
automation: None,
|
||||
source_directory: None,
|
||||
labels: HashMap::new(),
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
git: None,
|
||||
|
|
|
|||
|
|
@ -773,7 +773,7 @@ mod tests {
|
|||
push_outcome: fabro_types::PreRunPushOutcome::NotAttempted,
|
||||
}),
|
||||
labels: HashMap::new(),
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
fork_source_ref: None,
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ mod tests {
|
|||
("env".to_string(), "test".to_string()),
|
||||
("team".to_string(), "workflow".to_string()),
|
||||
]),
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
fork_source_ref: None,
|
||||
|
|
|
|||
|
|
@ -823,7 +823,7 @@ mod tests {
|
|||
automation: None,
|
||||
source_directory: None,
|
||||
labels: HashMap::new(),
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
git: None,
|
||||
|
|
@ -1148,7 +1148,7 @@ mod tests {
|
|||
push_outcome: fabro_types::PreRunPushOutcome::NotAttempted,
|
||||
}),
|
||||
labels: HashMap::new(),
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
fork_source_ref: None,
|
||||
|
|
@ -1219,7 +1219,7 @@ mod tests {
|
|||
push_outcome: fabro_types::PreRunPushOutcome::NotAttempted,
|
||||
}),
|
||||
labels: HashMap::new(),
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
fork_source_ref: None,
|
||||
|
|
@ -1575,7 +1575,7 @@ mod tests {
|
|||
source_directory: Some(tmp.path().display().to_string()),
|
||||
git: None,
|
||||
labels: std::collections::HashMap::new(),
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
fork_source_ref: None,
|
||||
|
|
@ -1704,7 +1704,7 @@ mod tests {
|
|||
source_directory: Some("/tmp/project".to_string()),
|
||||
git: None,
|
||||
labels: HashMap::new(),
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
fork_source_ref: None,
|
||||
|
|
@ -1722,7 +1722,7 @@ mod tests {
|
|||
workflow_slug: run_spec.workflow_slug.clone(),
|
||||
automation: None,
|
||||
db_prefix: None,
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
git: None,
|
||||
fork_source_ref: None,
|
||||
|
|
@ -1875,7 +1875,7 @@ mod tests {
|
|||
source_directory: None,
|
||||
git: None,
|
||||
labels: HashMap::new(),
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
fork_source_ref: None,
|
||||
|
|
@ -1893,7 +1893,7 @@ mod tests {
|
|||
workflow_slug: None,
|
||||
automation: None,
|
||||
db_prefix: None,
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
git: None,
|
||||
fork_source_ref: None,
|
||||
|
|
|
|||
|
|
@ -491,7 +491,7 @@ mod tests {
|
|||
push_outcome: fabro_types::PreRunPushOutcome::NotAttempted,
|
||||
}),
|
||||
labels: HashMap::new(),
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
fork_source_ref: None,
|
||||
|
|
|
|||
|
|
@ -639,7 +639,7 @@ mod tests {
|
|||
push_outcome: PreRunPushOutcome::NotAttempted,
|
||||
}),
|
||||
labels: HashMap::new(),
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
fork_source_ref: None,
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ mod tests {
|
|||
source_directory: Some("/tmp/test".to_string()),
|
||||
git: None,
|
||||
labels: HashMap::new(),
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
fork_source_ref: None,
|
||||
|
|
@ -170,7 +170,7 @@ mod tests {
|
|||
workflow_slug: Some("test".to_string()),
|
||||
automation: None,
|
||||
db_prefix: None,
|
||||
provenance: None,
|
||||
provenance: fabro_types::test_support::test_run_provenance(),
|
||||
manifest_blob: None,
|
||||
git: None,
|
||||
fork_source_ref: None,
|
||||
|
|
|
|||
|
|
@ -175,7 +175,13 @@ async fn initialized(
|
|||
workflow_slug: run_options.workflow_slug.clone(),
|
||||
automation: None,
|
||||
db_prefix: None,
|
||||
provenance: None,
|
||||
provenance: fabro_types::RunProvenance {
|
||||
server: None,
|
||||
client: None,
|
||||
subject: fabro_types::Principal::System {
|
||||
system_kind: fabro_types::SystemActorKind::Engine,
|
||||
},
|
||||
},
|
||||
manifest_blob: None,
|
||||
git: run_options.pre_run_git.clone(),
|
||||
fork_source_ref: run_options.fork_source_ref.clone(),
|
||||
|
|
|
|||
|
|
@ -26,5 +26,5 @@ import type { RunServerProvenance } from './run-server-provenance';
|
|||
export interface RunProvenance {
|
||||
'server'?: RunServerProvenance | null;
|
||||
'client'?: RunClientProvenance | null;
|
||||
'subject'?: Principal | null;
|
||||
'subject': Principal;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ export interface RunSpec {
|
|||
'automation'?: AutomationRef | null;
|
||||
'source_directory'?: string | null;
|
||||
'labels'?: { [key: string]: string; };
|
||||
'provenance'?: RunProvenance | null;
|
||||
'provenance': RunProvenance;
|
||||
'manifest_blob'?: string | null;
|
||||
'definition_blob'?: string | null;
|
||||
'git'?: GitContext | null;
|
||||
|
|
|
|||
2
lib/packages/fabro-api-client/src/models/run.ts
generated
2
lib/packages/fabro-api-client/src/models/run.ts
generated
|
|
@ -83,7 +83,7 @@ export interface Run {
|
|||
'workflow': WorkflowRef;
|
||||
'automation': AutomationRef | null;
|
||||
'repository': RepositoryRef | null;
|
||||
'created_by': Principal | null;
|
||||
'created_by': Principal;
|
||||
'origin': RunOrigin;
|
||||
'labels': { [key: string]: string; };
|
||||
'lifecycle': RunLifecycle;
|
||||
|
|
|
|||
|
|
@ -40,8 +40,8 @@ export function systemKind(principal: PrincipalSystem): string {
|
|||
}
|
||||
}
|
||||
|
||||
type Provenance = NonNullable<RunSpec["provenance"]>;
|
||||
type Subject = NonNullable<Provenance["subject"]>;
|
||||
type Provenance = RunSpec["provenance"];
|
||||
type Subject = Provenance["subject"];
|
||||
|
||||
type SubjectIsNotAny = AssertFalse<IsAny<Subject>>;
|
||||
type SubjectExtendsPrincipal = AssertExtends<Subject, Principal>;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue