mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-08-28 05:27:41 +00:00
refactor: unify duplicate API types via with_replacement
Eliminate four parallel-type duplications between fabro-api generated DTOs and fabro-types canonical types. The wire shape is owned by OpenAPI; canonical types are reused via fabro-api/build.rs with_replacement so the adapter functions and silent unwrap_or_default defaults disappear. - SecretType moves to fabro-types (was fabro-vault); deletes secret_type_from_api adapter. - DiffLineStats renamed to DiffStats, moved to fabro-types, switched u64 -> i64 to match the OpenAPI integer; deletes line_stats_to_api. - ManifestPreRunPushOutcome rewritten as a oneOf+discriminator PreRunPushOutcome over five variant schemas, deleting both pre_run_push_outcome_from_manifest and build_manifest_push_outcome. - ManifestGit and PreRunGitContext unify as GitContext: dirty: DirtyStatus replaces clean: bool (preserving the Unknown state previously truncated on the wire), sha becomes Option<String>, and origin_url/branch fold into the unified context. RunSpec and RunCreatedProps flatten three fields (repo_origin_url, base_branch, pre_run_git) into a single git: Option<GitContext>. Each replacement gets a fabro-api parity test (TypeId equality plus JSON roundtrip) modeled on run_summary_round_trip.rs. TS client regenerated. Greenfield app, no production deployments — wire contract changed directly without backwards-compat shims. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
7045a2d7a4
commit
642e312cca
52 changed files with 937 additions and 472 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -2355,6 +2355,7 @@ name = "fabro-vault"
|
|||
version = "0.217.0-nightly.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"fabro-types",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tempfile",
|
||||
|
|
|
|||
|
|
@ -3583,7 +3583,7 @@ components:
|
|||
description: CLI working directory at invocation time.
|
||||
example: "/tmp/project"
|
||||
git:
|
||||
$ref: "#/components/schemas/ManifestGit"
|
||||
$ref: "#/components/schemas/GitContext"
|
||||
goal:
|
||||
$ref: "#/components/schemas/ManifestGoal"
|
||||
args:
|
||||
|
|
@ -3599,14 +3599,13 @@ components:
|
|||
additionalProperties:
|
||||
$ref: "#/components/schemas/ManifestWorkflow"
|
||||
|
||||
ManifestGit:
|
||||
description: Observable git state from the CLI working directory.
|
||||
GitContext:
|
||||
description: Observable git state captured before the run starts.
|
||||
type: object
|
||||
required:
|
||||
- origin_url
|
||||
- branch
|
||||
- sha
|
||||
- clean
|
||||
- dirty
|
||||
- push_outcome
|
||||
properties:
|
||||
origin_url:
|
||||
|
|
@ -3618,17 +3617,32 @@ components:
|
|||
description: Current branch name.
|
||||
example: feature/foo
|
||||
sha:
|
||||
type: string
|
||||
description: Current commit SHA.
|
||||
type: ["string", "null"]
|
||||
description: Current commit SHA, when known.
|
||||
example: abc123def
|
||||
clean:
|
||||
type: boolean
|
||||
description: Whether the working tree has uncommitted changes.
|
||||
dirty:
|
||||
$ref: "#/components/schemas/DirtyStatus"
|
||||
push_outcome:
|
||||
$ref: "#/components/schemas/ManifestPreRunPushOutcome"
|
||||
$ref: "#/components/schemas/PreRunPushOutcome"
|
||||
|
||||
ManifestPreRunPushOutcome:
|
||||
PreRunPushOutcome:
|
||||
description: Outcome of the CLI's best-effort pre-run push.
|
||||
oneOf:
|
||||
- $ref: "#/components/schemas/PreRunPushOutcomeNotAttempted"
|
||||
- $ref: "#/components/schemas/PreRunPushOutcomeSucceeded"
|
||||
- $ref: "#/components/schemas/PreRunPushOutcomeFailed"
|
||||
- $ref: "#/components/schemas/PreRunPushOutcomeSkippedNoRemote"
|
||||
- $ref: "#/components/schemas/PreRunPushOutcomeSkippedRemoteMismatch"
|
||||
discriminator:
|
||||
propertyName: type
|
||||
mapping:
|
||||
not_attempted: "#/components/schemas/PreRunPushOutcomeNotAttempted"
|
||||
succeeded: "#/components/schemas/PreRunPushOutcomeSucceeded"
|
||||
failed: "#/components/schemas/PreRunPushOutcomeFailed"
|
||||
skipped_no_remote: "#/components/schemas/PreRunPushOutcomeSkippedNoRemote"
|
||||
skipped_remote_mismatch: "#/components/schemas/PreRunPushOutcomeSkippedRemoteMismatch"
|
||||
|
||||
PreRunPushOutcomeNotAttempted:
|
||||
type: object
|
||||
required:
|
||||
- type
|
||||
|
|
@ -3637,18 +3651,67 @@ components:
|
|||
type: string
|
||||
enum:
|
||||
- not_attempted
|
||||
|
||||
PreRunPushOutcomeSucceeded:
|
||||
type: object
|
||||
required:
|
||||
- type
|
||||
- remote
|
||||
- branch
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- succeeded
|
||||
remote:
|
||||
type: string
|
||||
branch:
|
||||
type: string
|
||||
|
||||
PreRunPushOutcomeFailed:
|
||||
type: object
|
||||
required:
|
||||
- type
|
||||
- remote
|
||||
- branch
|
||||
- message
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- failed
|
||||
remote:
|
||||
type: string
|
||||
branch:
|
||||
type: string
|
||||
message:
|
||||
type: string
|
||||
|
||||
PreRunPushOutcomeSkippedNoRemote:
|
||||
type: object
|
||||
required:
|
||||
- type
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- skipped_no_remote
|
||||
|
||||
PreRunPushOutcomeSkippedRemoteMismatch:
|
||||
type: object
|
||||
required:
|
||||
- type
|
||||
- remote
|
||||
- repo_origin_url
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- skipped_remote_mismatch
|
||||
remote:
|
||||
type: ["string", "null"]
|
||||
branch:
|
||||
type: ["string", "null"]
|
||||
message:
|
||||
type: ["string", "null"]
|
||||
type: string
|
||||
repo_origin_url:
|
||||
type: ["string", "null"]
|
||||
type: string
|
||||
|
||||
ManifestGoal:
|
||||
description: Resolved goal with provenance.
|
||||
|
|
@ -4466,43 +4529,6 @@ components:
|
|||
- dirty
|
||||
- unknown
|
||||
|
||||
PreRunPushOutcome:
|
||||
description: Outcome of the CLI submitter's best-effort pre-run push.
|
||||
type: object
|
||||
required:
|
||||
- type
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- not_attempted
|
||||
- succeeded
|
||||
- failed
|
||||
- skipped_no_remote
|
||||
- skipped_remote_mismatch
|
||||
remote:
|
||||
type: ["string", "null"]
|
||||
branch:
|
||||
type: ["string", "null"]
|
||||
message:
|
||||
type: ["string", "null"]
|
||||
repo_origin_url:
|
||||
type: ["string", "null"]
|
||||
|
||||
PreRunGitContext:
|
||||
description: Submitter-side git context captured before run creation.
|
||||
type: object
|
||||
required:
|
||||
- local_dirty
|
||||
- push_outcome
|
||||
properties:
|
||||
display_base_sha:
|
||||
type: ["string", "null"]
|
||||
local_dirty:
|
||||
$ref: "#/components/schemas/DirtyStatus"
|
||||
push_outcome:
|
||||
$ref: "#/components/schemas/PreRunPushOutcome"
|
||||
|
||||
ForkSourceRef:
|
||||
description: Source checkpoint used to initialize a forked or rewound run.
|
||||
type: object
|
||||
|
|
@ -4535,10 +4561,6 @@ components:
|
|||
type: ["string", "null"]
|
||||
source_directory:
|
||||
type: ["string", "null"]
|
||||
repo_origin_url:
|
||||
type: ["string", "null"]
|
||||
base_branch:
|
||||
type: ["string", "null"]
|
||||
labels:
|
||||
type: object
|
||||
additionalProperties:
|
||||
|
|
@ -4550,9 +4572,9 @@ components:
|
|||
type: ["string", "null"]
|
||||
definition_blob:
|
||||
type: ["string", "null"]
|
||||
pre_run_git:
|
||||
git:
|
||||
oneOf:
|
||||
- $ref: "#/components/schemas/PreRunGitContext"
|
||||
- $ref: "#/components/schemas/GitContext"
|
||||
- type: "null"
|
||||
fork_source_ref:
|
||||
oneOf:
|
||||
|
|
|
|||
|
|
@ -318,6 +318,11 @@ fn main() {
|
|||
"fabro_types::settings::run::MergeStrategy",
|
||||
&[],
|
||||
),
|
||||
("SecretType", "fabro_types::SecretType", &[]),
|
||||
("DiffStats", "fabro_types::DiffStats", &[]),
|
||||
("PreRunPushOutcome", "fabro_types::PreRunPushOutcome", &[]),
|
||||
("DirtyStatus", "fabro_types::DirtyStatus", &[]),
|
||||
("GitContext", "fabro_types::GitContext", &[]),
|
||||
];
|
||||
for (name, path, impls) in replacements {
|
||||
settings.with_replacement(*name, *path, impls.iter().copied());
|
||||
|
|
|
|||
|
|
@ -27,7 +27,10 @@ pub mod types {
|
|||
pub use fabro_types::status::{
|
||||
BlockedReason, FailureReason, RunControlAction, RunStatus, SuccessReason, TerminalStatus,
|
||||
};
|
||||
pub use fabro_types::{RepositoryReference, RunSummary, ServerSettings, WorkflowSettings};
|
||||
pub use fabro_types::{
|
||||
DiffStats, DirtyStatus, GitContext, PreRunPushOutcome, RepositoryReference, RunSummary,
|
||||
SecretType, ServerSettings, WorkflowSettings,
|
||||
};
|
||||
|
||||
pub use crate::generated::types::*;
|
||||
}
|
||||
|
|
|
|||
46
lib/crates/fabro-api/tests/diff_stats_round_trip.rs
Normal file
46
lib/crates/fabro-api/tests/diff_stats_round_trip.rs
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
use std::any::{TypeId, type_name};
|
||||
|
||||
use fabro_api::types::DiffStats as ApiDiffStats;
|
||||
use fabro_types::DiffStats;
|
||||
use serde_json::json;
|
||||
|
||||
#[test]
|
||||
fn diff_stats_reuses_canonical_type() {
|
||||
assert_same_type::<ApiDiffStats, DiffStats>();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn diff_stats_serializes_with_required_integer_fields() {
|
||||
let stats = DiffStats {
|
||||
additions: 567,
|
||||
deletions: 234,
|
||||
};
|
||||
assert_eq!(
|
||||
serde_json::to_value(stats).unwrap(),
|
||||
json!({
|
||||
"additions": 567,
|
||||
"deletions": 234,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn diff_stats_deserializes_from_required_payload() {
|
||||
let stats: DiffStats = serde_json::from_value(json!({
|
||||
"additions": 1,
|
||||
"deletions": 0,
|
||||
}))
|
||||
.unwrap();
|
||||
assert_eq!(stats.additions, 1);
|
||||
assert_eq!(stats.deletions, 0);
|
||||
}
|
||||
|
||||
fn assert_same_type<T: 'static, U: 'static>() {
|
||||
assert_eq!(
|
||||
TypeId::of::<T>(),
|
||||
TypeId::of::<U>(),
|
||||
"{} should be the same type as {}",
|
||||
type_name::<T>(),
|
||||
type_name::<U>()
|
||||
);
|
||||
}
|
||||
101
lib/crates/fabro-api/tests/git_context_round_trip.rs
Normal file
101
lib/crates/fabro-api/tests/git_context_round_trip.rs
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
use std::any::{TypeId, type_name};
|
||||
|
||||
use fabro_api::types::{
|
||||
DirtyStatus as ApiDirtyStatus, GitContext as ApiGitContext,
|
||||
PreRunPushOutcome as ApiPreRunPushOutcome,
|
||||
};
|
||||
use fabro_types::{DirtyStatus, GitContext, PreRunPushOutcome};
|
||||
use serde_json::json;
|
||||
|
||||
#[test]
|
||||
fn git_context_reuses_canonical_types() {
|
||||
assert_same_type::<ApiGitContext, GitContext>();
|
||||
assert_same_type::<ApiDirtyStatus, DirtyStatus>();
|
||||
assert_same_type::<ApiPreRunPushOutcome, PreRunPushOutcome>();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dirty_status_serializes_with_snake_case_strings() {
|
||||
assert_eq!(
|
||||
serde_json::to_value(DirtyStatus::Clean).unwrap(),
|
||||
json!("clean")
|
||||
);
|
||||
assert_eq!(
|
||||
serde_json::to_value(DirtyStatus::Dirty).unwrap(),
|
||||
json!("dirty")
|
||||
);
|
||||
assert_eq!(
|
||||
serde_json::to_value(DirtyStatus::Unknown).unwrap(),
|
||||
json!("unknown")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn git_context_with_known_sha_round_trips() {
|
||||
let ctx = GitContext {
|
||||
origin_url: "https://github.com/acme/widgets".to_string(),
|
||||
branch: "main".to_string(),
|
||||
sha: Some("abc123".to_string()),
|
||||
dirty: DirtyStatus::Clean,
|
||||
push_outcome: PreRunPushOutcome::Succeeded {
|
||||
remote: "origin".to_string(),
|
||||
branch: "main".to_string(),
|
||||
},
|
||||
};
|
||||
let json = serde_json::to_value(&ctx).unwrap();
|
||||
assert_eq!(
|
||||
json,
|
||||
json!({
|
||||
"origin_url": "https://github.com/acme/widgets",
|
||||
"branch": "main",
|
||||
"sha": "abc123",
|
||||
"dirty": "clean",
|
||||
"push_outcome": {
|
||||
"type": "succeeded",
|
||||
"remote": "origin",
|
||||
"branch": "main",
|
||||
},
|
||||
})
|
||||
);
|
||||
let round_trip: GitContext = serde_json::from_value(json).unwrap();
|
||||
assert_eq!(round_trip, ctx);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn git_context_omits_absent_sha_on_serialize() {
|
||||
let ctx = GitContext {
|
||||
origin_url: "https://github.com/acme/widgets".to_string(),
|
||||
branch: "feature/foo".to_string(),
|
||||
sha: None,
|
||||
dirty: DirtyStatus::Unknown,
|
||||
push_outcome: PreRunPushOutcome::SkippedNoRemote,
|
||||
};
|
||||
let json = serde_json::to_value(&ctx).unwrap();
|
||||
assert!(json.get("sha").is_none());
|
||||
assert_eq!(json["dirty"], "unknown");
|
||||
assert_eq!(json["push_outcome"]["type"], "skipped_no_remote");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn git_context_deserializes_when_sha_is_absent() {
|
||||
let ctx: GitContext = serde_json::from_value(json!({
|
||||
"origin_url": "https://github.com/acme/widgets",
|
||||
"branch": "main",
|
||||
"dirty": "dirty",
|
||||
"push_outcome": { "type": "not_attempted" },
|
||||
}))
|
||||
.unwrap();
|
||||
assert_eq!(ctx.sha, None);
|
||||
assert_eq!(ctx.dirty, DirtyStatus::Dirty);
|
||||
assert_eq!(ctx.push_outcome, PreRunPushOutcome::NotAttempted);
|
||||
}
|
||||
|
||||
fn assert_same_type<T: 'static, U: 'static>() {
|
||||
assert_eq!(
|
||||
TypeId::of::<T>(),
|
||||
TypeId::of::<U>(),
|
||||
"{} should be the same type as {}",
|
||||
type_name::<T>(),
|
||||
type_name::<U>()
|
||||
);
|
||||
}
|
||||
128
lib/crates/fabro-api/tests/pre_run_push_outcome_round_trip.rs
Normal file
128
lib/crates/fabro-api/tests/pre_run_push_outcome_round_trip.rs
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
use std::any::{TypeId, type_name};
|
||||
|
||||
use fabro_api::types::PreRunPushOutcome as ApiPreRunPushOutcome;
|
||||
use fabro_types::PreRunPushOutcome;
|
||||
use serde_json::json;
|
||||
|
||||
#[test]
|
||||
fn pre_run_push_outcome_reuses_canonical_type() {
|
||||
assert_same_type::<ApiPreRunPushOutcome, PreRunPushOutcome>();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn singletons_serialize_with_only_a_type_field() {
|
||||
assert_eq!(
|
||||
serde_json::to_value(PreRunPushOutcome::NotAttempted).unwrap(),
|
||||
json!({ "type": "not_attempted" })
|
||||
);
|
||||
assert_eq!(
|
||||
serde_json::to_value(PreRunPushOutcome::SkippedNoRemote).unwrap(),
|
||||
json!({ "type": "skipped_no_remote" })
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn succeeded_carries_remote_and_branch() {
|
||||
let outcome = PreRunPushOutcome::Succeeded {
|
||||
remote: "origin".to_string(),
|
||||
branch: "feature/foo".to_string(),
|
||||
};
|
||||
assert_eq!(
|
||||
serde_json::to_value(&outcome).unwrap(),
|
||||
json!({
|
||||
"type": "succeeded",
|
||||
"remote": "origin",
|
||||
"branch": "feature/foo",
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn failed_carries_message_alongside_remote_and_branch() {
|
||||
let outcome = PreRunPushOutcome::Failed {
|
||||
remote: "origin".to_string(),
|
||||
branch: "feature/foo".to_string(),
|
||||
message: "permission denied".to_string(),
|
||||
};
|
||||
assert_eq!(
|
||||
serde_json::to_value(&outcome).unwrap(),
|
||||
json!({
|
||||
"type": "failed",
|
||||
"remote": "origin",
|
||||
"branch": "feature/foo",
|
||||
"message": "permission denied",
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn skipped_remote_mismatch_carries_remote_and_repo_origin_url() {
|
||||
let outcome = PreRunPushOutcome::SkippedRemoteMismatch {
|
||||
remote: "git@github.com:user/fork.git".to_string(),
|
||||
repo_origin_url: "https://github.com/acme/canonical.git".to_string(),
|
||||
};
|
||||
assert_eq!(
|
||||
serde_json::to_value(&outcome).unwrap(),
|
||||
json!({
|
||||
"type": "skipped_remote_mismatch",
|
||||
"remote": "git@github.com:user/fork.git",
|
||||
"repo_origin_url": "https://github.com/acme/canonical.git",
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deserializes_each_variant_from_discriminator_payloads() {
|
||||
let not_attempted: PreRunPushOutcome =
|
||||
serde_json::from_value(json!({ "type": "not_attempted" })).unwrap();
|
||||
assert_eq!(not_attempted, PreRunPushOutcome::NotAttempted);
|
||||
|
||||
let succeeded: PreRunPushOutcome = serde_json::from_value(json!({
|
||||
"type": "succeeded",
|
||||
"remote": "origin",
|
||||
"branch": "main",
|
||||
}))
|
||||
.unwrap();
|
||||
assert_eq!(succeeded, PreRunPushOutcome::Succeeded {
|
||||
remote: "origin".to_string(),
|
||||
branch: "main".to_string(),
|
||||
});
|
||||
|
||||
let failed: PreRunPushOutcome = serde_json::from_value(json!({
|
||||
"type": "failed",
|
||||
"remote": "origin",
|
||||
"branch": "main",
|
||||
"message": "denied",
|
||||
}))
|
||||
.unwrap();
|
||||
assert_eq!(failed, PreRunPushOutcome::Failed {
|
||||
remote: "origin".to_string(),
|
||||
branch: "main".to_string(),
|
||||
message: "denied".to_string(),
|
||||
});
|
||||
|
||||
let skipped_no_remote: PreRunPushOutcome =
|
||||
serde_json::from_value(json!({ "type": "skipped_no_remote" })).unwrap();
|
||||
assert_eq!(skipped_no_remote, PreRunPushOutcome::SkippedNoRemote);
|
||||
|
||||
let skipped_mismatch: PreRunPushOutcome = serde_json::from_value(json!({
|
||||
"type": "skipped_remote_mismatch",
|
||||
"remote": "git@github.com:user/fork.git",
|
||||
"repo_origin_url": "https://github.com/acme/canonical.git",
|
||||
}))
|
||||
.unwrap();
|
||||
assert_eq!(skipped_mismatch, PreRunPushOutcome::SkippedRemoteMismatch {
|
||||
remote: "git@github.com:user/fork.git".to_string(),
|
||||
repo_origin_url: "https://github.com/acme/canonical.git".to_string(),
|
||||
});
|
||||
}
|
||||
|
||||
fn assert_same_type<T: 'static, U: 'static>() {
|
||||
assert_eq!(
|
||||
TypeId::of::<T>(),
|
||||
TypeId::of::<U>(),
|
||||
"{} should be the same type as {}",
|
||||
type_name::<T>(),
|
||||
type_name::<U>()
|
||||
);
|
||||
}
|
||||
46
lib/crates/fabro-api/tests/secret_type_round_trip.rs
Normal file
46
lib/crates/fabro-api/tests/secret_type_round_trip.rs
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
use std::any::{TypeId, type_name};
|
||||
|
||||
use fabro_api::types::SecretType as ApiSecretType;
|
||||
use fabro_types::SecretType;
|
||||
use serde_json::json;
|
||||
|
||||
#[test]
|
||||
fn secret_type_reuses_canonical_type() {
|
||||
assert_same_type::<ApiSecretType, SecretType>();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn secret_type_serializes_as_snake_case_strings() {
|
||||
assert_eq!(
|
||||
serde_json::to_value(SecretType::Environment).unwrap(),
|
||||
json!("environment")
|
||||
);
|
||||
assert_eq!(
|
||||
serde_json::to_value(SecretType::File).unwrap(),
|
||||
json!("file")
|
||||
);
|
||||
assert_eq!(
|
||||
serde_json::to_value(SecretType::Credential).unwrap(),
|
||||
json!("credential")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn secret_type_deserializes_each_variant() {
|
||||
let env: SecretType = serde_json::from_value(json!("environment")).unwrap();
|
||||
assert_eq!(env, SecretType::Environment);
|
||||
let file: SecretType = serde_json::from_value(json!("file")).unwrap();
|
||||
assert_eq!(file, SecretType::File);
|
||||
let cred: SecretType = serde_json::from_value(json!("credential")).unwrap();
|
||||
assert_eq!(cred, SecretType::Credential);
|
||||
}
|
||||
|
||||
fn assert_same_type<T: 'static, U: 'static>() {
|
||||
assert_eq!(
|
||||
TypeId::of::<T>(),
|
||||
TypeId::of::<U>(),
|
||||
"{} should be the same type as {}",
|
||||
type_name::<T>(),
|
||||
type_name::<U>()
|
||||
);
|
||||
}
|
||||
|
|
@ -31,7 +31,7 @@ pub(crate) async fn ensure_origin_if_local(
|
|||
|
||||
let state = client.get_run_state(run_id).await?;
|
||||
if let Some(run_spec) = state.spec {
|
||||
ensure_matching_repo_origin(run_spec.repo_origin_url.as_deref(), verb)?;
|
||||
ensure_matching_repo_origin(run_spec.repo_origin_url(), verb)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,14 +7,14 @@ use std::collections::{HashMap, HashSet};
|
|||
use std::path::{Component, Path, PathBuf};
|
||||
|
||||
use anyhow::{Context, Result, anyhow};
|
||||
use fabro_api::types::{self, ManifestPreRunPushOutcome, ManifestPreRunPushOutcomeType};
|
||||
use fabro_api::types;
|
||||
use fabro_config::project::{self, discover_project_config, resolve_workflow_path};
|
||||
use fabro_config::run::{resolve_run_goal_from_layer, resolve_run_goal_from_namespace};
|
||||
use fabro_config::{CliLayer, DaytonaDockerfileLayer, RunLayer, WorkflowSettingsBuilder};
|
||||
use fabro_graphviz::graph::AttrValue;
|
||||
use fabro_graphviz::parser;
|
||||
use fabro_types::settings::run::{ResolvedGoalSource, ResolvedRunGoal};
|
||||
use fabro_types::{RunId, WorkflowSettings};
|
||||
use fabro_types::{DirtyStatus, GitContext, PreRunPushOutcome, RunId, WorkflowSettings};
|
||||
use fabro_workflow::git::{GitSyncStatus, branch_needs_push, head_sha, push_branch, sync_status};
|
||||
|
||||
use crate::args::{PreflightArgs, RunArgs};
|
||||
|
|
@ -138,7 +138,7 @@ pub(crate) fn build_run_manifest(input: ManifestBuildInput) -> Result<BuiltManif
|
|||
)?;
|
||||
|
||||
let configured_repo_origin_url = configured_repo_origin_url(&workflow_settings);
|
||||
let git = build_manifest_git(&working_directory, configured_repo_origin_url.as_deref());
|
||||
let git = build_git_context(&working_directory, configured_repo_origin_url.as_deref());
|
||||
let args = input.args.filter(|args| !manifest_args_is_empty(args));
|
||||
|
||||
Ok(BuiltManifest {
|
||||
|
|
@ -498,14 +498,16 @@ fn resolved_goal_to_manifest(resolved: ResolvedRunGoal) -> types::ManifestGoal {
|
|||
}
|
||||
}
|
||||
|
||||
fn build_manifest_git(
|
||||
fn build_git_context(
|
||||
repo_path: &Path,
|
||||
configured_repo_origin_url: Option<&str>,
|
||||
) -> Option<types::ManifestGit> {
|
||||
) -> Option<GitContext> {
|
||||
let (origin_url, branch) = detect_manifest_repo_info(repo_path)?;
|
||||
let sha = head_sha(repo_path).ok()?;
|
||||
let status = sync_status(repo_path, "origin", Some(&branch));
|
||||
let clean = status != GitSyncStatus::Dirty;
|
||||
let sha = head_sha(repo_path).ok();
|
||||
let dirty = match sync_status(repo_path, "origin", Some(&branch)) {
|
||||
GitSyncStatus::Dirty => DirtyStatus::Dirty,
|
||||
GitSyncStatus::Synced | GitSyncStatus::Unsynced => DirtyStatus::Clean,
|
||||
};
|
||||
let repo_origin_url = configured_repo_origin_url
|
||||
.map(fabro_github::normalize_repo_origin_url)
|
||||
.filter(|url| !url.is_empty())
|
||||
|
|
@ -522,12 +524,12 @@ fn build_manifest_git(
|
|||
origin_url.as_deref(),
|
||||
configured_repo_origin_url,
|
||||
);
|
||||
Some(types::ManifestGit {
|
||||
branch,
|
||||
clean,
|
||||
Some(GitContext {
|
||||
origin_url: repo_origin_url,
|
||||
push_outcome,
|
||||
branch,
|
||||
sha,
|
||||
dirty,
|
||||
push_outcome,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -565,58 +567,37 @@ fn build_manifest_push_outcome(
|
|||
branch: &str,
|
||||
origin_url: Option<&str>,
|
||||
configured_repo_origin_url: Option<&str>,
|
||||
) -> ManifestPreRunPushOutcome {
|
||||
if origin_url.is_none() {
|
||||
return ManifestPreRunPushOutcome {
|
||||
type_: ManifestPreRunPushOutcomeType::SkippedNoRemote,
|
||||
remote: None,
|
||||
branch: Some(branch.to_string()),
|
||||
message: None,
|
||||
repo_origin_url: None,
|
||||
};
|
||||
}
|
||||
) -> PreRunPushOutcome {
|
||||
let Some(origin_url) = origin_url else {
|
||||
return PreRunPushOutcome::SkippedNoRemote;
|
||||
};
|
||||
|
||||
if let Some(repo_origin_url) = configured_repo_origin_url
|
||||
.map(fabro_github::normalize_repo_origin_url)
|
||||
.filter(|url| !url.is_empty())
|
||||
{
|
||||
let remote = origin_url
|
||||
.map(fabro_github::normalize_repo_origin_url)
|
||||
.unwrap_or_default();
|
||||
let remote = fabro_github::normalize_repo_origin_url(origin_url);
|
||||
if remote != repo_origin_url {
|
||||
return ManifestPreRunPushOutcome {
|
||||
type_: ManifestPreRunPushOutcomeType::SkippedRemoteMismatch,
|
||||
remote: Some(remote),
|
||||
branch: Some(branch.to_string()),
|
||||
message: None,
|
||||
repo_origin_url: Some(repo_origin_url),
|
||||
return PreRunPushOutcome::SkippedRemoteMismatch {
|
||||
remote,
|
||||
repo_origin_url,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if !branch_needs_push(repo_path, "origin", branch) {
|
||||
return ManifestPreRunPushOutcome {
|
||||
type_: ManifestPreRunPushOutcomeType::NotAttempted,
|
||||
remote: None,
|
||||
branch: None,
|
||||
message: None,
|
||||
repo_origin_url: None,
|
||||
};
|
||||
return PreRunPushOutcome::NotAttempted;
|
||||
}
|
||||
|
||||
match push_branch(repo_path, "origin", branch) {
|
||||
Ok(()) => ManifestPreRunPushOutcome {
|
||||
type_: ManifestPreRunPushOutcomeType::Succeeded,
|
||||
remote: Some("origin".to_string()),
|
||||
branch: Some(branch.to_string()),
|
||||
message: None,
|
||||
repo_origin_url: None,
|
||||
Ok(()) => PreRunPushOutcome::Succeeded {
|
||||
remote: "origin".to_string(),
|
||||
branch: branch.to_string(),
|
||||
},
|
||||
Err(err) => ManifestPreRunPushOutcome {
|
||||
type_: ManifestPreRunPushOutcomeType::Failed,
|
||||
remote: Some("origin".to_string()),
|
||||
branch: Some(branch.to_string()),
|
||||
message: Some(err.to_string()),
|
||||
repo_origin_url: None,
|
||||
Err(err) => PreRunPushOutcome::Failed {
|
||||
remote: "origin".to_string(),
|
||||
branch: branch.to_string(),
|
||||
message: err.to_string(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -1018,18 +999,10 @@ repository = "target"
|
|||
.git
|
||||
.expect("manifest git info should be detected");
|
||||
assert_eq!(git.origin_url, "https://github.com/example/target");
|
||||
assert_eq!(
|
||||
git.push_outcome.type_,
|
||||
ManifestPreRunPushOutcomeType::SkippedRemoteMismatch
|
||||
);
|
||||
assert_eq!(
|
||||
git.push_outcome.remote.as_deref(),
|
||||
Some("https://github.com/user/forked-target")
|
||||
);
|
||||
assert_eq!(
|
||||
git.push_outcome.repo_origin_url.as_deref(),
|
||||
Some("https://github.com/example/target")
|
||||
);
|
||||
assert_eq!(git.push_outcome, PreRunPushOutcome::SkippedRemoteMismatch {
|
||||
remote: "https://github.com/user/forked-target".to_string(),
|
||||
repo_origin_url: "https://github.com/example/target".to_string(),
|
||||
});
|
||||
}
|
||||
|
||||
fn init_git_repo(path: &Path, branch: &str, origin_url: &str) {
|
||||
|
|
|
|||
|
|
@ -34,8 +34,8 @@ use fabro_sandbox::reconnect::reconnect;
|
|||
use fabro_static::EnvVars;
|
||||
use fabro_types::RunId;
|
||||
use fabro_workflow::sandbox_git::{
|
||||
DiffError, DiffLineStats, DiffNumstat, RawDiffEntry, SubmoduleChange, SymlinkChange,
|
||||
list_changed_files_raw, list_diff_numstat, stream_blob_metadata, stream_blobs,
|
||||
DiffError, DiffNumstat, RawDiffEntry, SubmoduleChange, SymlinkChange, list_changed_files_raw,
|
||||
list_diff_numstat, stream_blob_metadata, stream_blobs,
|
||||
};
|
||||
use futures_util::FutureExt;
|
||||
use serde::Deserialize;
|
||||
|
|
@ -373,13 +373,6 @@ async fn materialize_sandbox_path(state: &Arc<AppState>, run_id: &RunId) -> List
|
|||
})
|
||||
}
|
||||
|
||||
fn line_stats_to_api(stats: DiffLineStats) -> DiffStats {
|
||||
DiffStats {
|
||||
additions: i64::try_from(stats.additions).unwrap_or(i64::MAX),
|
||||
deletions: i64::try_from(stats.deletions).unwrap_or(i64::MAX),
|
||||
}
|
||||
}
|
||||
|
||||
/// Choose a degraded reason given the current projection. Docker-provider
|
||||
/// runs aren't supported by the deployed server; completed runs are "gone";
|
||||
/// everything else is a transient "unreachable" (sandbox may come back).
|
||||
|
|
@ -451,7 +444,7 @@ fn build_fallback_response(
|
|||
/// summation we use on the live-sandbox path so the toolbar shows the same
|
||||
/// numbers regardless of which response branch we took.
|
||||
fn patch_to_stats(patch: &str) -> DiffStats {
|
||||
let mut stats = DiffLineStats::default();
|
||||
let mut stats = DiffStats::default();
|
||||
for section in patch.split("diff --git ").skip(1) {
|
||||
if patch_section_omits_line_stats(section) {
|
||||
continue;
|
||||
|
|
@ -467,7 +460,7 @@ fn patch_to_stats(patch: &str) -> DiffStats {
|
|||
}
|
||||
}
|
||||
}
|
||||
line_stats_to_api(stats)
|
||||
stats
|
||||
}
|
||||
|
||||
fn patch_section_omits_line_stats(section: &str) -> bool {
|
||||
|
|
@ -729,7 +722,7 @@ fn classify_entries(
|
|||
is_sensitive_fn: fn(&str) -> bool,
|
||||
) -> ClassifiedEntries {
|
||||
let mut out = Vec::with_capacity(raw.len());
|
||||
let mut stats = DiffLineStats::default();
|
||||
let mut stats = DiffStats::default();
|
||||
|
||||
for entry in raw {
|
||||
let (new_path, old_path) = match entry {
|
||||
|
|
@ -786,7 +779,7 @@ fn classify_entries(
|
|||
|
||||
ClassifiedEntries {
|
||||
entries: out,
|
||||
stats: line_stats_to_api(stats),
|
||||
stats,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1638,7 +1631,7 @@ diff --git a/src/main.rs b/src/main.rs
|
|||
] {
|
||||
numstat
|
||||
.line_stats_by_path
|
||||
.insert(path.to_string(), DiffLineStats {
|
||||
.insert(path.to_string(), DiffStats {
|
||||
additions,
|
||||
deletions,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ use fabro_types::settings::run::{
|
|||
ApprovalMode, DaytonaNetworkLayer, DaytonaSettings, DockerSettings, DockerfileSource, RunGoal,
|
||||
RunMode, RunNamespace, WorktreeMode,
|
||||
};
|
||||
use fabro_types::{DirtyStatus, PreRunGitContext, PreRunPushOutcome, RunId, WorkflowSettings};
|
||||
use fabro_types::{RunId, WorkflowSettings};
|
||||
use fabro_util::check_report::{CheckDetail, CheckReport, CheckResult, CheckSection, CheckStatus};
|
||||
use fabro_validate::Severity;
|
||||
use fabro_workflow::Error as WorkflowError;
|
||||
|
|
@ -41,7 +41,7 @@ use crate::server::AppState;
|
|||
#[derive(Clone)]
|
||||
pub(crate) struct PreparedManifest {
|
||||
pub cwd: PathBuf,
|
||||
pub git: Option<types::ManifestGit>,
|
||||
pub git: Option<types::GitContext>,
|
||||
pub root_source: String,
|
||||
pub run_id: Option<RunId>,
|
||||
pub settings: WorkflowSettings,
|
||||
|
|
@ -165,12 +165,7 @@ pub(crate) fn create_run_input(
|
|||
workflow_bundle: Some(prepared.workflow_bundle),
|
||||
submitted_manifest_bytes: None,
|
||||
run_id: prepared.run_id,
|
||||
repo_origin_url: prepared.git.as_ref().and_then(|git| {
|
||||
let origin_url = fabro_github::normalize_repo_origin_url(&git.origin_url);
|
||||
(!origin_url.is_empty()).then_some(origin_url)
|
||||
}),
|
||||
base_branch: prepared.git.as_ref().map(|git| git.branch.clone()),
|
||||
pre_run_git: prepared.git.as_ref().map(pre_run_git_from_manifest),
|
||||
git: prepared.git,
|
||||
fork_source_ref: None,
|
||||
in_place: prepared.in_place,
|
||||
provenance: None,
|
||||
|
|
@ -178,48 +173,6 @@ pub(crate) fn create_run_input(
|
|||
}
|
||||
}
|
||||
|
||||
fn pre_run_git_from_manifest(git: &types::ManifestGit) -> PreRunGitContext {
|
||||
PreRunGitContext {
|
||||
display_base_sha: Some(git.sha.clone()),
|
||||
local_dirty: if git.clean {
|
||||
DirtyStatus::Clean
|
||||
} else {
|
||||
DirtyStatus::Dirty
|
||||
},
|
||||
push_outcome: pre_run_push_outcome_from_manifest(&git.push_outcome),
|
||||
}
|
||||
}
|
||||
|
||||
fn pre_run_push_outcome_from_manifest(
|
||||
outcome: &types::ManifestPreRunPushOutcome,
|
||||
) -> PreRunPushOutcome {
|
||||
match outcome.type_ {
|
||||
types::ManifestPreRunPushOutcomeType::NotAttempted => PreRunPushOutcome::NotAttempted,
|
||||
types::ManifestPreRunPushOutcomeType::Succeeded => PreRunPushOutcome::Succeeded {
|
||||
remote: outcome
|
||||
.remote
|
||||
.clone()
|
||||
.unwrap_or_else(|| "origin".to_string()),
|
||||
branch: outcome.branch.clone().unwrap_or_default(),
|
||||
},
|
||||
types::ManifestPreRunPushOutcomeType::Failed => PreRunPushOutcome::Failed {
|
||||
remote: outcome
|
||||
.remote
|
||||
.clone()
|
||||
.unwrap_or_else(|| "origin".to_string()),
|
||||
branch: outcome.branch.clone().unwrap_or_default(),
|
||||
message: outcome.message.clone().unwrap_or_default(),
|
||||
},
|
||||
types::ManifestPreRunPushOutcomeType::SkippedNoRemote => PreRunPushOutcome::SkippedNoRemote,
|
||||
types::ManifestPreRunPushOutcomeType::SkippedRemoteMismatch => {
|
||||
PreRunPushOutcome::SkippedRemoteMismatch {
|
||||
remote: outcome.remote.clone().unwrap_or_default(),
|
||||
repo_origin_url: outcome.repo_origin_url.clone().unwrap_or_default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn run_preflight(
|
||||
state: &AppState,
|
||||
prepared: &PreparedManifest,
|
||||
|
|
@ -565,13 +518,19 @@ fn base_preflight_checks(prepared: &PreparedManifest, graph: &Graph) -> Vec<Chec
|
|||
CheckDetail {
|
||||
text: format!(
|
||||
"Git: {}",
|
||||
prepared.git.as_ref().map_or("unknown", |git| if git.clean {
|
||||
"clean"
|
||||
} else {
|
||||
"dirty"
|
||||
})
|
||||
prepared
|
||||
.git
|
||||
.as_ref()
|
||||
.map_or("unknown", |git| match git.dirty {
|
||||
fabro_types::DirtyStatus::Clean => "clean",
|
||||
fabro_types::DirtyStatus::Dirty => "dirty",
|
||||
fabro_types::DirtyStatus::Unknown => "unknown",
|
||||
})
|
||||
),
|
||||
warn: prepared.git.as_ref().is_some_and(|git| !git.clean),
|
||||
warn: prepared
|
||||
.git
|
||||
.as_ref()
|
||||
.is_some_and(|git| git.dirty != fabro_types::DirtyStatus::Clean),
|
||||
},
|
||||
],
|
||||
remediation: None,
|
||||
|
|
|
|||
|
|
@ -35,9 +35,9 @@ pub use fabro_api::types::{
|
|||
QuestionType as ApiQuestionType, RenderWorkflowGraphDirection, RenderWorkflowGraphRequest,
|
||||
RewindRequest, RewindResponse, RunArtifactEntry, RunArtifactListResponse, RunBilling,
|
||||
RunBillingStage, RunBillingTotals, RunError, RunManifest, RunStage, RunStatusResponse,
|
||||
SandboxFileEntry, SandboxFileListResponse, SecretType as ApiSecretType, SshAccessRequest,
|
||||
SshAccessResponse, StageStatus as ApiStageStatus, StartRunRequest, SubmitAnswerRequest,
|
||||
SystemFeatures, SystemInfoResponse, SystemRunCounts, TimelineEntryResponse, WriteBlobResponse,
|
||||
SandboxFileEntry, SandboxFileListResponse, SshAccessRequest, SshAccessResponse,
|
||||
StageStatus as ApiStageStatus, StartRunRequest, SubmitAnswerRequest, SystemFeatures,
|
||||
SystemInfoResponse, SystemRunCounts, TimelineEntryResponse, WriteBlobResponse,
|
||||
};
|
||||
use fabro_auth::{
|
||||
CredentialSource, VaultCredentialSource, auth_issue_message, parse_credential_secret,
|
||||
|
|
@ -1826,20 +1826,12 @@ async fn list_secrets(_auth: AuthenticatedService, State(state): State<Arc<AppSt
|
|||
(StatusCode::OK, Json(serde_json::json!({ "data": data }))).into_response()
|
||||
}
|
||||
|
||||
fn secret_type_from_api(secret_type: ApiSecretType) -> SecretType {
|
||||
match secret_type {
|
||||
ApiSecretType::Environment => SecretType::Environment,
|
||||
ApiSecretType::File => SecretType::File,
|
||||
ApiSecretType::Credential => SecretType::Credential,
|
||||
}
|
||||
}
|
||||
|
||||
async fn create_secret(
|
||||
_auth: AuthenticatedService,
|
||||
State(state): State<Arc<AppState>>,
|
||||
Json(body): Json<CreateSecretRequest>,
|
||||
) -> Response {
|
||||
let secret_type = secret_type_from_api(body.type_);
|
||||
let secret_type = body.type_;
|
||||
let name = body.name;
|
||||
let value = body.value;
|
||||
let description = body.description;
|
||||
|
|
@ -5407,14 +5399,14 @@ impl<'a> RunPrInputs<'a> {
|
|||
"Run spec missing from store.",
|
||||
)
|
||||
})?;
|
||||
let origin_url = run_spec.repo_origin_url.as_deref().ok_or_else(|| {
|
||||
let origin_url = run_spec.repo_origin_url().ok_or_else(|| {
|
||||
ApiError::with_code(
|
||||
StatusCode::BAD_REQUEST,
|
||||
"Run has no repo origin URL — pull request creation requires git metadata.",
|
||||
"missing_repo_origin",
|
||||
)
|
||||
})?;
|
||||
let base_branch = run_spec.base_branch.as_deref().ok_or_else(|| {
|
||||
let base_branch = run_spec.base_branch().ok_or_else(|| {
|
||||
ApiError::with_code(
|
||||
StatusCode::BAD_REQUEST,
|
||||
"Run has no base branch — pull request creation requires git metadata.",
|
||||
|
|
@ -9724,19 +9716,27 @@ strategy = "token"
|
|||
"goal".to_string(),
|
||||
AttrValue::String("Ship the server-side PR".to_string()),
|
||||
);
|
||||
let git = match (repo_origin_url, base_branch) {
|
||||
(Some(origin), Some(branch)) => Some(fabro_types::GitContext {
|
||||
origin_url: origin.to_string(),
|
||||
branch: branch.to_string(),
|
||||
sha: None,
|
||||
dirty: fabro_types::DirtyStatus::Clean,
|
||||
push_outcome: fabro_types::PreRunPushOutcome::NotAttempted,
|
||||
}),
|
||||
_ => None,
|
||||
};
|
||||
let run_spec = RunSpec {
|
||||
run_id,
|
||||
settings: fabro_types::WorkflowSettings::default(),
|
||||
graph,
|
||||
workflow_slug: Some("test".to_string()),
|
||||
source_directory: Some("/tmp/project".to_string()),
|
||||
repo_origin_url: repo_origin_url.map(str::to_string),
|
||||
base_branch: base_branch.map(str::to_string),
|
||||
git: git.clone(),
|
||||
labels: HashMap::new(),
|
||||
provenance: None,
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
pre_run_git: None,
|
||||
fork_source_ref: None,
|
||||
in_place: false,
|
||||
};
|
||||
|
|
@ -9751,13 +9751,11 @@ strategy = "token"
|
|||
labels: run_spec.labels.clone().into_iter().collect(),
|
||||
run_dir: run_spec.source_directory.clone().unwrap_or_default(),
|
||||
source_directory: run_spec.source_directory.clone(),
|
||||
repo_origin_url: run_spec.repo_origin_url.clone(),
|
||||
base_branch: run_spec.base_branch.clone(),
|
||||
workflow_slug: run_spec.workflow_slug.clone(),
|
||||
db_prefix: None,
|
||||
provenance: run_spec.provenance.clone(),
|
||||
manifest_blob: None,
|
||||
pre_run_git: None,
|
||||
git,
|
||||
fork_source_ref: None,
|
||||
in_place: false,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -54,13 +54,11 @@ impl RunProjectionReducer for RunProjection {
|
|||
graph: props.graph.clone(),
|
||||
workflow_slug: props.workflow_slug.clone(),
|
||||
source_directory: props.source_directory.clone(),
|
||||
repo_origin_url: props.repo_origin_url.clone(),
|
||||
base_branch: props.base_branch.clone(),
|
||||
labels,
|
||||
provenance: props.provenance.clone(),
|
||||
manifest_blob: props.manifest_blob,
|
||||
definition_blob: None,
|
||||
pre_run_git: props.pre_run_git.clone(),
|
||||
git: props.git.clone(),
|
||||
fork_source_ref: props.fork_source_ref.clone(),
|
||||
in_place: props.in_place,
|
||||
});
|
||||
|
|
@ -397,7 +395,8 @@ pub(crate) fn build_summary(state: &RunProjection, run_id: &RunId) -> RunSummary
|
|||
state
|
||||
.spec
|
||||
.as_ref()
|
||||
.and_then(|spec| spec.repo_origin_url.clone()),
|
||||
.and_then(|spec| spec.git.as_ref())
|
||||
.map(|git| git.origin_url.clone()),
|
||||
state.start.as_ref().map(|start| start.start_time),
|
||||
state.status.unwrap_or(RunStatus::Submitted),
|
||||
state.pending_control,
|
||||
|
|
@ -990,13 +989,11 @@ mod tests {
|
|||
graph: fabro_types::Graph::new("test"),
|
||||
workflow_slug: Some("test".to_string()),
|
||||
source_directory: Some("/tmp/repo".to_string()),
|
||||
repo_origin_url: None,
|
||||
base_branch: None,
|
||||
git: None,
|
||||
labels: HashMap::new(),
|
||||
provenance: None,
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
pre_run_git: None,
|
||||
fork_source_ref: None,
|
||||
in_place: false,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -357,13 +357,17 @@ mod tests {
|
|||
graph,
|
||||
workflow_slug: Some("night-sky".to_string()),
|
||||
source_directory: Some(format!("/tmp/{label}")),
|
||||
repo_origin_url: Some("https://github.com/fabro-sh/fabro".to_string()),
|
||||
base_branch: Some("main".to_string()),
|
||||
labels: std::collections::HashMap::from([("team".to_string(), "infra".to_string())]),
|
||||
provenance: None,
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
pre_run_git: None,
|
||||
git: Some(fabro_types::GitContext {
|
||||
origin_url: "https://github.com/fabro-sh/fabro".to_string(),
|
||||
branch: "main".to_string(),
|
||||
sha: None,
|
||||
dirty: fabro_types::DirtyStatus::Clean,
|
||||
push_outcome: fabro_types::PreRunPushOutcome::NotAttempted,
|
||||
}),
|
||||
fork_source_ref: None,
|
||||
in_place: false,
|
||||
}
|
||||
|
|
@ -400,8 +404,7 @@ mod tests {
|
|||
"workflow_slug": run_spec.workflow_slug,
|
||||
"source_directory": run_spec.source_directory,
|
||||
"run_dir": format!("/tmp/{label}"),
|
||||
"repo_origin_url": run_spec.repo_origin_url,
|
||||
"base_branch": run_spec.base_branch,
|
||||
"git": run_spec.git,
|
||||
"labels": run_spec.labels,
|
||||
}),
|
||||
))
|
||||
|
|
|
|||
|
|
@ -17,13 +17,17 @@ fn sample_run_spec() -> RunSpec {
|
|||
graph: Graph::new("ship"),
|
||||
workflow_slug: Some("demo".to_string()),
|
||||
source_directory: Some("/tmp/project".to_string()),
|
||||
repo_origin_url: Some("https://github.com/fabro-sh/fabro.git".to_string()),
|
||||
base_branch: Some("main".to_string()),
|
||||
labels: HashMap::from([("team".to_string(), "platform".to_string())]),
|
||||
provenance: None,
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
pre_run_git: None,
|
||||
git: Some(fabro_types::GitContext {
|
||||
origin_url: "https://github.com/fabro-sh/fabro.git".to_string(),
|
||||
branch: "main".to_string(),
|
||||
sha: None,
|
||||
dirty: fabro_types::DirtyStatus::Clean,
|
||||
push_outcome: fabro_types::PreRunPushOutcome::NotAttempted,
|
||||
}),
|
||||
fork_source_ref: None,
|
||||
in_place: false,
|
||||
}
|
||||
|
|
|
|||
7
lib/crates/fabro-types/src/diff.rs
Normal file
7
lib/crates/fabro-types/src/diff.rs
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct DiffStats {
|
||||
pub additions: i64,
|
||||
pub deletions: i64,
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@ pub mod blob_ref;
|
|||
pub mod checkpoint;
|
||||
pub mod conclusion;
|
||||
pub mod dense;
|
||||
pub mod diff;
|
||||
pub mod event_envelope;
|
||||
pub mod failure_signature;
|
||||
pub mod graph;
|
||||
|
|
@ -23,6 +24,7 @@ pub mod run_id;
|
|||
pub mod run_projection;
|
||||
pub mod run_summary;
|
||||
pub mod sandbox_record;
|
||||
pub mod secret;
|
||||
pub mod settings;
|
||||
pub mod stage_id;
|
||||
pub mod start;
|
||||
|
|
@ -42,6 +44,7 @@ pub use blob_ref::{
|
|||
pub use checkpoint::Checkpoint;
|
||||
pub use conclusion::{Conclusion, StageSummary};
|
||||
pub use dense::{ServerSettings, UserSettings, WorkflowSettings};
|
||||
pub use diff::DiffStats;
|
||||
pub use event_envelope::EventEnvelope;
|
||||
pub use failure_signature::FailureSignature;
|
||||
pub use graph::{AttrValue, Edge, Graph, Node, is_llm_handler_type, shape_to_handler_type};
|
||||
|
|
@ -57,8 +60,8 @@ pub use retro::{
|
|||
OpenItemKind, Retro, RetroNarrative, SmoothnessRating, StageRetro,
|
||||
};
|
||||
pub use run::{
|
||||
DirtyStatus, ForkSourceRef, PreRunGitContext, PreRunPushOutcome, RunAuthMethod,
|
||||
RunClientProvenance, RunProvenance, RunServerProvenance, RunSpec, RunSubjectProvenance,
|
||||
DirtyStatus, ForkSourceRef, GitContext, PreRunPushOutcome, RunAuthMethod, RunClientProvenance,
|
||||
RunProvenance, RunServerProvenance, RunSpec, RunSubjectProvenance,
|
||||
};
|
||||
pub use run_blob_id::RunBlobId;
|
||||
pub use run_event::{ActorKind, ActorRef, EventBody, RunEvent, RunNoticeLevel};
|
||||
|
|
@ -66,6 +69,7 @@ pub use run_id::{RunId, fixtures};
|
|||
pub use run_projection::{NodeState, PendingInterviewRecord, RunProjection};
|
||||
pub use run_summary::RunSummary;
|
||||
pub use sandbox_record::SandboxRecord;
|
||||
pub use secret::SecretType;
|
||||
pub use stage_id::{ParallelBranchId, StageId};
|
||||
pub use start::StartRecord;
|
||||
pub use status::{
|
||||
|
|
|
|||
|
|
@ -76,11 +76,13 @@ pub enum PreRunPushOutcome {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct PreRunGitContext {
|
||||
pub struct GitContext {
|
||||
pub origin_url: String,
|
||||
pub branch: String,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub display_base_sha: Option<String>,
|
||||
pub local_dirty: DirtyStatus,
|
||||
pub push_outcome: PreRunPushOutcome,
|
||||
pub sha: Option<String>,
|
||||
pub dirty: DirtyStatus,
|
||||
pub push_outcome: PreRunPushOutcome,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
|
|
@ -98,10 +100,6 @@ pub struct RunSpec {
|
|||
pub workflow_slug: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub source_directory: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub repo_origin_url: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub base_branch: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "HashMap::is_empty")]
|
||||
pub labels: HashMap<String, String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
|
|
@ -111,7 +109,7 @@ pub struct RunSpec {
|
|||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub definition_blob: Option<RunBlobId>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub pre_run_git: Option<PreRunGitContext>,
|
||||
pub git: Option<GitContext>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub fork_source_ref: Option<ForkSourceRef>,
|
||||
#[serde(default)]
|
||||
|
|
@ -151,17 +149,17 @@ impl RunSpec {
|
|||
|
||||
#[must_use]
|
||||
pub fn repo_origin_url(&self) -> Option<&str> {
|
||||
self.repo_origin_url.as_deref()
|
||||
self.git.as_ref().map(|git| git.origin_url.as_str())
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn base_branch(&self) -> Option<&str> {
|
||||
self.base_branch.as_deref()
|
||||
self.git.as_ref().map(|git| git.branch.as_str())
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn pre_run_git(&self) -> Option<&PreRunGitContext> {
|
||||
self.pre_run_git.as_ref()
|
||||
pub fn git(&self) -> Option<&GitContext> {
|
||||
self.git.as_ref()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize};
|
|||
use super::{ActorRef, BilledTokenCounts, RunNoticeLevel};
|
||||
use crate::status::{BlockedReason, FailureReason, SuccessReason};
|
||||
use crate::{
|
||||
ForkSourceRef, Graph, PreRunGitContext, RunBlobId, RunControlAction, RunId, RunProvenance,
|
||||
ForkSourceRef, GitContext, Graph, RunBlobId, RunControlAction, RunId, RunProvenance,
|
||||
WorkflowSettings,
|
||||
};
|
||||
|
||||
|
|
@ -23,10 +23,6 @@ pub struct RunCreatedProps {
|
|||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub source_directory: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub repo_origin_url: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub base_branch: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub workflow_slug: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub db_prefix: Option<String>,
|
||||
|
|
@ -35,7 +31,7 @@ pub struct RunCreatedProps {
|
|||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub manifest_blob: Option<RunBlobId>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub pre_run_git: Option<PreRunGitContext>,
|
||||
pub git: Option<GitContext>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub fork_source_ref: Option<ForkSourceRef>,
|
||||
#[serde(default)]
|
||||
|
|
|
|||
12
lib/crates/fabro-types/src/secret.rs
Normal file
12
lib/crates/fabro-types/src/secret.rs
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use strum::Display;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Display, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum SecretType {
|
||||
#[default]
|
||||
Environment,
|
||||
File,
|
||||
Credential,
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
use std::collections::BTreeMap;
|
||||
|
||||
use fabro_types::graph::Graph;
|
||||
use fabro_types::run::{DirtyStatus, ForkSourceRef, PreRunGitContext, PreRunPushOutcome};
|
||||
use fabro_types::run::{DirtyStatus, ForkSourceRef, GitContext, PreRunPushOutcome};
|
||||
use fabro_types::run_event::run::RunCreatedProps;
|
||||
use fabro_types::settings::InterpString;
|
||||
use fabro_types::settings::run::RunGoal;
|
||||
|
|
@ -23,16 +23,16 @@ fn run_created_props_round_trip_templated_settings() {
|
|||
labels: BTreeMap::from([("team".to_string(), "platform".to_string())]),
|
||||
run_dir: "/tmp/run".to_string(),
|
||||
source_directory: Some("/Users/client/project".to_string()),
|
||||
repo_origin_url: Some("https://github.com/fabro-sh/fabro.git".to_string()),
|
||||
base_branch: Some("main".to_string()),
|
||||
workflow_slug: Some("demo".to_string()),
|
||||
db_prefix: Some("run_".to_string()),
|
||||
provenance: None,
|
||||
manifest_blob: None,
|
||||
pre_run_git: Some(PreRunGitContext {
|
||||
display_base_sha: Some("abc123".to_string()),
|
||||
local_dirty: DirtyStatus::Unknown,
|
||||
push_outcome: PreRunPushOutcome::SkippedNoRemote,
|
||||
git: Some(GitContext {
|
||||
origin_url: "https://github.com/fabro-sh/fabro.git".to_string(),
|
||||
branch: "main".to_string(),
|
||||
sha: None,
|
||||
dirty: DirtyStatus::Unknown,
|
||||
push_outcome: PreRunPushOutcome::SkippedNoRemote,
|
||||
}),
|
||||
fork_source_ref: Some(ForkSourceRef {
|
||||
source_run_id: fixtures::RUN_2,
|
||||
|
|
@ -46,9 +46,12 @@ fn run_created_props_round_trip_templated_settings() {
|
|||
assert!(json.get("host_repo_path").is_none());
|
||||
assert_eq!(json["source_directory"], "/Users/client/project");
|
||||
assert_eq!(
|
||||
json["pre_run_git"]["push_outcome"]["type"],
|
||||
"skipped_no_remote"
|
||||
json["git"]["origin_url"],
|
||||
"https://github.com/fabro-sh/fabro.git"
|
||||
);
|
||||
assert_eq!(json["git"]["branch"], "main");
|
||||
assert_eq!(json["git"]["dirty"], "unknown");
|
||||
assert_eq!(json["git"]["push_outcome"]["type"], "skipped_no_remote");
|
||||
assert_eq!(json["in_place"], true);
|
||||
|
||||
let round_trip: RunCreatedProps =
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use fabro_types::graph::Graph;
|
||||
use fabro_types::run::{DirtyStatus, PreRunGitContext, PreRunPushOutcome, RunSpec};
|
||||
use fabro_types::run::{DirtyStatus, GitContext, PreRunPushOutcome, RunSpec};
|
||||
use fabro_types::{WorkflowSettings, fixtures};
|
||||
|
||||
fn sample_run_spec() -> RunSpec {
|
||||
|
|
@ -11,16 +11,16 @@ fn sample_run_spec() -> RunSpec {
|
|||
graph: Graph::new("ship"),
|
||||
workflow_slug: Some("demo".to_string()),
|
||||
source_directory: Some("/Users/client/project".to_string()),
|
||||
repo_origin_url: Some("https://github.com/fabro-sh/fabro.git".to_string()),
|
||||
base_branch: Some("main".to_string()),
|
||||
labels: HashMap::from([("team".to_string(), "platform".to_string())]),
|
||||
provenance: None,
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
pre_run_git: Some(PreRunGitContext {
|
||||
display_base_sha: Some("abc123".to_string()),
|
||||
local_dirty: DirtyStatus::Dirty,
|
||||
push_outcome: PreRunPushOutcome::SkippedRemoteMismatch {
|
||||
git: Some(GitContext {
|
||||
origin_url: "https://github.com/fabro-sh/fabro.git".to_string(),
|
||||
branch: "main".to_string(),
|
||||
sha: Some("abc123".to_string()),
|
||||
dirty: DirtyStatus::Dirty,
|
||||
push_outcome: PreRunPushOutcome::SkippedRemoteMismatch {
|
||||
remote: "https://github.com/user/fork.git".to_string(),
|
||||
repo_origin_url: "https://github.com/fabro-sh/fabro.git".to_string(),
|
||||
},
|
||||
|
|
@ -44,9 +44,7 @@ fn run_spec_getters_return_declared_fields() {
|
|||
Some("platform")
|
||||
);
|
||||
assert_eq!(
|
||||
run_spec
|
||||
.pre_run_git()
|
||||
.and_then(|ctx| ctx.display_base_sha.as_deref()),
|
||||
run_spec.git().and_then(|ctx| ctx.sha.as_deref()),
|
||||
Some("abc123")
|
||||
);
|
||||
assert_eq!(
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use fabro_types::graph::Graph;
|
||||
use fabro_types::run::{DirtyStatus, ForkSourceRef, PreRunGitContext, PreRunPushOutcome, RunSpec};
|
||||
use fabro_types::run::{DirtyStatus, ForkSourceRef, GitContext, PreRunPushOutcome, RunSpec};
|
||||
use fabro_types::settings::InterpString;
|
||||
use fabro_types::settings::run::RunGoal;
|
||||
use fabro_types::{WorkflowSettings, fixtures};
|
||||
|
|
@ -20,16 +20,16 @@ fn run_spec_round_trips_templated_settings() {
|
|||
graph: Graph::new("ship"),
|
||||
workflow_slug: Some("demo".to_string()),
|
||||
source_directory: Some("/Users/client/project".to_string()),
|
||||
repo_origin_url: Some("https://github.com/fabro-sh/fabro.git".to_string()),
|
||||
base_branch: Some("main".to_string()),
|
||||
labels: HashMap::from([("team".to_string(), "platform".to_string())]),
|
||||
provenance: None,
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
pre_run_git: Some(PreRunGitContext {
|
||||
display_base_sha: Some("abc123".to_string()),
|
||||
local_dirty: DirtyStatus::Clean,
|
||||
push_outcome: PreRunPushOutcome::Succeeded {
|
||||
git: Some(GitContext {
|
||||
origin_url: "https://github.com/fabro-sh/fabro.git".to_string(),
|
||||
branch: "main".to_string(),
|
||||
sha: Some("abc123".to_string()),
|
||||
dirty: DirtyStatus::Clean,
|
||||
push_outcome: PreRunPushOutcome::Succeeded {
|
||||
remote: "origin".to_string(),
|
||||
branch: "main".to_string(),
|
||||
},
|
||||
|
|
@ -45,8 +45,14 @@ fn run_spec_round_trips_templated_settings() {
|
|||
assert!(json.get("working_directory").is_none());
|
||||
assert!(json.get("host_repo_path").is_none());
|
||||
assert_eq!(json["source_directory"], "/Users/client/project");
|
||||
assert_eq!(json["pre_run_git"]["local_dirty"], "clean");
|
||||
assert_eq!(json["pre_run_git"]["push_outcome"]["type"], "succeeded");
|
||||
assert_eq!(
|
||||
json["git"]["origin_url"],
|
||||
"https://github.com/fabro-sh/fabro.git"
|
||||
);
|
||||
assert_eq!(json["git"]["branch"], "main");
|
||||
assert_eq!(json["git"]["sha"], "abc123");
|
||||
assert_eq!(json["git"]["dirty"], "clean");
|
||||
assert_eq!(json["git"]["push_outcome"]["type"], "succeeded");
|
||||
assert_eq!(json["fork_source_ref"]["checkpoint_sha"], "def456");
|
||||
assert_eq!(json["in_place"], false);
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ workspace = true
|
|||
|
||||
[dependencies]
|
||||
chrono.workspace = true
|
||||
fabro-types = { path = "../fabro-types" }
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
ulid.workspace = true
|
||||
|
|
|
|||
|
|
@ -7,14 +7,7 @@ use std::collections::HashMap;
|
|||
use std::path::{Component, Path, PathBuf};
|
||||
use std::{fmt, io};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, serde::Serialize, serde::Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum SecretType {
|
||||
#[default]
|
||||
Environment,
|
||||
File,
|
||||
Credential,
|
||||
}
|
||||
pub use fabro_types::SecretType;
|
||||
|
||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||
pub struct SecretEntry {
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ use std::sync::Arc;
|
|||
use std::sync::atomic::{AtomicI64, Ordering};
|
||||
|
||||
use ::fabro_types::{
|
||||
ActorRef, BilledTokenCounts, BlockedReason, FailureReason, ForkSourceRef, ParallelBranchId,
|
||||
PreRunGitContext, PullRequestRecord, RunBlobId, RunControlAction, RunEvent, RunId,
|
||||
ActorRef, BilledTokenCounts, BlockedReason, FailureReason, ForkSourceRef, GitContext,
|
||||
ParallelBranchId, PullRequestRecord, RunBlobId, RunControlAction, RunEvent, RunId,
|
||||
RunProvenance, StageId, StageStatus, SuccessReason, run_event as fabro_types,
|
||||
};
|
||||
use anyhow::{Context, Result};
|
||||
|
|
@ -49,10 +49,6 @@ pub enum Event {
|
|||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
source_directory: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
repo_origin_url: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
base_branch: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
workflow_slug: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
db_prefix: Option<String>,
|
||||
|
|
@ -61,7 +57,7 @@ pub enum Event {
|
|||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
manifest_blob: Option<RunBlobId>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pre_run_git: Option<PreRunGitContext>,
|
||||
git: Option<GitContext>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
fork_source_ref: Option<ForkSourceRef>,
|
||||
#[serde(default)]
|
||||
|
|
@ -1522,13 +1518,11 @@ fn event_body_from_event(event: &Event) -> EventBody {
|
|||
labels,
|
||||
run_dir,
|
||||
source_directory,
|
||||
repo_origin_url,
|
||||
base_branch,
|
||||
workflow_slug,
|
||||
db_prefix,
|
||||
provenance,
|
||||
manifest_blob,
|
||||
pre_run_git,
|
||||
git,
|
||||
fork_source_ref,
|
||||
in_place,
|
||||
..
|
||||
|
|
@ -1541,13 +1535,11 @@ fn event_body_from_event(event: &Event) -> EventBody {
|
|||
labels: labels.clone(),
|
||||
run_dir: run_dir.clone(),
|
||||
source_directory: source_directory.clone(),
|
||||
repo_origin_url: repo_origin_url.clone(),
|
||||
base_branch: base_branch.clone(),
|
||||
workflow_slug: workflow_slug.clone(),
|
||||
db_prefix: db_prefix.clone(),
|
||||
provenance: provenance.clone(),
|
||||
manifest_blob: *manifest_blob,
|
||||
pre_run_git: pre_run_git.clone(),
|
||||
git: git.clone(),
|
||||
fork_source_ref: fork_source_ref.clone(),
|
||||
in_place: *in_place,
|
||||
}),
|
||||
|
|
@ -3679,13 +3671,11 @@ mod tests {
|
|||
labels: BTreeMap::default(),
|
||||
run_dir: "/tmp/run".to_string(),
|
||||
source_directory: Some("/tmp/run".to_string()),
|
||||
repo_origin_url: None,
|
||||
base_branch: None,
|
||||
workflow_slug: None,
|
||||
db_prefix: None,
|
||||
provenance: Some(provenance),
|
||||
manifest_blob: None,
|
||||
pre_run_git: None,
|
||||
git: None,
|
||||
fork_source_ref: None,
|
||||
in_place: false,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ use fabro_sandbox::SandboxProvider;
|
|||
use fabro_store::Database;
|
||||
use fabro_template::{TemplateContext, render as render_template};
|
||||
use fabro_types::settings::run::{RunMode, RunNamespace};
|
||||
use fabro_types::{ForkSourceRef, PreRunGitContext, RunId, RunProvenance, WorkflowSettings};
|
||||
use fabro_types::{ForkSourceRef, GitContext, RunId, RunProvenance, WorkflowSettings};
|
||||
use fabro_util::json::normalize_json_value;
|
||||
use tokio::task::spawn_blocking;
|
||||
|
||||
|
|
@ -41,9 +41,7 @@ pub struct CreateRunInput {
|
|||
pub workflow_bundle: Option<WorkflowBundle>,
|
||||
pub submitted_manifest_bytes: Option<Vec<u8>>,
|
||||
pub run_id: Option<RunId>,
|
||||
pub repo_origin_url: Option<String>,
|
||||
pub base_branch: Option<String>,
|
||||
pub pre_run_git: Option<PreRunGitContext>,
|
||||
pub git: Option<GitContext>,
|
||||
pub fork_source_ref: Option<ForkSourceRef>,
|
||||
pub in_place: bool,
|
||||
pub provenance: Option<RunProvenance>,
|
||||
|
|
@ -64,10 +62,8 @@ struct PersistCreateOptions {
|
|||
run_dir: Option<PathBuf>,
|
||||
workflow_slug: Option<String>,
|
||||
labels: HashMap<String, String>,
|
||||
base_branch: Option<String>,
|
||||
source_directory: Option<String>,
|
||||
repo_origin_url: Option<String>,
|
||||
pre_run_git: Option<PreRunGitContext>,
|
||||
git: Option<GitContext>,
|
||||
fork_source_ref: Option<ForkSourceRef>,
|
||||
in_place: bool,
|
||||
provenance: Option<RunProvenance>,
|
||||
|
|
@ -101,9 +97,7 @@ pub async fn create(
|
|||
workflow_bundle,
|
||||
submitted_manifest_bytes,
|
||||
run_id,
|
||||
repo_origin_url,
|
||||
base_branch,
|
||||
pre_run_git,
|
||||
git,
|
||||
fork_source_ref,
|
||||
in_place,
|
||||
provenance,
|
||||
|
|
@ -138,10 +132,8 @@ pub async fn create(
|
|||
run_dir: Some(persisted_run_dir),
|
||||
workflow_slug: workflow_slug.or(resolved_workflow_slug),
|
||||
labels,
|
||||
base_branch,
|
||||
source_directory,
|
||||
repo_origin_url,
|
||||
pre_run_git,
|
||||
git,
|
||||
fork_source_ref,
|
||||
in_place,
|
||||
provenance,
|
||||
|
|
@ -228,13 +220,11 @@ async fn persist_created_run(
|
|||
.collect::<BTreeMap<_, _>>(),
|
||||
run_dir: persisted.run_dir().display().to_string(),
|
||||
source_directory: record.source_directory.clone(),
|
||||
repo_origin_url: record.repo_origin_url.clone(),
|
||||
base_branch: record.base_branch.clone(),
|
||||
workflow_slug: record.workflow_slug.clone(),
|
||||
db_prefix: None,
|
||||
provenance: record.provenance.clone(),
|
||||
manifest_blob,
|
||||
pre_run_git: record.pre_run_git.clone(),
|
||||
git: record.git.clone(),
|
||||
fork_source_ref: record.fork_source_ref.clone(),
|
||||
in_place: record.in_place,
|
||||
},
|
||||
|
|
@ -350,10 +340,8 @@ fn persist_validated(
|
|||
run_dir,
|
||||
workflow_slug,
|
||||
labels,
|
||||
base_branch,
|
||||
source_directory,
|
||||
repo_origin_url,
|
||||
pre_run_git,
|
||||
git,
|
||||
fork_source_ref,
|
||||
in_place,
|
||||
provenance,
|
||||
|
|
@ -376,13 +364,11 @@ fn persist_validated(
|
|||
graph: validated.graph().clone(),
|
||||
workflow_slug,
|
||||
source_directory,
|
||||
repo_origin_url,
|
||||
base_branch,
|
||||
labels,
|
||||
provenance,
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
pre_run_git,
|
||||
git,
|
||||
fork_source_ref,
|
||||
in_place,
|
||||
};
|
||||
|
|
@ -722,9 +708,7 @@ mod tests {
|
|||
workflow_bundle: None,
|
||||
submitted_manifest_bytes: None,
|
||||
run_id: None,
|
||||
repo_origin_url: None,
|
||||
base_branch: None,
|
||||
pre_run_git: None,
|
||||
git: None,
|
||||
fork_source_ref: None,
|
||||
in_place: false,
|
||||
provenance: None,
|
||||
|
|
@ -767,9 +751,7 @@ mod tests {
|
|||
workflow_bundle: None,
|
||||
submitted_manifest_bytes: None,
|
||||
run_id: None,
|
||||
repo_origin_url: None,
|
||||
base_branch: None,
|
||||
pre_run_git: None,
|
||||
git: None,
|
||||
fork_source_ref: None,
|
||||
in_place: false,
|
||||
provenance: None,
|
||||
|
|
@ -828,9 +810,13 @@ mod tests {
|
|||
workflow_bundle: None,
|
||||
submitted_manifest_bytes: None,
|
||||
run_id: Some(fixtures::RUN_1),
|
||||
repo_origin_url: None,
|
||||
base_branch: Some("main".to_string()),
|
||||
pre_run_git: None,
|
||||
git: Some(fabro_types::GitContext {
|
||||
origin_url: String::new(),
|
||||
branch: "main".to_string(),
|
||||
sha: None,
|
||||
dirty: fabro_types::DirtyStatus::Clean,
|
||||
push_outcome: fabro_types::PreRunPushOutcome::NotAttempted,
|
||||
}),
|
||||
fork_source_ref: None,
|
||||
in_place: false,
|
||||
provenance: None,
|
||||
|
|
@ -938,9 +924,7 @@ mod tests {
|
|||
workflow_bundle: None,
|
||||
submitted_manifest_bytes: None,
|
||||
run_id: Some(fixtures::RUN_2),
|
||||
repo_origin_url: None,
|
||||
base_branch: None,
|
||||
pre_run_git: None,
|
||||
git: None,
|
||||
fork_source_ref: None,
|
||||
in_place: false,
|
||||
provenance: None,
|
||||
|
|
@ -976,9 +960,13 @@ mod tests {
|
|||
workflow_bundle: None,
|
||||
submitted_manifest_bytes: None,
|
||||
run_id: Some(fixtures::RUN_2),
|
||||
repo_origin_url: Some("https://github.com/acme/widgets".to_string()),
|
||||
base_branch: None,
|
||||
pre_run_git: None,
|
||||
git: Some(fabro_types::GitContext {
|
||||
origin_url: "https://github.com/acme/widgets".to_string(),
|
||||
branch: String::new(),
|
||||
sha: None,
|
||||
dirty: fabro_types::DirtyStatus::Clean,
|
||||
push_outcome: fabro_types::PreRunPushOutcome::NotAttempted,
|
||||
}),
|
||||
fork_source_ref: None,
|
||||
in_place: false,
|
||||
provenance: None,
|
||||
|
|
@ -990,7 +978,7 @@ mod tests {
|
|||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
created.persisted.run_spec().repo_origin_url.as_deref(),
|
||||
created.persisted.run_spec().repo_origin_url(),
|
||||
Some("https://github.com/acme/widgets")
|
||||
);
|
||||
}
|
||||
|
|
@ -1042,9 +1030,7 @@ mod tests {
|
|||
workflow_bundle: None,
|
||||
submitted_manifest_bytes: None,
|
||||
run_id: Some(fixtures::RUN_3),
|
||||
repo_origin_url: None,
|
||||
base_branch: None,
|
||||
pre_run_git: None,
|
||||
git: None,
|
||||
fork_source_ref: None,
|
||||
in_place: false,
|
||||
provenance: None,
|
||||
|
|
@ -1087,9 +1073,7 @@ mod tests {
|
|||
workflow_bundle: None,
|
||||
submitted_manifest_bytes: None,
|
||||
run_id: Some(fixtures::RUN_64),
|
||||
repo_origin_url: None,
|
||||
base_branch: None,
|
||||
pre_run_git: None,
|
||||
git: None,
|
||||
fork_source_ref: None,
|
||||
in_place: false,
|
||||
provenance: Some(fabro_types::RunProvenance {
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ fn validate_source_spec(
|
|||
"target checkpoint has an empty git_commit_sha; cannot fork".to_string(),
|
||||
));
|
||||
}
|
||||
let Some(origin) = spec.repo_origin_url.as_ref() else {
|
||||
let Some(origin) = spec.repo_origin_url() else {
|
||||
return Err(Error::Validation(
|
||||
"source run has no repo_origin_url; cannot validate fork origin".to_string(),
|
||||
));
|
||||
|
|
@ -180,13 +180,11 @@ async fn persist_forked_run(
|
|||
labels: spec.labels.clone().into_iter().collect(),
|
||||
run_dir: String::new(),
|
||||
source_directory: spec.source_directory.clone(),
|
||||
repo_origin_url: spec.repo_origin_url.clone(),
|
||||
base_branch: spec.base_branch.clone(),
|
||||
workflow_slug: spec.workflow_slug.clone(),
|
||||
db_prefix: None,
|
||||
provenance: spec.provenance.clone(),
|
||||
manifest_blob: spec.manifest_blob,
|
||||
pre_run_git: spec.pre_run_git.clone(),
|
||||
git: spec.git.clone(),
|
||||
fork_source_ref: spec.fork_source_ref.clone(),
|
||||
in_place: spec.in_place,
|
||||
})
|
||||
|
|
@ -330,13 +328,17 @@ mod tests {
|
|||
labels: BTreeMap::new(),
|
||||
run_dir: "/tmp/source".to_string(),
|
||||
source_directory: Some("/client/source".to_string()),
|
||||
repo_origin_url: Some("https://github.com/example/repo.git".to_string()),
|
||||
base_branch: Some("main".to_string()),
|
||||
workflow_slug: Some("fork-source".to_string()),
|
||||
db_prefix: None,
|
||||
provenance: None,
|
||||
manifest_blob: None,
|
||||
pre_run_git: None,
|
||||
git: Some(fabro_types::GitContext {
|
||||
origin_url: "https://github.com/example/repo.git".to_string(),
|
||||
branch: "main".to_string(),
|
||||
sha: None,
|
||||
dirty: fabro_types::DirtyStatus::Clean,
|
||||
push_outcome: fabro_types::PreRunPushOutcome::NotAttempted,
|
||||
}),
|
||||
fork_source_ref: None,
|
||||
in_place: false,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -359,8 +359,8 @@ impl RunSession {
|
|||
config: resolve_docker_config(resolved).unwrap_or_default(),
|
||||
github_app: services.github_app.clone(),
|
||||
run_id: Some(record.run_id),
|
||||
clone_origin_url: record.repo_origin_url.clone(),
|
||||
clone_branch: record.base_branch.clone(),
|
||||
clone_origin_url: record.repo_origin_url().map(str::to_string),
|
||||
clone_branch: record.base_branch().map(str::to_string),
|
||||
},
|
||||
SandboxProvider::Daytona => {
|
||||
let api_key = match &services.vault {
|
||||
|
|
@ -375,8 +375,8 @@ impl RunSession {
|
|||
config: resolve_daytona_config(resolved).unwrap_or_default(),
|
||||
github_app: services.github_app.clone(),
|
||||
run_id: Some(record.run_id),
|
||||
clone_origin_url: record.repo_origin_url.clone(),
|
||||
clone_branch: record.base_branch.clone(),
|
||||
clone_origin_url: record.repo_origin_url().map(str::to_string),
|
||||
clone_branch: record.base_branch().map(str::to_string),
|
||||
api_key,
|
||||
}
|
||||
}
|
||||
|
|
@ -394,7 +394,7 @@ impl RunSession {
|
|||
devcontainer_env: HashMap::new(),
|
||||
toml_env,
|
||||
github_permissions,
|
||||
origin_url: record.repo_origin_url.clone(),
|
||||
origin_url: record.repo_origin_url().map(str::to_string),
|
||||
};
|
||||
|
||||
let devcontainer = resolved.sandbox.devcontainer.then(|| DevcontainerSpec {
|
||||
|
|
@ -447,7 +447,7 @@ impl RunSession {
|
|||
preserve_sandbox: resolved.sandbox.preserve,
|
||||
pr_config,
|
||||
pr_github_app: services.github_app,
|
||||
pr_origin_url: record.repo_origin_url.clone(),
|
||||
pr_origin_url: record.repo_origin_url().map(str::to_string),
|
||||
pr_model: model,
|
||||
workflow_path,
|
||||
workflow_bundle,
|
||||
|
|
@ -698,9 +698,9 @@ impl RunSession {
|
|||
labels: record.labels.clone(),
|
||||
workflow_slug: record.workflow_slug.clone(),
|
||||
github_app: self.github_app.clone(),
|
||||
pre_run_git: record.pre_run_git.clone(),
|
||||
pre_run_git: record.git.clone(),
|
||||
fork_source_ref: record.fork_source_ref.clone(),
|
||||
base_branch: record.base_branch.clone(),
|
||||
base_branch: record.base_branch().map(str::to_string),
|
||||
display_base_sha: None,
|
||||
git: self.git.clone(),
|
||||
};
|
||||
|
|
@ -1074,9 +1074,7 @@ mod tests {
|
|||
workflow_bundle: None,
|
||||
submitted_manifest_bytes: None,
|
||||
run_id: Some(fixtures::RUN_1),
|
||||
repo_origin_url: None,
|
||||
base_branch: None,
|
||||
pre_run_git: None,
|
||||
git: None,
|
||||
fork_source_ref: None,
|
||||
in_place: false,
|
||||
provenance: None,
|
||||
|
|
@ -1254,9 +1252,7 @@ mod tests {
|
|||
workflow_bundle: Some(workflow_bundle),
|
||||
submitted_manifest_bytes: None,
|
||||
run_id: Some(fixtures::RUN_1),
|
||||
repo_origin_url: None,
|
||||
base_branch: None,
|
||||
pre_run_git: None,
|
||||
git: None,
|
||||
fork_source_ref: None,
|
||||
in_place: false,
|
||||
provenance: None,
|
||||
|
|
|
|||
|
|
@ -145,13 +145,17 @@ fn persisted_workflow(graph: Graph, source: String, run_dir: &Path, run_id: RunI
|
|||
.display()
|
||||
.to_string(),
|
||||
),
|
||||
repo_origin_url: None,
|
||||
base_branch: Some("main".to_string()),
|
||||
git: Some(fabro_types::GitContext {
|
||||
origin_url: String::new(),
|
||||
branch: "main".to_string(),
|
||||
sha: None,
|
||||
dirty: fabro_types::DirtyStatus::Clean,
|
||||
push_outcome: fabro_types::PreRunPushOutcome::NotAttempted,
|
||||
}),
|
||||
labels: HashMap::new(),
|
||||
provenance: None,
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
pre_run_git: None,
|
||||
fork_source_ref: None,
|
||||
in_place: false,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ fn resolve_worktree_plan(options: &mut InitOptions) -> Option<WorktreePlan> {
|
|||
.run_options
|
||||
.pre_run_git
|
||||
.as_ref()
|
||||
.map(|git| git.local_dirty);
|
||||
.map(|git| git.dirty);
|
||||
|
||||
if matches!(local_dirty, Some(fabro_types::DirtyStatus::Dirty)) {
|
||||
let env_name = if !is_local {
|
||||
|
|
@ -162,7 +162,7 @@ fn resolve_worktree_plan(options: &mut InitOptions) -> Option<WorktreePlan> {
|
|||
.run_options
|
||||
.pre_run_git
|
||||
.as_ref()
|
||||
.and_then(|git| git.display_base_sha.clone());
|
||||
.and_then(|git| git.sha.clone());
|
||||
return None;
|
||||
}
|
||||
|
||||
|
|
@ -184,7 +184,7 @@ fn resolve_worktree_plan(options: &mut InitOptions) -> Option<WorktreePlan> {
|
|||
.run_options
|
||||
.pre_run_git
|
||||
.as_ref()
|
||||
.and_then(|git| git.display_base_sha.clone()),
|
||||
.and_then(|git| git.sha.clone()),
|
||||
)
|
||||
};
|
||||
options.run_options.display_base_sha.clone_from(&base_sha);
|
||||
|
|
@ -865,13 +865,17 @@ mod tests {
|
|||
graph,
|
||||
workflow_slug: Some("test".to_string()),
|
||||
source_directory: Some(std::env::current_dir().unwrap().display().to_string()),
|
||||
repo_origin_url: None,
|
||||
base_branch: Some("main".to_string()),
|
||||
git: Some(fabro_types::GitContext {
|
||||
origin_url: String::new(),
|
||||
branch: "main".to_string(),
|
||||
sha: None,
|
||||
dirty: fabro_types::DirtyStatus::Clean,
|
||||
push_outcome: fabro_types::PreRunPushOutcome::NotAttempted,
|
||||
}),
|
||||
labels: HashMap::new(),
|
||||
provenance: None,
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
pre_run_git: None,
|
||||
fork_source_ref: None,
|
||||
in_place: false,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -137,8 +137,13 @@ mod tests {
|
|||
graph,
|
||||
workflow_slug: Some("ship".to_string()),
|
||||
source_directory: Some("/tmp/project".to_string()),
|
||||
repo_origin_url: None,
|
||||
base_branch: Some("main".to_string()),
|
||||
git: Some(fabro_types::GitContext {
|
||||
origin_url: String::new(),
|
||||
branch: "main".to_string(),
|
||||
sha: None,
|
||||
dirty: fabro_types::DirtyStatus::Clean,
|
||||
push_outcome: fabro_types::PreRunPushOutcome::NotAttempted,
|
||||
}),
|
||||
labels: HashMap::from([
|
||||
("env".to_string(), "test".to_string()),
|
||||
("team".to_string(), "workflow".to_string()),
|
||||
|
|
@ -146,7 +151,6 @@ mod tests {
|
|||
provenance: None,
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
pre_run_git: None,
|
||||
fork_source_ref: None,
|
||||
in_place: false,
|
||||
}
|
||||
|
|
@ -164,13 +168,11 @@ mod tests {
|
|||
labels: record.labels.clone().into_iter().collect(),
|
||||
run_dir: run_dir.to_string_lossy().to_string(),
|
||||
source_directory: record.source_directory.clone(),
|
||||
repo_origin_url: record.repo_origin_url.clone(),
|
||||
base_branch: record.base_branch.clone(),
|
||||
workflow_slug: record.workflow_slug.clone(),
|
||||
db_prefix: None,
|
||||
provenance: record.provenance.clone(),
|
||||
manifest_blob: None,
|
||||
pre_run_git: record.pre_run_git.clone(),
|
||||
git: record.git.clone(),
|
||||
fork_source_ref: record.fork_source_ref.clone(),
|
||||
in_place: record.in_place,
|
||||
})
|
||||
|
|
@ -265,7 +267,7 @@ mod tests {
|
|||
);
|
||||
assert_eq!(loaded_record.workflow_slug, expected.workflow_slug);
|
||||
assert_eq!(loaded_record.source_directory, expected.source_directory);
|
||||
assert_eq!(loaded_record.base_branch, expected.base_branch);
|
||||
assert_eq!(loaded_record.base_branch(), expected.base_branch());
|
||||
assert_eq!(loaded_record.labels, expected.labels);
|
||||
assert_eq!(loaded.source(), source);
|
||||
assert!(loaded.diagnostics().is_empty());
|
||||
|
|
|
|||
|
|
@ -1172,13 +1172,17 @@ mod tests {
|
|||
graph: Graph::new("test"),
|
||||
workflow_slug: Some("test".to_string()),
|
||||
source_directory: Some("/tmp/project".to_string()),
|
||||
repo_origin_url: None,
|
||||
base_branch: Some("main".to_string()),
|
||||
git: Some(fabro_types::GitContext {
|
||||
origin_url: String::new(),
|
||||
branch: "main".to_string(),
|
||||
sha: None,
|
||||
dirty: fabro_types::DirtyStatus::Clean,
|
||||
push_outcome: fabro_types::PreRunPushOutcome::NotAttempted,
|
||||
}),
|
||||
labels: HashMap::new(),
|
||||
provenance: None,
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
pre_run_git: None,
|
||||
fork_source_ref: None,
|
||||
in_place: false,
|
||||
};
|
||||
|
|
@ -1191,13 +1195,11 @@ mod tests {
|
|||
labels: run_spec.labels.clone().into_iter().collect(),
|
||||
run_dir: "/tmp/project".to_string(),
|
||||
source_directory: run_spec.source_directory.clone(),
|
||||
repo_origin_url: run_spec.repo_origin_url.clone(),
|
||||
base_branch: run_spec.base_branch.clone(),
|
||||
workflow_slug: run_spec.workflow_slug.clone(),
|
||||
db_prefix: None,
|
||||
provenance: run_spec.provenance.clone(),
|
||||
manifest_blob: None,
|
||||
pre_run_git: None,
|
||||
git: run_spec.git.clone(),
|
||||
fork_source_ref: None,
|
||||
in_place: false,
|
||||
})
|
||||
|
|
@ -1239,13 +1241,17 @@ mod tests {
|
|||
graph: Graph::new("test"),
|
||||
workflow_slug: Some("test".to_string()),
|
||||
source_directory: Some("/tmp/project".to_string()),
|
||||
repo_origin_url: None,
|
||||
base_branch: Some("main".to_string()),
|
||||
git: Some(fabro_types::GitContext {
|
||||
origin_url: String::new(),
|
||||
branch: "main".to_string(),
|
||||
sha: None,
|
||||
dirty: fabro_types::DirtyStatus::Clean,
|
||||
push_outcome: fabro_types::PreRunPushOutcome::NotAttempted,
|
||||
}),
|
||||
labels: HashMap::new(),
|
||||
provenance: None,
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
pre_run_git: None,
|
||||
fork_source_ref: None,
|
||||
in_place: false,
|
||||
};
|
||||
|
|
@ -1258,13 +1264,11 @@ mod tests {
|
|||
labels: run_spec.labels.clone().into_iter().collect(),
|
||||
run_dir: "/tmp/project".to_string(),
|
||||
source_directory: run_spec.source_directory.clone(),
|
||||
repo_origin_url: run_spec.repo_origin_url.clone(),
|
||||
base_branch: run_spec.base_branch.clone(),
|
||||
workflow_slug: run_spec.workflow_slug.clone(),
|
||||
db_prefix: None,
|
||||
provenance: run_spec.provenance.clone(),
|
||||
manifest_blob: None,
|
||||
pre_run_git: None,
|
||||
git: run_spec.git.clone(),
|
||||
fork_source_ref: None,
|
||||
in_place: false,
|
||||
})
|
||||
|
|
@ -1539,13 +1543,11 @@ mod tests {
|
|||
graph: Graph::new("test"),
|
||||
workflow_slug: None,
|
||||
source_directory: Some(tmp.path().display().to_string()),
|
||||
repo_origin_url: None,
|
||||
base_branch: None,
|
||||
git: None,
|
||||
labels: std::collections::HashMap::new(),
|
||||
provenance: None,
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
pre_run_git: None,
|
||||
fork_source_ref: None,
|
||||
in_place: false,
|
||||
};
|
||||
|
|
@ -1558,13 +1560,11 @@ mod tests {
|
|||
labels: run_spec.labels.clone().into_iter().collect(),
|
||||
run_dir: tmp.path().display().to_string(),
|
||||
source_directory: run_spec.source_directory.clone(),
|
||||
repo_origin_url: run_spec.repo_origin_url.clone(),
|
||||
base_branch: None,
|
||||
workflow_slug: None,
|
||||
db_prefix: None,
|
||||
provenance: run_spec.provenance.clone(),
|
||||
manifest_blob: None,
|
||||
pre_run_git: None,
|
||||
git: None,
|
||||
fork_source_ref: None,
|
||||
in_place: false,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -216,13 +216,11 @@ mod tests {
|
|||
graph: Graph::new("test"),
|
||||
workflow_slug: None,
|
||||
source_directory: Some(run_dir.to_string_lossy().to_string()),
|
||||
repo_origin_url: None,
|
||||
base_branch: None,
|
||||
git: None,
|
||||
labels: std::collections::HashMap::new(),
|
||||
provenance: None,
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
pre_run_git: None,
|
||||
fork_source_ref: None,
|
||||
in_place: false,
|
||||
};
|
||||
|
|
@ -235,13 +233,11 @@ mod tests {
|
|||
labels: run_spec.labels.clone().into_iter().collect(),
|
||||
run_dir: run_dir.to_string_lossy().to_string(),
|
||||
source_directory: run_spec.source_directory.clone(),
|
||||
repo_origin_url: run_spec.repo_origin_url.clone(),
|
||||
base_branch: None,
|
||||
workflow_slug: None,
|
||||
db_prefix: None,
|
||||
provenance: run_spec.provenance.clone(),
|
||||
manifest_blob: None,
|
||||
pre_run_git: None,
|
||||
git: None,
|
||||
fork_source_ref: None,
|
||||
in_place: false,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -428,13 +428,17 @@ mod tests {
|
|||
graph: Graph::new("ship"),
|
||||
workflow_slug: Some("demo".to_string()),
|
||||
source_directory: Some("/tmp/project".to_string()),
|
||||
repo_origin_url: Some("https://github.com/fabro-sh/fabro.git".to_string()),
|
||||
base_branch: Some("main".to_string()),
|
||||
git: Some(fabro_types::GitContext {
|
||||
origin_url: "https://github.com/fabro-sh/fabro.git".to_string(),
|
||||
branch: "main".to_string(),
|
||||
sha: None,
|
||||
dirty: fabro_types::DirtyStatus::Clean,
|
||||
push_outcome: fabro_types::PreRunPushOutcome::NotAttempted,
|
||||
}),
|
||||
labels: HashMap::from([("team".to_string(), "platform".to_string())]),
|
||||
provenance: None,
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
pre_run_git: None,
|
||||
fork_source_ref: None,
|
||||
in_place: false,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -439,13 +439,17 @@ mod tests {
|
|||
graph: Graph::new("test"),
|
||||
workflow_slug: Some("test".to_string()),
|
||||
source_directory: Some("/tmp/project".to_string()),
|
||||
repo_origin_url: None,
|
||||
base_branch: Some("main".to_string()),
|
||||
git: Some(fabro_types::GitContext {
|
||||
origin_url: String::new(),
|
||||
branch: "main".to_string(),
|
||||
sha: None,
|
||||
dirty: fabro_types::DirtyStatus::Clean,
|
||||
push_outcome: fabro_types::PreRunPushOutcome::NotAttempted,
|
||||
}),
|
||||
labels: HashMap::new(),
|
||||
provenance: None,
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
pre_run_git: None,
|
||||
fork_source_ref: None,
|
||||
in_place: false,
|
||||
}
|
||||
|
|
@ -469,13 +473,11 @@ mod tests {
|
|||
labels: run_spec.labels.clone().into_iter().collect(),
|
||||
run_dir: run_dir.display().to_string(),
|
||||
source_directory: run_spec.source_directory.clone(),
|
||||
repo_origin_url: run_spec.repo_origin_url.clone(),
|
||||
base_branch: run_spec.base_branch.clone(),
|
||||
workflow_slug: run_spec.workflow_slug.clone(),
|
||||
db_prefix: None,
|
||||
provenance: run_spec.provenance.clone(),
|
||||
manifest_blob: None,
|
||||
pre_run_git: run_spec.pre_run_git.clone(),
|
||||
git: run_spec.git.clone(),
|
||||
fork_source_ref: run_spec.fork_source_ref.clone(),
|
||||
in_place: run_spec.in_place,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use std::sync::Arc;
|
|||
use std::sync::atomic::AtomicBool;
|
||||
|
||||
use fabro_types::settings::run::RunMode;
|
||||
use fabro_types::{ForkSourceRef, PreRunGitContext, RunId, WorkflowSettings};
|
||||
use fabro_types::{ForkSourceRef, GitContext, RunId, WorkflowSettings};
|
||||
|
||||
use crate::git::{GitAuthor, git_author_from_settings};
|
||||
|
||||
|
|
@ -31,7 +31,7 @@ pub struct RunOptions {
|
|||
/// GitHub credentials for pushing metadata branches to origin.
|
||||
pub github_app: Option<fabro_github::GitHubCredentials>,
|
||||
/// Submitter-side git context captured before the run was created.
|
||||
pub pre_run_git: Option<PreRunGitContext>,
|
||||
pub pre_run_git: Option<GitContext>,
|
||||
/// Source checkpoint ref used by fork/rewind-created runs.
|
||||
pub fork_source_ref: Option<ForkSourceRef>,
|
||||
/// Name of the branch the run was started from (for PR base).
|
||||
|
|
|
|||
|
|
@ -135,13 +135,11 @@ mod tests {
|
|||
graph: Graph::new("test"),
|
||||
workflow_slug: Some("test".to_string()),
|
||||
source_directory: Some("/tmp/test".to_string()),
|
||||
repo_origin_url: None,
|
||||
base_branch: None,
|
||||
git: None,
|
||||
labels: HashMap::new(),
|
||||
provenance: None,
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
pre_run_git: None,
|
||||
fork_source_ref: None,
|
||||
in_place: false,
|
||||
}
|
||||
|
|
@ -160,13 +158,11 @@ mod tests {
|
|||
labels: std::collections::BTreeMap::new(),
|
||||
run_dir: "/tmp/test".to_string(),
|
||||
source_directory: Some("/tmp/test".to_string()),
|
||||
repo_origin_url: None,
|
||||
base_branch: None,
|
||||
workflow_slug: Some("test".to_string()),
|
||||
db_prefix: None,
|
||||
provenance: None,
|
||||
manifest_blob: None,
|
||||
pre_run_git: None,
|
||||
git: None,
|
||||
fork_source_ref: None,
|
||||
in_place: false,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -527,11 +527,7 @@ fn classify_entry(
|
|||
})
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct DiffLineStats {
|
||||
pub additions: u64,
|
||||
pub deletions: u64,
|
||||
}
|
||||
pub use fabro_types::DiffStats;
|
||||
|
||||
/// Output of `git diff --numstat`: which paths are binary, plus per-path
|
||||
/// `+/-` line totals for text files in the range. Both pieces come from a
|
||||
|
|
@ -541,7 +537,7 @@ pub struct DiffNumstat {
|
|||
/// Repo-relative paths (post-rename) that git classifies as binary.
|
||||
pub binary_paths: HashSet<String>,
|
||||
/// Repo-relative paths (post-rename) to line stats for text files.
|
||||
pub line_stats_by_path: HashMap<String, DiffLineStats>,
|
||||
pub line_stats_by_path: HashMap<String, DiffStats>,
|
||||
}
|
||||
|
||||
/// Run `git diff --numstat` once and return both the set of binary paths and
|
||||
|
|
@ -593,14 +589,14 @@ pub async fn list_diff_numstat(
|
|||
let Some(path_s) = parts.next() else {
|
||||
continue;
|
||||
};
|
||||
let Ok(adds) = adds_s.parse::<u64>() else {
|
||||
let Ok(adds) = adds_s.parse::<i64>() else {
|
||||
continue;
|
||||
};
|
||||
let Ok(dels) = dels_s.parse::<u64>() else {
|
||||
let Ok(dels) = dels_s.parse::<i64>() else {
|
||||
continue;
|
||||
};
|
||||
let path = extract_new_path_from_numstat(path_s);
|
||||
out.line_stats_by_path.insert(path, DiffLineStats {
|
||||
out.line_stats_by_path.insert(path, DiffStats {
|
||||
additions: adds,
|
||||
deletions: dels,
|
||||
});
|
||||
|
|
@ -1186,13 +1182,17 @@ mod tests {
|
|||
graph: fabro_types::Graph::new("metadata"),
|
||||
workflow_slug: Some("metadata".to_string()),
|
||||
source_directory: Some("/Users/client/project".to_string()),
|
||||
repo_origin_url: Some("https://github.com/fabro-sh/fabro.git".to_string()),
|
||||
base_branch: Some("main".to_string()),
|
||||
git: Some(fabro_types::GitContext {
|
||||
origin_url: "https://github.com/fabro-sh/fabro.git".to_string(),
|
||||
branch: "main".to_string(),
|
||||
sha: None,
|
||||
dirty: fabro_types::DirtyStatus::Clean,
|
||||
push_outcome: fabro_types::PreRunPushOutcome::NotAttempted,
|
||||
}),
|
||||
labels: HashMap::new(),
|
||||
provenance: None,
|
||||
manifest_blob: None,
|
||||
definition_blob: None,
|
||||
pre_run_git: None,
|
||||
fork_source_ref: None,
|
||||
in_place: false,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -120,13 +120,11 @@ async fn initialized(
|
|||
.collect::<BTreeMap<_, _>>(),
|
||||
run_dir: run_options.run_dir.display().to_string(),
|
||||
source_directory: Some(sandbox.working_directory().to_string()),
|
||||
repo_origin_url: None,
|
||||
base_branch: run_options.base_branch.clone(),
|
||||
workflow_slug: run_options.workflow_slug.clone(),
|
||||
db_prefix: None,
|
||||
provenance: None,
|
||||
manifest_blob: None,
|
||||
pre_run_git: run_options.pre_run_git.clone(),
|
||||
git: run_options.pre_run_git.clone(),
|
||||
fork_source_ref: run_options.fork_source_ref.clone(),
|
||||
in_place: false,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ models/file-diff.ts
|
|||
models/fork-request.ts
|
||||
models/fork-response.ts
|
||||
models/fork-source-ref.ts
|
||||
models/git-context.ts
|
||||
models/git-hub-meta-hooks-entry.ts
|
||||
models/github-integration-settings.ts
|
||||
models/github-integration-strategy.ts
|
||||
|
|
@ -113,9 +114,7 @@ models/manifest-args.ts
|
|||
models/manifest-config.ts
|
||||
models/manifest-file-entry.ts
|
||||
models/manifest-file-ref.ts
|
||||
models/manifest-git.ts
|
||||
models/manifest-goal.ts
|
||||
models/manifest-pre-run-push-outcome.ts
|
||||
models/manifest-target.ts
|
||||
models/manifest-workflow-config.ts
|
||||
models/manifest-workflow.ts
|
||||
|
|
@ -146,7 +145,11 @@ models/paginated-saved-query-list.ts
|
|||
models/paginated-stage-turn-list.ts
|
||||
models/pagination-meta.ts
|
||||
models/pending-interview-record.ts
|
||||
models/pre-run-git-context.ts
|
||||
models/pre-run-push-outcome-failed.ts
|
||||
models/pre-run-push-outcome-not-attempted.ts
|
||||
models/pre-run-push-outcome-skipped-no-remote.ts
|
||||
models/pre-run-push-outcome-skipped-remote-mismatch.ts
|
||||
models/pre-run-push-outcome-succeeded.ts
|
||||
models/pre-run-push-outcome.ts
|
||||
models/preflight-check-detail.ts
|
||||
models/preflight-check-report.ts
|
||||
|
|
|
|||
44
lib/packages/fabro-api-client/src/models/git-context.ts
Normal file
44
lib/packages/fabro-api-client/src/models/git-context.ts
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* Fabro Run API
|
||||
* HTTP API for managing Fabro workflow run executions.
|
||||
*
|
||||
* The version of the OpenAPI document: 0.1.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
|
||||
// May contain unused imports in some cases
|
||||
// @ts-ignore
|
||||
import type { DirtyStatus } from './dirty-status';
|
||||
// May contain unused imports in some cases
|
||||
// @ts-ignore
|
||||
import type { PreRunPushOutcome } from './pre-run-push-outcome';
|
||||
|
||||
/**
|
||||
* Observable git state captured before the run starts.
|
||||
*/
|
||||
export interface GitContext {
|
||||
/**
|
||||
* Remote origin URL with any embedded credentials removed.
|
||||
*/
|
||||
'origin_url': string;
|
||||
/**
|
||||
* Current branch name.
|
||||
*/
|
||||
'branch': string;
|
||||
/**
|
||||
* Current commit SHA, when known.
|
||||
*/
|
||||
'sha'?: string | null;
|
||||
'dirty': DirtyStatus;
|
||||
'push_outcome': PreRunPushOutcome;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -55,6 +55,7 @@ export * from './file-diff';
|
|||
export * from './fork-request';
|
||||
export * from './fork-response';
|
||||
export * from './fork-source-ref';
|
||||
export * from './git-context';
|
||||
export * from './git-hub-meta-hooks-entry';
|
||||
export * from './github-integration-settings';
|
||||
export * from './github-integration-strategy';
|
||||
|
|
@ -92,9 +93,7 @@ export * from './manifest-args';
|
|||
export * from './manifest-config';
|
||||
export * from './manifest-file-entry';
|
||||
export * from './manifest-file-ref';
|
||||
export * from './manifest-git';
|
||||
export * from './manifest-goal';
|
||||
export * from './manifest-pre-run-push-outcome';
|
||||
export * from './manifest-target';
|
||||
export * from './manifest-workflow';
|
||||
export * from './manifest-workflow-config';
|
||||
|
|
@ -125,8 +124,12 @@ export * from './paginated-saved-query-list';
|
|||
export * from './paginated-stage-turn-list';
|
||||
export * from './pagination-meta';
|
||||
export * from './pending-interview-record';
|
||||
export * from './pre-run-git-context';
|
||||
export * from './pre-run-push-outcome';
|
||||
export * from './pre-run-push-outcome-failed';
|
||||
export * from './pre-run-push-outcome-not-attempted';
|
||||
export * from './pre-run-push-outcome-skipped-no-remote';
|
||||
export * from './pre-run-push-outcome-skipped-remote-mismatch';
|
||||
export * from './pre-run-push-outcome-succeeded';
|
||||
export * from './preflight-check-detail';
|
||||
export * from './preflight-check-report';
|
||||
export * from './preflight-check-result';
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* Fabro Run API
|
||||
* HTTP API for managing Fabro workflow run executions.
|
||||
*
|
||||
* The version of the OpenAPI document: 0.1.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
export interface PreRunPushOutcomeFailed {
|
||||
'type': PreRunPushOutcomeFailedTypeEnum;
|
||||
'remote': string;
|
||||
'branch': string;
|
||||
'message': string;
|
||||
}
|
||||
|
||||
export const PreRunPushOutcomeFailedTypeEnum = {
|
||||
FAILED: 'failed'
|
||||
} as const;
|
||||
|
||||
export type PreRunPushOutcomeFailedTypeEnum = typeof PreRunPushOutcomeFailedTypeEnum[keyof typeof PreRunPushOutcomeFailedTypeEnum];
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* Fabro Run API
|
||||
* HTTP API for managing Fabro workflow run executions.
|
||||
*
|
||||
* The version of the OpenAPI document: 0.1.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
export interface PreRunPushOutcomeNotAttempted {
|
||||
'type': PreRunPushOutcomeNotAttemptedTypeEnum;
|
||||
}
|
||||
|
||||
export const PreRunPushOutcomeNotAttemptedTypeEnum = {
|
||||
NOT_ATTEMPTED: 'not_attempted'
|
||||
} as const;
|
||||
|
||||
export type PreRunPushOutcomeNotAttemptedTypeEnum = typeof PreRunPushOutcomeNotAttemptedTypeEnum[keyof typeof PreRunPushOutcomeNotAttemptedTypeEnum];
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* Fabro Run API
|
||||
* HTTP API for managing Fabro workflow run executions.
|
||||
*
|
||||
* The version of the OpenAPI document: 0.1.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
export interface PreRunPushOutcomeSkippedNoRemote {
|
||||
'type': PreRunPushOutcomeSkippedNoRemoteTypeEnum;
|
||||
}
|
||||
|
||||
export const PreRunPushOutcomeSkippedNoRemoteTypeEnum = {
|
||||
SKIPPED_NO_REMOTE: 'skipped_no_remote'
|
||||
} as const;
|
||||
|
||||
export type PreRunPushOutcomeSkippedNoRemoteTypeEnum = typeof PreRunPushOutcomeSkippedNoRemoteTypeEnum[keyof typeof PreRunPushOutcomeSkippedNoRemoteTypeEnum];
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* Fabro Run API
|
||||
* HTTP API for managing Fabro workflow run executions.
|
||||
*
|
||||
* The version of the OpenAPI document: 0.1.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
export interface PreRunPushOutcomeSkippedRemoteMismatch {
|
||||
'type': PreRunPushOutcomeSkippedRemoteMismatchTypeEnum;
|
||||
'remote': string;
|
||||
'repo_origin_url': string;
|
||||
}
|
||||
|
||||
export const PreRunPushOutcomeSkippedRemoteMismatchTypeEnum = {
|
||||
SKIPPED_REMOTE_MISMATCH: 'skipped_remote_mismatch'
|
||||
} as const;
|
||||
|
||||
export type PreRunPushOutcomeSkippedRemoteMismatchTypeEnum = typeof PreRunPushOutcomeSkippedRemoteMismatchTypeEnum[keyof typeof PreRunPushOutcomeSkippedRemoteMismatchTypeEnum];
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* Fabro Run API
|
||||
* HTTP API for managing Fabro workflow run executions.
|
||||
*
|
||||
* The version of the OpenAPI document: 0.1.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
export interface PreRunPushOutcomeSucceeded {
|
||||
'type': PreRunPushOutcomeSucceededTypeEnum;
|
||||
'remote': string;
|
||||
'branch': string;
|
||||
}
|
||||
|
||||
export const PreRunPushOutcomeSucceededTypeEnum = {
|
||||
SUCCEEDED: 'succeeded'
|
||||
} as const;
|
||||
|
||||
export type PreRunPushOutcomeSucceededTypeEnum = typeof PreRunPushOutcomeSucceededTypeEnum[keyof typeof PreRunPushOutcomeSucceededTypeEnum];
|
||||
|
||||
|
||||
|
|
@ -13,26 +13,26 @@
|
|||
*/
|
||||
|
||||
|
||||
// May contain unused imports in some cases
|
||||
// @ts-ignore
|
||||
import type { PreRunPushOutcomeFailed } from './pre-run-push-outcome-failed';
|
||||
// May contain unused imports in some cases
|
||||
// @ts-ignore
|
||||
import type { PreRunPushOutcomeNotAttempted } from './pre-run-push-outcome-not-attempted';
|
||||
// May contain unused imports in some cases
|
||||
// @ts-ignore
|
||||
import type { PreRunPushOutcomeSkippedNoRemote } from './pre-run-push-outcome-skipped-no-remote';
|
||||
// May contain unused imports in some cases
|
||||
// @ts-ignore
|
||||
import type { PreRunPushOutcomeSkippedRemoteMismatch } from './pre-run-push-outcome-skipped-remote-mismatch';
|
||||
// May contain unused imports in some cases
|
||||
// @ts-ignore
|
||||
import type { PreRunPushOutcomeSucceeded } from './pre-run-push-outcome-succeeded';
|
||||
|
||||
/**
|
||||
* Outcome of the CLI submitter\'s best-effort pre-run push.
|
||||
* @type PreRunPushOutcome
|
||||
* Outcome of the CLI\'s best-effort pre-run push.
|
||||
*/
|
||||
export interface PreRunPushOutcome {
|
||||
'type': PreRunPushOutcomeTypeEnum;
|
||||
'remote'?: string | null;
|
||||
'branch'?: string | null;
|
||||
'message'?: string | null;
|
||||
'repo_origin_url'?: string | null;
|
||||
}
|
||||
|
||||
export const PreRunPushOutcomeTypeEnum = {
|
||||
NOT_ATTEMPTED: 'not_attempted',
|
||||
SUCCEEDED: 'succeeded',
|
||||
FAILED: 'failed',
|
||||
SKIPPED_NO_REMOTE: 'skipped_no_remote',
|
||||
SKIPPED_REMOTE_MISMATCH: 'skipped_remote_mismatch'
|
||||
} as const;
|
||||
|
||||
export type PreRunPushOutcomeTypeEnum = typeof PreRunPushOutcomeTypeEnum[keyof typeof PreRunPushOutcomeTypeEnum];
|
||||
export type PreRunPushOutcome = { type: 'failed' } & PreRunPushOutcomeFailed | { type: 'not_attempted' } & PreRunPushOutcomeNotAttempted | { type: 'skipped_no_remote' } & PreRunPushOutcomeSkippedNoRemote | { type: 'skipped_remote_mismatch' } & PreRunPushOutcomeSkippedRemoteMismatch | { type: 'succeeded' } & PreRunPushOutcomeSucceeded;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,9 @@
|
|||
*/
|
||||
|
||||
|
||||
// May contain unused imports in some cases
|
||||
// @ts-ignore
|
||||
import type { GitContext } from './git-context';
|
||||
// May contain unused imports in some cases
|
||||
// @ts-ignore
|
||||
import type { ManifestArgs } from './manifest-args';
|
||||
|
|
@ -21,9 +24,6 @@ import type { ManifestArgs } from './manifest-args';
|
|||
import type { ManifestConfig } from './manifest-config';
|
||||
// May contain unused imports in some cases
|
||||
// @ts-ignore
|
||||
import type { ManifestGit } from './manifest-git';
|
||||
// May contain unused imports in some cases
|
||||
// @ts-ignore
|
||||
import type { ManifestGoal } from './manifest-goal';
|
||||
// May contain unused imports in some cases
|
||||
// @ts-ignore
|
||||
|
|
@ -48,7 +48,7 @@ export interface RunManifest {
|
|||
* CLI working directory at invocation time.
|
||||
*/
|
||||
'cwd': string;
|
||||
'git'?: ManifestGit;
|
||||
'git'?: GitContext;
|
||||
'goal'?: ManifestGoal;
|
||||
'args'?: ManifestArgs;
|
||||
'target': ManifestTarget;
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
import type { ForkSourceRef } from './fork-source-ref';
|
||||
// May contain unused imports in some cases
|
||||
// @ts-ignore
|
||||
import type { PreRunGitContext } from './pre-run-git-context';
|
||||
import type { GitContext } from './git-context';
|
||||
|
||||
/**
|
||||
* Durable workflow run specification reconstructed from run.created events.
|
||||
|
|
@ -32,13 +32,11 @@ export interface RunSpec {
|
|||
'graph': { [key: string]: any; };
|
||||
'workflow_slug'?: string | null;
|
||||
'source_directory'?: string | null;
|
||||
'repo_origin_url'?: string | null;
|
||||
'base_branch'?: string | null;
|
||||
'labels'?: { [key: string]: string; };
|
||||
'provenance'?: { [key: string]: any; } | null;
|
||||
'manifest_blob'?: string | null;
|
||||
'definition_blob'?: string | null;
|
||||
'pre_run_git'?: PreRunGitContext | null;
|
||||
'git'?: GitContext | null;
|
||||
'fork_source_ref'?: ForkSourceRef | null;
|
||||
'in_place': boolean;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue