Make run provenance and creator total

This commit is contained in:
Fabro 2026-06-03 17:37:52 +00:00
parent 26fdc23a9f
commit 5fea2c5ad9
87 changed files with 405 additions and 240 deletions

View file

@ -6,6 +6,7 @@ import {
RunSummaryPanelView,
type RunSummaryPanelViewProps,
} from "./run-summary-panel";
import { TEST_PRINCIPAL } from "../lib/test-fixtures";
function instanceText(instance: TestRenderer.ReactTestInstance): string {
const parts: string[] = [];
@ -53,7 +54,7 @@ function cellAfterLabel(
function makeRun(overrides: Record<string, any> = {}) {
return {
id: "run_1",
created_by: null,
created_by: TEST_PRINCIPAL,
diff: null,
billing: null,
...overrides,
@ -73,7 +74,7 @@ describe("RunSummaryPanelView", () => {
test("shows unavailable copy for missing run fields after load", () => {
const tree = render({ run: makeRun() });
expect(instanceText(cellAfterLabel(tree, "Created by"))).toBe(EMPTY_VALUE);
expect(instanceText(cellAfterLabel(tree, "Created by"))).toBe("Ttest");
expect(instanceText(cellAfterLabel(tree, "Changes"))).toBe(EMPTY_VALUE);
expect(instanceText(cellAfterLabel(tree, "Cost"))).toBe(EMPTY_VALUE);
});

View file

@ -116,7 +116,7 @@ export function RunSummaryPanelView({
artifactsCount,
artifactsLoading,
}: RunSummaryPanelViewProps) {
const created = run?.created_by ? principalDisplay(run.created_by) : null;
const created = run ? principalDisplay(run.created_by) : null;
const diff = run?.diff ?? null;
const cost = formatUsdMicros(run?.billing?.total_usd_micros);
const sandboxKind = sandboxLifecycleKind(run?.sandbox);
@ -133,7 +133,7 @@ export function RunSummaryPanelView({
<span className={VALUE_CLASS}>{created.label}</span>
</div>
) : (
<EmptyValue />
<EmptyValue />
)}
</Cell>

View file

@ -36,6 +36,7 @@ export function RunTableRow({
const lifecycleLabel = listLifecycleStatusLabel(run);
const statusDisplay = columnStatusDisplay[run.status];
const show = (col: ToggleableColumn) => !hiddenColumns.has(col);
const creatorDisplay = principalDisplay(run.createdBy);
return (
<tr className={`group relative border-b border-line transition-colors last:border-b-0 ${selected ? "bg-overlay/30" : "hover:bg-overlay/40"}`}>
@ -54,14 +55,9 @@ 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}>
<span aria-label={`Created by ${display.label}`}>{display.glyph}</span>
</Tooltip>
);
})()}
<Tooltip label={creatorDisplay.label}>
<span aria-label={`Created by ${creatorDisplay.label}`}>{creatorDisplay.glyph}</span>
</Tooltip>
</td>
)}
{show("repo") && (

View file

@ -8,6 +8,7 @@ import {
mapRunToRunItem,
runStatusDisplay,
} from "./runs";
import { TEST_PRINCIPAL } from "../lib/test-fixtures";
function makeRun(overrides: Partial<Run> = {}): Run {
return {
@ -17,7 +18,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: TEST_PRINCIPAL,
origin: { kind: "api" },
labels: {},
lifecycle: {

View file

@ -41,7 +41,7 @@ export interface RunItem {
sandboxWorkingDirectory?: string;
sourceDirectory?: string;
createdAt?: string;
createdBy?: Principal | null;
createdBy: Principal;
lastEventAt?: string;
size?: RunSize;
}

View file

@ -24,6 +24,7 @@ import {
unarchiveRuns,
} from "./run-actions";
import { generatedAxios } from "./api-client";
import { TEST_PRINCIPAL } from "./test-fixtures";
type StubResponseInit = {
status: number;
@ -47,7 +48,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: {

View file

@ -0,0 +1,8 @@
import type { Principal } from "@qltysh/fabro-api-client";
export const TEST_PRINCIPAL = {
kind: "user",
identity: { issuer: "fabro:test", subject: "test-user" },
login: "test",
auth_method: "dev_token",
} satisfies Principal;

View file

@ -4,6 +4,7 @@ import TestRenderer, { act } from "react-test-renderer";
import { createMemoryRouter, RouterProvider } from "react-router";
import { ToastProvider } from "../components/toast";
import { TEST_PRINCIPAL } from "../lib/test-fixtures";
import { setupReactTestEnv } from "../lib/test-utils";
let currentRun: any = null;
@ -120,7 +121,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: {

View file

@ -13,6 +13,7 @@ import {
import { ToastProvider } from "../components/toast";
import { DemoModeProvider } from "../lib/demo-mode";
import { TEST_PRINCIPAL } from "../lib/test-fixtures";
let currentRunSummary: any = null;
let currentRunState: any = null;
@ -221,7 +222,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: {

View file

@ -5,6 +5,7 @@ import { MemoryRouter, Route, Routes } from "react-router";
import { toast as sonnerToast } from "sonner";
import { ToastProvider } from "../components/toast";
import { TEST_PRINCIPAL } from "../lib/test-fixtures";
let currentFilesPayload: any = null;
let currentCommitsPayload: any = null;
@ -51,7 +52,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: {

View file

@ -5,6 +5,7 @@ import type { PaginatedRunList, Run } from "@qltysh/fabro-api-client";
import { ToastProvider } from "../components/toast";
import { CHILD_RUNS_LIST_PREFERENCES_STORAGE_KEY } from "../components/runs-list/preferences";
import { TEST_PRINCIPAL } from "../lib/test-fixtures";
import { setupReactTestEnv } from "../lib/test-utils";
class MemoryStorage {
@ -35,7 +36,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: TEST_PRINCIPAL,
origin: { kind: "api" },
labels: {},
lifecycle: {

View file

@ -11,6 +11,7 @@ import {
shouldRefreshBoardForEvent,
} from "./runs";
import { summarizeBatchLifecycleAction } from "../components/runs-list/batch-lifecycle";
import { TEST_PRINCIPAL } from "../lib/test-fixtures";
function boardRun(id: string, column: BoardColumn, questionText?: string): Run {
const status =
@ -34,7 +35,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: TEST_PRINCIPAL,
origin: { kind: "api" },
labels: {},
lifecycle: {

View file

@ -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:

View file

@ -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"] }

View file

@ -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();

View file

@ -1,7 +1,9 @@
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 as types_test_support,
};
use serde_json::{Value, json};
#[test]
@ -20,7 +22,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": types_test_support::test_run_provenance()
}
});
@ -39,6 +42,7 @@ 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",
"provenance": types_test_support::test_run_provenance(),
"web_url": format!("http://localhost:3000/runs/{}", fixtures::RUN_1)
}
});

View file

@ -1,7 +1,9 @@
use std::any::{TypeId, type_name};
use fabro_api::types::RunProjection as ApiRunProjection;
use fabro_types::{Graph, RunProjection, RunSpec, WorkflowSettings};
use fabro_types::{
Graph, RunProjection, RunSpec, WorkflowSettings, test_support as types_test_support,
};
use serde_json::json;
#[test]
@ -137,7 +139,7 @@ fn run_spec_json() -> serde_json::Value {
automation: None,
source_directory: None,
labels: std::collections::HashMap::new(),
provenance: None,
provenance: types_test_support::test_run_provenance(),
manifest_blob: None,
definition_blob: None,
git: None,

View file

@ -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 as types_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: types_test_support::test_principal(),
origin: RunOrigin::default(),
labels: HashMap::from([("team".to_string(), "core".to_string())]),
lifecycle: RunLifecycle {
@ -161,7 +161,7 @@ fn run_summary_json_matches_openapi_shape() {
"origin_url": null,
"provider": "unknown"
},
"created_by": null,
"created_by": types_test_support::test_principal(),
"origin": {
"kind": "api"
},
@ -253,6 +253,7 @@ fn run_summary_deserializes_when_optional_fields_are_absent() {
"origin_url": null,
"provider": "unknown"
},
"created_by": types_test_support::test_principal(),
"models": [],
"timestamps": {
"created_at": "2026-04-20T12:00:00Z",

View file

@ -128,6 +128,7 @@ temp-env = "0.3"
httpmock = "0.8"
fabro-test = { workspace = true }
fabro-macros = { path = "../fabro-macros" }
fabro-types = { path = "../fabro-types", features = ["clap", "test-support"] }
hkdf.workspace = true
reqwest = { workspace = true, features = ["cookies"] }
tokio = { workspace = true, features = ["test-util", "macros"] }

View file

@ -822,6 +822,7 @@ mod tests {
)]
use fabro_interview::{Answer, AnswerValue};
use fabro_types::test_support as types_test_support;
use fabro_util::terminal::Styles;
use httpmock::MockServer;
@ -841,7 +842,7 @@ mod tests {
automation: None,
source_directory: None,
labels: std::collections::HashMap::default(),
provenance: None,
provenance: types_test_support::test_run_provenance(),
manifest_blob: None,
definition_blob: None,
git: None,

View file

@ -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,

View file

@ -21,7 +21,7 @@ use fabro_config::daemon::ServerDaemon;
use fabro_config::{Storage, envfile};
use fabro_store::EventEnvelope;
use fabro_test::{TestContext, expect_reqwest_status};
use fabro_types::{RunId, StageId};
use fabro_types::{RunId, StageId, test_support as types_test_support};
use httpmock::{Mock, MockServer};
use serde_json::Value;
use shlex::try_quote;
@ -165,6 +165,7 @@ pub(crate) fn remote_run_summary_json(
) -> Value {
serde_json::json!({
"id": run_id,
"children_count": 0,
"title": goal,
"goal": goal,
"workflow": {
@ -172,11 +173,13 @@ pub(crate) fn remote_run_summary_json(
"name": workflow_name,
"graph_name": null
},
"automation": null,
"repository": {
"name": "repo",
"origin_url": null,
"provider": "unknown"
},
"created_by": types_test_support::test_principal(),
"origin": {
"kind": "api"
},
@ -199,6 +202,9 @@ pub(crate) fn remote_run_summary_json(
},
"timing": null,
"billing": null,
"ask_fabro": {
"available": false
},
"diff": null,
"pull_request": null,
"current_question": null,

View file

@ -9,7 +9,7 @@ pub(crate) use auth_harness::{
pub(crate) use auth_tokens::{TEST_SESSION_SECRET, issue_test_github_jwt, issue_test_worker_jwt};
use fabro_store::EventEnvelope;
use fabro_test::{EnvVars, TestContext, preserve_coverage_env};
use fabro_types::{Graph, RunId, RunSpec, WorkflowSettings};
use fabro_types::{Graph, RunId, RunSpec, WorkflowSettings, test_support as types_test_support};
pub(crate) fn run_output_filters(context: &TestContext) -> Vec<(String, String)> {
let mut filters = context.filters();
@ -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: types_test_support::test_run_provenance(),
manifest_blob: None,
definition_blob: None,
git: None,

View file

@ -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 as types_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: types_test_support::test_run_provenance(),
manifest_blob: None,
definition_blob: None,
fork_source_ref: None,

View file

@ -1081,7 +1081,7 @@ fn ts(s: &str) -> DateTime<Utc> {
mod runs {
use std::collections::HashMap;
use std::sync::OnceLock;
use std::sync::{LazyLock, OnceLock};
use std::time::Duration;
use fabro_api::types::*;
@ -1092,13 +1092,23 @@ mod runs {
};
use fabro_types::settings::{InterpString, ProjectNamespace, WorkflowNamespace};
use fabro_types::{
PendingReason, RepositoryRef, RunBillingSummary, RunId, RunLifecycle, RunLinks, RunOrigin,
RunSize, RunTimestamps, StageId, WorkflowRef, WorkflowSettings,
AuthMethod, IdpIdentity, PendingReason, Principal, RepositoryRef, RunBillingSummary, RunId,
RunLifecycle, RunLinks, RunOrigin, RunSize, RunTimestamps, StageId, WorkflowRef,
WorkflowSettings,
};
use super::ts;
use crate::server::run_stage_from_stage_id;
static DEMO_PRINCIPAL: LazyLock<Principal> = LazyLock::new(|| {
Principal::user(
IdpIdentity::new("fabro:demo", "demo")
.expect("hard-coded demo identity should be valid"),
"demo".to_string(),
AuthMethod::DevToken,
)
});
fn labels(entries: &[(&str, &str)]) -> HashMap<String, String> {
entries
.iter()
@ -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 {

View file

@ -1717,7 +1717,7 @@ fn count_flags(data: &[FileDiff]) -> (u64, u64, u64, u64) {
mod tests {
use std::sync::atomic::{AtomicUsize, Ordering};
use fabro_types::{CommandTermination, RunId};
use fabro_types::{CommandTermination, RunId, test_support as types_test_support};
use tokio::time::{Duration, sleep};
use super::*;
@ -2389,7 +2389,7 @@ index 1111111..2222222 160000
automation: None,
source_directory: None,
labels: HashMap::default(),
provenance: None,
provenance: types_test_support::test_run_provenance(),
manifest_blob: None,
definition_blob: None,
git: None,

View file

@ -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;
@ -193,6 +195,7 @@ pub(crate) fn validate_prepared_manifest(
pub(crate) fn create_run_input(
prepared: PreparedManifest,
configured_providers: Vec<ProviderId>,
provenance: RunProvenance,
web_url: Option<String>,
) -> CreateRunInput {
CreateRunInput {
@ -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,
}

View file

@ -1879,8 +1879,7 @@ async fn http_log_middleware(mut req: axum_extract::Request, next: Next) -> Resp
let principal_kind = auth_context
.principal
.as_ref()
.map(Principal::kind)
.unwrap_or("none");
.map_or("none", Principal::kind);
let auth_status = auth_context.auth_status.as_str();
macro_rules! emit_http_log {

View file

@ -535,7 +535,7 @@ mod stage_events_tests {
use axum::body::{Body, to_bytes};
use axum::http::{Request, StatusCode, header};
use fabro_store::EventPayload;
use fabro_types::{Graph, RunId, WorkflowSettings};
use fabro_types::{Graph, RunId, WorkflowSettings, test_support as types_test_support};
use fabro_workflow::event as workflow_event;
use http_body_util::BodyExt;
use serde_json::json;
@ -570,7 +570,7 @@ mod stage_events_tests {
workflow_slug: None,
automation: None,
db_prefix: None,
provenance: None,
provenance: types_test_support::test_run_provenance(),
manifest_blob: None,
git: None,
fork_source_ref: None,

View file

@ -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 {

View file

@ -850,7 +850,7 @@ mod tests {
use fabro_types::run_event::AgentMessageProps;
use fabro_types::{
BilledTokenCounts, EventEnvelope, Graph, PairMessageId, RunEvent, StageId,
WorkflowSettings, fixtures,
WorkflowSettings, fixtures, test_support as types_test_support,
};
use fabro_workflow::event as workflow_event;
use tower::ServiceExt;
@ -1024,7 +1024,7 @@ mod tests {
workflow_slug: None,
automation: None,
db_prefix: None,
provenance: None,
provenance: types_test_support::test_run_provenance(),
manifest_blob: None,
git: None,
fork_source_ref: None,

View file

@ -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(),
provenance,
web_url.clone(),
);
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(),
}
}

View file

@ -1299,7 +1299,7 @@ FABRO_PROC_NET_TCP /proc/net/tcp6
mod retrieve_sandbox_tests {
use axum::body::{Body, to_bytes};
use axum::http::{Request, StatusCode};
use fabro_types::{Graph, RunId, WorkflowSettings};
use fabro_types::{Graph, RunId, WorkflowSettings, test_support as types_test_support};
use serde_json::{Value, json};
use tower::ServiceExt;
@ -1339,6 +1339,7 @@ mod retrieve_sandbox_tests {
"settings": WorkflowSettings::default(),
"graph": Graph::new("test"),
"run_dir": "/tmp/test",
"provenance": types_test_support::test_run_provenance(),
},
}),
run_id,

View file

@ -1506,6 +1506,7 @@ mod tests {
use fabro_agent::config::ToolAccess;
use fabro_agent::tool_registry::{RegisteredTool, ToolContext, ToolRegistry, ToolSource};
use fabro_llm::types::{ToolCall, ToolDefinition};
use fabro_types::test_support as types_test_support;
use super::*;
@ -1700,7 +1701,7 @@ mod tests {
automation: None,
source_directory: None,
labels: HashMap::default(),
provenance: None,
provenance: types_test_support::test_run_provenance(),
manifest_blob: None,
definition_blob: None,
git: None,

View file

@ -29,7 +29,7 @@ use fabro_types::{
SandboxProviderKind, StageContextWindowBreakdownItem, StageContextWindowCategory,
StageContextWindowCountMethod, StageContextWindowProjection, StageContextWindowStaleness,
StageContextWindowWarning, StageModelUsage, StageTiming, SuccessReason, SystemActorKind,
WorkflowSettings, fixtures,
WorkflowSettings, fixtures, test_support as types_test_support,
};
use fabro_util::check_report::CheckStatus;
use fabro_workflow::records::CheckpointExt;
@ -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: 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: 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: 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: 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: 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: types_test_support::test_run_provenance(),
manifest_blob: None,
git: None,
fork_source_ref: None,

View file

@ -14,7 +14,9 @@ use axum::body::Body;
use axum::http::{Request, StatusCode};
use fabro_server::test_support::test_app_state_with_store;
use fabro_store::{ArtifactStore, Database};
use fabro_types::{Graph, RunId, SandboxProviderKind, WorkflowSettings};
use fabro_types::{
Graph, RunId, SandboxProviderKind, WorkflowSettings, test_support as types_test_support,
};
use fabro_workflow::event as workflow_event;
use fabro_workflow::run_status::SuccessReason;
use object_store::memory::InMemory as MemoryObjectStore;
@ -69,7 +71,7 @@ async fn append_completed_run_with_final_patch(
workflow_slug: None,
automation: None,
db_prefix: None,
provenance: None,
provenance: types_test_support::test_run_provenance(),
manifest_blob: None,
git: None,
fork_source_ref: None,

View file

@ -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

View file

@ -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 as types_test_support,
};
use serde_json::json;
@ -1358,7 +1354,7 @@ mod tests {
automation: None,
source_directory: None,
labels: HashMap::new(),
provenance: None,
provenance: types_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_retry_projects_retried_from_none() {
let event = test_raw_event(
1,
"run.created",
@ -1652,7 +1648,7 @@ mod tests {
"run_id": fixtures::RUN_1,
"event": event,
"node_id": node_id,
"properties": properties,
"properties": test_event_properties(event, properties),
}))
.unwrap(),
}
@ -1673,12 +1669,25 @@ mod tests {
"run_id": fixtures::RUN_1,
"event": event,
"node_id": node_id,
"properties": properties,
"properties": test_event_properties(event, properties),
}))
.unwrap(),
}
}
fn test_event_properties(event: &str, properties: &serde_json::Value) -> serde_json::Value {
let mut properties = properties.clone();
if event == "run.created" {
let object = properties
.as_object_mut()
.expect("run.created test properties should be a JSON object");
object
.entry("provenance".to_string())
.or_insert_with(|| json!(types_test_support::test_run_provenance()));
}
properties
}
#[test]
fn live_run_timing_returns_none_before_run_starts() {
let state = initialized_projection();
@ -1822,7 +1831,7 @@ mod tests {
"repo_origin_url": null,
"base_branch": null,
"labels": {},
"provenance": null,
"provenance": types_test_support::test_run_provenance(),
"manifest_blob": null,
"definition_blob": null,
"git": null,
@ -2851,7 +2860,7 @@ mod tests {
source_directory: Some("/tmp/repo".to_string()),
git: None,
labels: HashMap::new(),
provenance: None,
provenance: types_test_support::test_run_provenance(),
manifest_blob: None,
definition_blob: None,
fork_source_ref: None,
@ -2877,7 +2886,7 @@ mod tests {
source_directory: Some("/tmp/repo".to_string()),
git: None,
labels: HashMap::new(),
provenance: None,
provenance: types_test_support::test_run_provenance(),
manifest_blob: None,
definition_blob: None,
fork_source_ref: None,
@ -2930,7 +2939,7 @@ mod tests {
}
#[test]
fn legacy_run_created_without_title_infers_projection_title() {
fn run_created_without_title_infers_projection_title_from_goal() {
let event = test_raw_event(
1,
"run.created",
@ -3016,7 +3025,8 @@ mod tests {
"labels": {},
"run_dir": "/tmp/run",
"source_directory": "/tmp/run",
"manifest_blob": manifest_blob
"manifest_blob": manifest_blob,
"provenance": types_test_support::test_run_provenance()
}
}))
.unwrap(),

View file

@ -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 as types_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: types_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(),

View file

@ -667,7 +667,9 @@ 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 as types_test_support,
};
use object_store::memory::InMemory;
use serde_json::json;
@ -723,6 +725,7 @@ mod tests {
"settings": WorkflowSettings::default(),
"graph": Graph::new("test"),
"run_dir": "/tmp/test",
"provenance": types_test_support::test_run_provenance(),
},
}),
run_id,

View file

@ -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 as types_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: types_test_support::test_run_provenance(),
manifest_blob: None,
definition_blob: None,
git: Some(fabro_types::GitContext {

View file

@ -29,4 +29,5 @@ tokio.workspace = true
toml.workspace = true
[dev-dependencies]
fabro-types = { path = "../fabro-types", features = ["test-support"] }
tempfile = "3"

View file

@ -307,7 +307,10 @@ 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 as types_test_support,
};
use super::*;
@ -413,7 +416,7 @@ mod tests {
},
automation: None,
repository: None,
created_by: None,
created_by: types_test_support::test_principal(),
origin: RunOrigin::default(),
labels: HashMap::new(),
lifecycle: RunLifecycle {

View file

@ -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 as types_test_support,
};
use schemars::SchemaGenerator;
use serde_json::json;
@ -902,7 +902,7 @@ mod tests {
},
automation: None,
repository: None,
created_by: None,
created_by: types_test_support::test_principal(),
origin: RunOrigin::default(),
labels: HashMap::new(),
lifecycle: RunLifecycle {

View file

@ -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 as types_test_support,
};
use serde_json::json;
@ -690,7 +690,7 @@ mod tests {
},
automation: None,
repository: None,
created_by: None,
created_by: types_test_support::test_principal(),
origin: RunOrigin::default(),
labels: HashMap::new(),
lifecycle: RunLifecycle {

View file

@ -293,7 +293,10 @@ 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 as types_test_support,
};
use super::*;
@ -444,7 +447,7 @@ mod tests {
},
automation: None,
repository: None,
created_by: None,
created_by: types_test_support::test_principal(),
origin: RunOrigin::default(),
labels: HashMap::from([("group".to_string(), group.to_string())]),
lifecycle: RunLifecycle {

View file

@ -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;

View file

@ -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")]

View file

@ -933,7 +933,7 @@ mod tests {
use super::*;
use crate::{
AuthMethod, Edge, Graph, IdpIdentity, Node, PendingReason, RunBlobId, WorkflowSettings,
fixtures,
fixtures, test_support as types_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": types_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": types_test_support::test_run_provenance()
}
});

View file

@ -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")]

View file

@ -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,

View file

@ -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,

View 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(),
}
}

View file

@ -6,7 +6,20 @@ 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, Principal, RunProvenance, SystemActorKind, TurnId, WorkflowSettings,
fixtures,
};
fn test_run_provenance() -> RunProvenance {
RunProvenance {
server: None,
client: None,
subject: Principal::System {
system_kind: SystemActorKind::Engine,
},
}
}
fn templated_settings() -> WorkflowSettings {
let mut settings = WorkflowSettings::default();
@ -32,7 +45,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_run_provenance(),
manifest_blob: None,
git: Some(GitContext {
origin_url: "https://github.com/fabro-sh/fabro.git".to_string(),
@ -97,7 +110,7 @@ fn run_created_props_omits_web_url_when_absent() {
workflow_slug: None,
automation: None,
db_prefix: None,
provenance: None,
provenance: test_run_provenance(),
manifest_blob: None,
git: None,
fork_source_ref: None,
@ -133,6 +146,7 @@ fn run_created_props_defaults_additive_fields_for_legacy_events() {
"title": null,
"settings": WorkflowSettings::default(),
"graph": Graph::new("ship"),
"provenance": test_run_provenance(),
"labels": {},
"run_dir": "/tmp/run"
});

View file

@ -3,7 +3,17 @@ 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::{Principal, RunProvenance, SystemActorKind, WorkflowSettings, fixtures};
fn test_run_provenance() -> RunProvenance {
RunProvenance {
server: None,
client: None,
subject: Principal::System {
system_kind: SystemActorKind::Engine,
},
}
}
fn sample_run_spec() -> RunSpec {
let settings = WorkflowSettings {
@ -27,7 +37,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_run_provenance(),
manifest_blob: None,
definition_blob: None,
git: Some(GitContext {

View file

@ -4,7 +4,19 @@ 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, Principal, RunProvenance, SystemActorKind, WorkflowSettings, fixtures,
};
fn test_run_provenance() -> RunProvenance {
RunProvenance {
server: None,
client: None,
subject: Principal::System {
system_kind: SystemActorKind::Engine,
},
}
}
fn templated_settings() -> WorkflowSettings {
let mut settings = WorkflowSettings::default();
@ -27,7 +39,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_run_provenance(),
manifest_blob: None,
definition_blob: None,
git: Some(GitContext {
@ -80,7 +92,8 @@ fn run_spec_defaults_automation_for_legacy_specs() {
"run_id": fixtures::RUN_1,
"settings": WorkflowSettings::default(),
"graph": Graph::new("ship"),
"labels": {}
"labels": {},
"provenance": test_run_provenance()
});
let record: RunSpec = serde_json::from_value(json).expect("legacy spec should deserialize");

View file

@ -166,6 +166,7 @@ mod tests {
use fabro_types::{
AttrValue, BilledTokenCounts, Graph, Node, RunProjection, RunSpec, StageCompletion,
StageOutcome, WorkflowSettings, first_event_seq, fixtures,
test_support as types_test_support,
};
use super::billing_rollup_from_projection;
@ -353,7 +354,7 @@ mod tests {
automation: None,
source_directory: None,
labels: HashMap::new(),
provenance: None,
provenance: types_test_support::test_run_provenance(),
manifest_blob: None,
definition_blob: None,
git: None,

View file

@ -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"));

View file

@ -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")]

View file

@ -213,6 +213,7 @@ mod tests {
use std::sync::Arc;
use ::fabro_types::{Graph, RunNoticeLevel, WorkflowSettings, fixtures};
use fabro_types::test_support as types_test_support;
use tokio::sync::Mutex as AsyncMutex;
use super::*;
@ -244,7 +245,7 @@ mod tests {
workflow_slug: None,
automation: None,
db_prefix: None,
provenance: None,
provenance: types_test_support::test_run_provenance(),
manifest_blob: None,
git: None,
fork_source_ref: None,

View file

@ -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 }

View file

@ -343,7 +343,9 @@ mod tests {
use fabro_dump::RunDump;
use fabro_store::Database;
use fabro_types::{CommandTermination, StageModelUsage, fixtures};
use fabro_types::{
CommandTermination, StageModelUsage, fixtures, test_support as types_test_support,
};
use object_store::memory::InMemory;
use super::*;
@ -469,7 +471,7 @@ mod tests {
workflow_slug: None,
automation: None,
db_prefix: None,
provenance: None,
provenance: types_test_support::test_run_provenance(),
manifest_blob: None,
git: None,
fork_source_ref: None,

View file

@ -429,7 +429,7 @@ mod tests {
use fabro_graphviz::graph::AttrValue;
use fabro_model::{ReasoningEffort, Speed};
use fabro_store::{Database, RunDatabase, StageId};
use fabro_types::fixtures;
use fabro_types::{fixtures, test_support as types_test_support};
use object_store::memory::InMemory;
use tempfile::TempDir;
@ -484,7 +484,7 @@ mod tests {
workflow_slug: None,
automation: None,
db_prefix: None,
provenance: None,
provenance: types_test_support::test_run_provenance(),
manifest_blob: None,
git: None,
fork_source_ref: None,

View file

@ -228,7 +228,10 @@ mod tests {
use bytes::Bytes;
use fabro_graphviz::graph::AttrValue;
use fabro_store::{Database, RunDatabase, StageId};
use fabro_types::{Graph, RunProjection, RunSpec, WorkflowSettings, fixtures};
use fabro_types::{
Graph, RunProjection, RunSpec, WorkflowSettings, fixtures,
test_support as types_test_support,
};
use object_store::memory::InMemory;
use tokio::sync::Mutex;
@ -256,7 +259,7 @@ mod tests {
automation: None,
source_directory: None,
labels: std::collections::HashMap::default(),
provenance: None,
provenance: types_test_support::test_run_provenance(),
manifest_blob: None,
definition_blob: None,
git: None,
@ -357,7 +360,7 @@ mod tests {
workflow_slug: None,
automation: None,
db_prefix: None,
provenance: None,
provenance: types_test_support::test_run_provenance(),
manifest_blob: None,
git: None,
fork_source_ref: None,

View file

@ -1600,6 +1600,7 @@ mod tests {
use fabro_types::{
EventEnvelope, FailureReason, Run, RunId, RunLifecycle, RunLinks, RunOrigin,
RunPairStatusResponse, RunProjection, RunStatus, RunTimestamps, SuccessReason, WorkflowRef,
test_support as types_test_support,
};
use fabro_vault::{SecretType, Vault};
use futures::stream;
@ -2133,7 +2134,7 @@ reasoning = false
},
automation: None,
repository: None,
created_by: None,
created_by: types_test_support::test_principal(),
origin: RunOrigin::default(),
labels: HashMap::new(),
lifecycle: RunLifecycle {

View file

@ -692,7 +692,7 @@ mod tests {
use fabro_graphviz::graph::{AttrValue, Edge};
use fabro_store::{Database, StageId};
use fabro_types::fixtures;
use fabro_types::{fixtures, test_support as types_test_support};
use object_store::memory::InMemory;
use super::*;
@ -728,7 +728,7 @@ mod tests {
workflow_slug: None,
automation: None,
db_prefix: None,
provenance: None,
provenance: types_test_support::test_run_provenance(),
manifest_blob: None,
git: None,
fork_source_ref: None,

View file

@ -225,7 +225,7 @@ mod tests {
use fabro_graphviz::graph::AttrValue;
use fabro_model::{ReasoningEffort, Speed};
use fabro_store::{Database, RunDatabase, StageId};
use fabro_types::fixtures;
use fabro_types::{fixtures, test_support as types_test_support};
use object_store::memory::InMemory;
use tempfile::TempDir;
@ -283,7 +283,7 @@ mod tests {
workflow_slug: None,
automation: None,
db_prefix: None,
provenance: None,
provenance: types_test_support::test_run_provenance(),
manifest_blob: None,
git: None,
fork_source_ref: None,

View file

@ -598,7 +598,10 @@ mod tests {
use fabro_model::Catalog;
use fabro_store::{Database, EventEnvelope, RunDatabase, RunProjection};
use fabro_types::run_event::{MetadataSnapshotFailureKind, MetadataSnapshotPhase};
use fabro_types::{EventBody, RunBlobId, RunEvent, WorkflowSettings, fixtures};
use fabro_types::{
EventBody, RunBlobId, RunEvent, WorkflowSettings, fixtures,
test_support as types_test_support,
};
use object_store::memory::InMemory;
use super::*;
@ -736,7 +739,7 @@ mod tests {
workflow_slug: Some("metadata".to_string()),
automation: None,
db_prefix: None,
provenance: None,
provenance: types_test_support::test_run_provenance(),
manifest_blob: None,
git: None,
fork_source_ref: None,

View file

@ -136,7 +136,10 @@ mod tests {
use std::time::Duration;
use fabro_store::Database;
use fabro_types::{FailureReason, RunId, SuccessReason, TerminalStatus, fixtures};
use fabro_types::{
FailureReason, RunId, SuccessReason, TerminalStatus, fixtures,
test_support as types_test_support,
};
use object_store::memory::InMemory;
use super::*;
@ -226,7 +229,7 @@ mod tests {
workflow_slug: None,
automation: None,
db_prefix: None,
provenance: None,
provenance: types_test_support::test_run_provenance(),
manifest_blob: None,
git: None,
fork_source_ref: None,

View file

@ -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>,
}
@ -422,7 +422,7 @@ mod tests {
use fabro_store::Database;
use fabro_types::settings::InterpString;
use fabro_types::settings::run::RunMode;
use fabro_types::{WorkflowSettings, fixtures};
use fabro_types::{WorkflowSettings, fixtures, test_support as types_test_support};
use fabro_util::error::collect_chain;
use fabro_validate::Severity;
use object_store::local::LocalFileSystem;
@ -1115,7 +1115,7 @@ mod tests {
git: None,
fork_source_ref: None,
parent_id: None,
provenance: None,
provenance: 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: 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: 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: 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: 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(),

View file

@ -284,7 +284,7 @@ mod tests {
use fabro_graphviz::graph::Graph;
use fabro_store::{Database, RunProjectionReducer};
use fabro_types::{StageId, WorkflowSettings, fixtures};
use fabro_types::{StageId, WorkflowSettings, fixtures, test_support as types_test_support};
use object_store::memory::InMemory;
use super::*;
@ -383,7 +383,7 @@ mod tests {
workflow_slug: Some("fork-source".to_string()),
automation: None,
db_prefix: None,
provenance: None,
provenance: types_test_support::test_run_provenance(),
manifest_blob: None,
git: Some(fabro_types::GitContext {
origin_url: "https://github.com/example/repo.git".to_string(),

View file

@ -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>,
}
@ -123,6 +123,7 @@ mod tests {
AuthMethod, DirtyStatus, FailureReason, ForkSourceRef, GitContext, Graph, IdpIdentity,
PreRunPushOutcome, Principal, PullRequestLink, RunBlobId, RunRunnableSource,
RunServerProvenance, RunTiming, UserPrincipal, WorkflowSettings, fixtures,
test_support as types_test_support,
};
use object_store::memory::InMemory;
@ -152,7 +153,7 @@ mod tests {
version: "test".to_string(),
}),
client: None,
subject: Some(actor(login)),
subject: actor(login),
}
}
@ -191,7 +192,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 +369,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 +403,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 +457,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 +511,7 @@ mod tests {
let err = retry_run(&store, &RetryRunInput {
source_run_id: run_id,
new_run_id: RunId::new(),
provenance: None,
provenance: types_test_support::test_run_provenance(),
web_url: None,
})
.await
@ -535,7 +529,7 @@ mod tests {
let err = retry_run(&store, &RetryRunInput {
source_run_id: fixtures::RUN_1,
new_run_id: RunId::new(),
provenance: None,
provenance: types_test_support::test_run_provenance(),
web_url: None,
})
.await

View file

@ -1129,7 +1129,10 @@ mod tests {
use fabro_store::Database;
use fabro_types::settings::run::RunMode;
use fabro_types::settings::{InterpString, ModelRef};
use fabro_types::{BilledModelUsage, ManifestPath, StageTiming, WorkflowSettings, fixtures};
use fabro_types::{
BilledModelUsage, ManifestPath, StageTiming, WorkflowSettings, fixtures,
test_support as types_test_support,
};
use object_store::memory::InMemory;
use super::*;
@ -1438,7 +1441,7 @@ reasoning = false
git: None,
fork_source_ref: None,
parent_id: None,
provenance: None,
provenance: types_test_support::test_run_provenance(),
configured_providers: Vec::new(),
web_url: None,
},
@ -1860,7 +1863,7 @@ reasoning = false
git: None,
fork_source_ref: None,
parent_id: None,
provenance: None,
provenance: types_test_support::test_run_provenance(),
configured_providers: Vec::new(),
web_url: None,
},

View file

@ -204,6 +204,7 @@ mod tests {
use chrono::Utc;
use fabro_types::{
Checkpoint, CheckpointRecord, Graph, RunDiff, RunSpec, WorkflowSettings, fixtures,
test_support as types_test_support,
};
use super::*;
@ -248,7 +249,7 @@ mod tests {
automation: None,
source_directory: None,
labels: HashMap::new(),
provenance: None,
provenance: types_test_support::test_run_provenance(),
manifest_blob: None,
definition_blob: None,
git: None,

View file

@ -18,7 +18,10 @@ use fabro_interview::AutoApproveInterviewer;
use fabro_sandbox::SandboxSpec;
use fabro_store::Database;
use fabro_types::settings::run::RunModelControls;
use fabro_types::{Principal, RunId, SystemActorKind, WorkflowSettings, fixtures, format_blob_ref};
use fabro_types::{
Principal, RunId, SystemActorKind, WorkflowSettings, fixtures, format_blob_ref,
test_support as types_test_support,
};
use object_store::memory::InMemory;
use super::*;
@ -165,7 +168,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: types_test_support::test_run_provenance(),
manifest_blob: None,
definition_blob: None,
fork_source_ref: None,
@ -208,7 +211,7 @@ async fn seed_created_and_starting(
workflow_slug: run_options.workflow_slug.clone(),
automation: None,
db_prefix: None,
provenance: None,
provenance: 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(),

View file

@ -651,7 +651,7 @@ mod tests {
use fabro_types::run_event::{MetadataSnapshotFailureKind, MetadataSnapshotPhase};
use fabro_types::{
BilledTokenCounts, EventBody, RunBlobId, RunEvent, RunId, RunSpec, StageCompletion,
WorkflowSettings, first_event_seq, fixtures,
WorkflowSettings, first_event_seq, fixtures, test_support as types_test_support,
};
use object_store::memory::InMemory;
@ -739,7 +739,7 @@ mod tests {
workflow_slug: Some("metadata".to_string()),
automation: None,
db_prefix: None,
provenance: None,
provenance: 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: types_test_support::test_run_provenance(),
manifest_blob: None,
definition_blob: None,
git: None,

View file

@ -648,7 +648,9 @@ mod tests {
use fabro_sandbox::SandboxSpec;
use fabro_store::Database;
use fabro_types::settings::run::RunModelControls;
use fabro_types::{EventBody, RunEvent, RunId, WorkflowSettings, fixtures};
use fabro_types::{
EventBody, RunEvent, RunId, WorkflowSettings, fixtures, test_support as types_test_support,
};
use fabro_vault::{SecretType, Vault};
use object_store::memory::InMemory;
use tokio::fs::{create_dir_all, write};
@ -773,7 +775,7 @@ mod tests {
push_outcome: fabro_types::PreRunPushOutcome::NotAttempted,
}),
labels: HashMap::new(),
provenance: None,
provenance: types_test_support::test_run_provenance(),
manifest_blob: None,
definition_blob: None,
fork_source_ref: None,

View file

@ -59,7 +59,7 @@ mod tests {
use fabro_graphviz::graph::{AttrValue, Edge, Graph, Node};
use fabro_store::{Database, RunDatabase};
use fabro_types::fixtures;
use fabro_types::{fixtures, test_support as types_test_support};
use object_store::memory::InMemory;
use super::*;
@ -148,7 +148,7 @@ mod tests {
("env".to_string(), "test".to_string()),
("team".to_string(), "workflow".to_string()),
]),
provenance: None,
provenance: types_test_support::test_run_provenance(),
manifest_blob: None,
definition_blob: None,
fork_source_ref: None,

View file

@ -680,7 +680,7 @@ mod tests {
use fabro_store::Database;
use fabro_types::{
BilledTokenCounts, RunProjection, RunSpec, SuccessReason, WorkflowSettings,
first_event_seq, fixtures,
first_event_seq, fixtures, test_support as types_test_support,
};
use fabro_vault::{SecretType, Vault};
use futures::stream;
@ -823,7 +823,7 @@ mod tests {
automation: None,
source_directory: None,
labels: HashMap::new(),
provenance: None,
provenance: 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: 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: 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: 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: 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: 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: 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: types_test_support::test_run_provenance(),
manifest_blob: None,
git: None,
fork_source_ref: None,

View file

@ -457,7 +457,7 @@ mod tests {
use fabro_graphviz::graph::Graph;
use fabro_store::Database;
use fabro_types::{RunStatus, WorkflowSettings, fixtures};
use fabro_types::{RunStatus, WorkflowSettings, fixtures, test_support as types_test_support};
use object_store::memory::InMemory;
use super::scan_runs_combined;
@ -491,7 +491,7 @@ mod tests {
push_outcome: fabro_types::PreRunPushOutcome::NotAttempted,
}),
labels: HashMap::new(),
provenance: None,
provenance: types_test_support::test_run_provenance(),
manifest_blob: None,
definition_blob: None,
fork_source_ref: None,

View file

@ -537,7 +537,10 @@ mod tests {
use std::sync::Arc;
use fabro_store::RunProjection;
use fabro_types::{DirtyStatus, GitContext, PreRunPushOutcome, RunSpec, WorkflowSettings};
use fabro_types::{
DirtyStatus, GitContext, PreRunPushOutcome, RunSpec, WorkflowSettings,
test_support as types_test_support,
};
use git2::{ErrorClass, ErrorCode};
use super::*;
@ -639,7 +642,7 @@ mod tests {
push_outcome: PreRunPushOutcome::NotAttempted,
}),
labels: HashMap::new(),
provenance: None,
provenance: types_test_support::test_run_provenance(),
manifest_blob: None,
definition_blob: None,
fork_source_ref: None,

View file

@ -120,7 +120,9 @@ mod tests {
use fabro_graphviz::graph::Graph;
use fabro_store::Database;
use fabro_types::run_event::RunSubmittedProps;
use fabro_types::{EventBody, RunEvent, WorkflowSettings, fixtures};
use fabro_types::{
EventBody, RunEvent, WorkflowSettings, fixtures, test_support as types_test_support,
};
use object_store::memory::InMemory;
use super::RunStoreHandle;
@ -148,7 +150,7 @@ mod tests {
source_directory: Some("/tmp/test".to_string()),
git: None,
labels: HashMap::new(),
provenance: None,
provenance: types_test_support::test_run_provenance(),
manifest_blob: None,
definition_blob: None,
fork_source_ref: None,
@ -170,7 +172,7 @@ mod tests {
workflow_slug: Some("test".to_string()),
automation: None,
db_prefix: None,
provenance: None,
provenance: types_test_support::test_run_provenance(),
manifest_blob: None,
git: None,
fork_source_ref: None,

View file

@ -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(),

View file

@ -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;
}

View file

@ -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;

View file

@ -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;

View file

@ -1,4 +1,4 @@
import type { AutomationRef, Principal, PrincipalSystem, RunSpec } from "../src";
import type { AutomationRef, Principal, PrincipalSystem, Run, RunSpec } from "../src";
type AssertFalse<T extends false> = T;
type AssertExtends<T extends U, U> = true;
@ -40,12 +40,16 @@ 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 Creator = Run["created_by"];
type SubjectIsNotAny = AssertFalse<IsAny<Subject>>;
type SubjectExtendsPrincipal = AssertExtends<Subject, Principal>;
type PrincipalExtendsSubject = AssertExtends<Principal, Subject>;
type CreatorIsNotAny = AssertFalse<IsAny<Creator>>;
type CreatorExtendsPrincipal = AssertExtends<Creator, Principal>;
type PrincipalExtendsCreator = AssertExtends<Principal, Creator>;
type Automation = NonNullable<RunSpec["automation"]>;
type AutomationExtendsRef = AssertExtends<Automation, AutomationRef>;
@ -67,6 +71,9 @@ const _automationTriggerId: AutomationTriggerId = "schedule_1";
void (null as unknown as SubjectIsNotAny);
void (null as unknown as SubjectExtendsPrincipal);
void (null as unknown as PrincipalExtendsSubject);
void (null as unknown as CreatorIsNotAny);
void (null as unknown as CreatorExtendsPrincipal);
void (null as unknown as PrincipalExtendsCreator);
void (null as unknown as AutomationExtendsRef);
void _principalSubject;
void _automation;