fix(run-files): align diff stats with visible files

Track numstat by path so sensitive, binary, symlink, and submodule entries do not inflate aggregate line counts, and clean generated client whitespace churn from the API update.
This commit is contained in:
Bryan Helmkamp 2026-04-25 07:36:33 -04:00
parent a4e63ec897
commit ffbffa96aa
No known key found for this signature in database
17 changed files with 268 additions and 132 deletions

View file

@ -521,9 +521,11 @@ export default function RunFiles({ loaderData }: any) {
const toolbar = (
<Toolbar
totalChanged={meta.total_changed}
additions={meta.stats.additions}
deletions={meta.stats.deletions}
changeSummary={{
totalChanged: meta.total_changed,
additions: meta.stats.additions,
deletions: meta.stats.deletions,
}}
onRefresh={() => revalidator.revalidate()}
refreshing={isRevalidating}
refreshDisabled={refreshDisabled}

View file

@ -8,10 +8,14 @@ import { ArrowPathIcon } from "@heroicons/react/20/solid";
*/
export type DiffStyle = "split" | "unified";
type ChangeSummary = {
totalChanged: number;
additions: number;
deletions: number;
};
export function Toolbar({
totalChanged,
additions,
deletions,
changeSummary,
onRefresh,
refreshing,
refreshDisabled,
@ -21,12 +25,7 @@ export function Toolbar({
onDiffStyleChange,
diffStyleForced,
}: {
/** From `meta.total_changed`. May exceed the rendered file list when truncated. */
totalChanged: number;
/** From `meta.stats.additions`. Aggregate `+` line count across the diff. */
additions: number;
/** From `meta.stats.deletions`. Aggregate `-` line count across the diff. */
deletions: number;
changeSummary: ChangeSummary;
onRefresh: () => void;
refreshing: boolean;
/** True when the server has nothing new to show (to_sha unchanged). */
@ -43,6 +42,7 @@ export function Toolbar({
*/
diffStyleForced: boolean;
}) {
const { totalChanged, additions, deletions } = changeSummary;
const refreshTitle = refreshing
? "Refreshing"
: refreshDisabled

View file

@ -34,8 +34,8 @@ use fabro_sandbox::reconnect::reconnect;
use fabro_static::EnvVars;
use fabro_types::RunId;
use fabro_workflow::sandbox_git::{
DiffError, DiffNumstat, RawDiffEntry, SubmoduleChange, SymlinkChange, list_changed_files_raw,
list_diff_numstat, stream_blob_metadata, stream_blobs,
DiffError, DiffLineStats, DiffNumstat, RawDiffEntry, SubmoduleChange, SymlinkChange,
list_changed_files_raw, list_diff_numstat, stream_blob_metadata, stream_blobs,
};
use futures_util::FutureExt;
use serde::Deserialize;
@ -297,18 +297,17 @@ async fn materialize_sandbox_path(state: &Arc<AppState>, run_id: &RunId) -> List
return Err(transient_503("git diff --numstat", &message));
}
};
let binary_paths = numstat.binary_paths.clone();
let total_changed_before_cap = raw_entries.len();
// Classify every entry against the denylist + binary/symlink/submodule
// flags FIRST so no-blob-needed placeholders don't consume cap slots
// that belong to real file changes.
let classified = classify_entries(&raw_entries, &binary_paths, is_sensitive);
let classified = classify_entries(&raw_entries, &numstat, is_sensitive);
let stats = classified.stats;
// Then cap the combined list at 200 entries.
let truncated_by_count = classified.len() > FILE_COUNT_CAP;
let mut classified = classified;
let truncated_by_count = classified.entries.len() > FILE_COUNT_CAP;
let mut classified = classified.entries;
if truncated_by_count {
classified.truncate(FILE_COUNT_CAP);
}
@ -364,7 +363,7 @@ async fn materialize_sandbox_path(state: &Arc<AppState>, run_id: &RunId) -> List
files_omitted_by_budget: (files_omitted_by_budget > 0)
.then(|| i64::try_from(files_omitted_by_budget).unwrap_or(i64::MAX)),
total_changed: i64::try_from(total_changed_before_cap).unwrap_or(i64::MAX),
stats: numstat_to_stats(&numstat),
stats,
to_sha: Some(to_sha_wrapper(&to_sha)),
to_sha_committed_at,
degraded: Some(false),
@ -374,10 +373,10 @@ async fn materialize_sandbox_path(state: &Arc<AppState>, run_id: &RunId) -> List
})
}
fn numstat_to_stats(n: &DiffNumstat) -> DiffStats {
fn line_stats_to_api(stats: DiffLineStats) -> DiffStats {
DiffStats {
additions: i64::try_from(n.additions).unwrap_or(i64::MAX),
deletions: i64::try_from(n.deletions).unwrap_or(i64::MAX),
additions: i64::try_from(stats.additions).unwrap_or(i64::MAX),
deletions: i64::try_from(stats.deletions).unwrap_or(i64::MAX),
}
}
@ -452,22 +451,44 @@ 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 additions: u64 = 0;
let mut deletions: u64 = 0;
for line in patch.lines() {
if line.starts_with("+++") || line.starts_with("---") {
let mut stats = DiffLineStats::default();
for section in patch.split("diff --git ").skip(1) {
if patch_section_omits_line_stats(section) {
continue;
}
match line.as_bytes().first() {
Some(b'+') => additions = additions.saturating_add(1),
Some(b'-') => deletions = deletions.saturating_add(1),
_ => {}
for line in section.lines() {
if line.starts_with("+++") || line.starts_with("---") {
continue;
}
match line.as_bytes().first() {
Some(b'+') => stats.additions = stats.additions.saturating_add(1),
Some(b'-') => stats.deletions = stats.deletions.saturating_add(1),
_ => {}
}
}
}
DiffStats {
additions: i64::try_from(additions).unwrap_or(i64::MAX),
deletions: i64::try_from(deletions).unwrap_or(i64::MAX),
line_stats_to_api(stats)
}
fn patch_section_omits_line_stats(section: &str) -> bool {
section.lines().any(|line| {
patch_mode_line_matches(line, "120000") || patch_mode_line_matches(line, "160000")
})
}
fn patch_mode_line_matches(line: &str, mode: &str) -> bool {
let line = line.trim_end();
if let Some(rest) = line
.strip_prefix("new file mode ")
.or_else(|| line.strip_prefix("deleted file mode "))
.or_else(|| line.strip_prefix("old mode "))
.or_else(|| line.strip_prefix("new mode "))
{
return rest == mode;
}
line.strip_prefix("index ")
.and_then(|rest| rest.split_whitespace().last())
== Some(mode)
}
/// Truncate a patch at `cap_bytes` on a UTF-8 character boundary. Returns
@ -693,14 +714,22 @@ enum ClassifiedEntry {
NeedsFetch(RawDiffEntry),
}
struct ClassifiedEntries {
entries: Vec<ClassifiedEntry>,
stats: DiffStats,
}
/// Classify every raw entry against the denylist + binary flags. Runs before
/// the 200-file cap so sensitive entries don't evict real changes.
/// the 200-file cap so sensitive entries don't evict real changes, and so
/// stats include every eligible text file even when the rendered list is
/// capped.
fn classify_entries(
raw: &[RawDiffEntry],
binary_paths: &HashSet<String>,
numstat: &DiffNumstat,
is_sensitive_fn: fn(&str) -> bool,
) -> Vec<ClassifiedEntry> {
) -> ClassifiedEntries {
let mut out = Vec::with_capacity(raw.len());
let mut stats = DiffLineStats::default();
for entry in raw {
let (new_path, old_path) = match entry {
@ -739,19 +768,26 @@ fn classify_entries(
}
// `git diff --numstat` reports the post-rename path on renames,
// so checking `new_path` covers both non-rename and rename cases.
_ if binary_paths.contains(new_path) => {
_ if numstat.binary_paths.contains(new_path) => {
out.push(ClassifiedEntry::Prebuilt(build_placeholder_file_diff(
entry,
&PlaceholderKind::Binary,
)));
}
_ => {
if let Some(line_stats) = numstat.line_stats_by_path.get(new_path) {
stats.additions = stats.additions.saturating_add(line_stats.additions);
stats.deletions = stats.deletions.saturating_add(line_stats.deletions);
}
out.push(ClassifiedEntry::NeedsFetch(entry.clone()));
}
}
}
out
ClassifiedEntries {
entries: out,
stats: line_stats_to_api(stats),
}
}
enum PlaceholderKind {
@ -1432,6 +1468,105 @@ diff --git a/src/bar.rs b/src/bar.rs
assert_eq!(count_diff_headers(patch), 2);
}
#[test]
fn patch_to_stats_counts_content_lines_only() {
let patch = "\
diff --git a/src/a.rs b/src/a.rs
--- a/src/a.rs
+++ b/src/a.rs
@@ -1 +1,2 @@
-old
+new
+extra
";
let stats = patch_to_stats(patch);
assert_eq!(stats.additions, 2);
assert_eq!(stats.deletions, 1);
}
#[test]
fn patch_to_stats_skips_symlink_and_submodule_sections() {
let patch = "\
diff --git a/link b/link
new file mode 120000
--- /dev/null
+++ b/link
@@ -0,0 +1 @@
+target
diff --git a/vendor/lib b/vendor/lib
index 1111111..2222222 160000
--- a/vendor/lib
+++ b/vendor/lib
@@ -1 +1 @@
-Subproject commit 1111111
+Subproject commit 2222222
diff --git a/src/lib.rs b/src/lib.rs
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1 +1 @@
-old
+new
";
let stats = patch_to_stats(patch);
assert_eq!(stats.additions, 1);
assert_eq!(stats.deletions, 1);
}
#[test]
fn classify_entries_sums_only_displayable_text_stats() {
let raw = vec![
RawDiffEntry::Added {
path: "src/visible.rs".to_string(),
new_blob: "a1".to_string(),
new_mode: "100644".to_string(),
},
RawDiffEntry::Modified {
path: ".env".to_string(),
old_blob: "b1".to_string(),
new_blob: "b2".to_string(),
new_mode: "100644".to_string(),
},
RawDiffEntry::Modified {
path: "image.png".to_string(),
old_blob: "c1".to_string(),
new_blob: "c2".to_string(),
new_mode: "100644".to_string(),
},
RawDiffEntry::Symlink {
path: "link".to_string(),
change_kind: SymlinkChange::Added,
old_blob: None,
new_blob: Some("d1".to_string()),
},
RawDiffEntry::Submodule {
path: "vendor/lib".to_string(),
change_kind: SubmoduleChange::Modified,
},
];
let mut numstat = DiffNumstat::default();
for (path, additions, deletions) in [
("src/visible.rs", 5, 1),
(".env", 100, 100),
("image.png", 200, 200),
("link", 1, 0),
("vendor/lib", 1, 1),
] {
numstat
.line_stats_by_path
.insert(path.to_string(), DiffLineStats {
additions,
deletions,
});
}
numstat.binary_paths.insert("image.png".to_string());
let classified = classify_entries(&raw, &numstat, is_sensitive);
assert_eq!(classified.stats.additions, 5);
assert_eq!(classified.stats.deletions, 1);
assert_eq!(classified.entries.len(), raw.len());
}
#[test]
fn extract_diff_header_paths_pulls_both_sides_from_header() {
assert_eq!(

View file

@ -58,7 +58,7 @@
<script type="module" src="/assets/chunk-sadshphz.js"></script>
<script type="module" src="/assets/chunk-pmthkscp.js"></script>
<script type="module" src="/assets/chunk-v61ks9f7.js"></script>
<script type="module" src="/assets/entry-7q292616.js"></script>
<script type="module" src="/assets/entry-grs8nqaw.js"></script>
<script type="module" src="/assets/chunk-n1k68xa8.js"></script>
<script type="module" src="/assets/chunk-rsph5pvm.js"></script>
<script type="module" src="/assets/chunk-9t57pdty.js"></script>

View file

@ -1,3 +1,4 @@
use std::collections::{HashMap, HashSet};
use std::path::Path;
use fabro_agent::Sandbox;
@ -552,24 +553,26 @@ fn classify_entry(
})
}
/// Output of `git diff --numstat`: which paths are binary, plus aggregate
/// `+/-` line totals across the text files in the range. Both pieces come
/// from a single git invocation so callers don't need to run two diffs.
#[derive(Debug, Default, Clone)]
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub struct DiffLineStats {
pub additions: u64,
pub deletions: u64,
}
/// 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
/// single git invocation so callers don't need to run two diffs.
#[derive(Debug, Default)]
pub struct DiffNumstat {
/// Repo-relative paths (post-rename) that git classifies as binary.
pub binary_paths: std::collections::HashSet<String>,
/// Sum of `+` columns across text files. Binary entries (`-\t-`) do not
/// contribute.
pub additions: u64,
/// Sum of `-` columns across text files. Binary entries (`-\t-`) do not
/// contribute.
pub deletions: u64,
pub binary_paths: HashSet<String>,
/// Repo-relative paths (post-rename) to line stats for text files.
pub line_stats_by_path: HashMap<String, DiffLineStats>,
}
/// Run `git diff --numstat` once and return both the set of binary paths and
/// the aggregate text-file `+/-` totals. The single call replaces the
/// previous binary-only helper.
/// text-file `+/-` totals. The single call replaces the previous binary-only
/// helper.
pub async fn list_diff_numstat(
sandbox: &dyn Sandbox,
base_sha: &str,
@ -611,14 +614,20 @@ pub async fn list_diff_numstat(
let mut parts = line.splitn(3, '\t');
let adds_s = parts.next().unwrap_or("");
let dels_s = parts.next().unwrap_or("");
let Some(path_s) = parts.next() else {
continue;
};
let Ok(adds) = adds_s.parse::<u64>() else {
continue;
};
let Ok(dels) = dels_s.parse::<u64>() else {
continue;
};
out.additions = out.additions.saturating_add(adds);
out.deletions = out.deletions.saturating_add(dels);
let path = extract_new_path_from_numstat(path_s);
out.line_stats_by_path.insert(path, DiffLineStats {
additions: adds,
deletions: dels,
});
}
Ok(out)
}
@ -1264,8 +1273,9 @@ mod tests {
"binary_paths: {:?}",
stats.binary_paths
);
assert_eq!(stats.additions, 3, "additions: {stats:?}");
assert_eq!(stats.deletions, 2, "deletions: {stats:?}");
let doc_stats = stats.line_stats_by_path.get("doc.md").unwrap();
assert_eq!(doc_stats.additions, 3, "additions: {stats:?}");
assert_eq!(doc_stats.deletions, 2, "deletions: {stats:?}");
}
#[tokio::test]

View file

@ -5,7 +5,7 @@
* 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
@ -67,7 +67,7 @@ import type { TimelineEntryResponse } from '../models';
export const RunsApiAxiosParamCreator = function (configuration?: Configuration) {
return {
/**
* Marks a terminal run (`succeeded`, `failed`, or `dead`) as `archived`. Archived runs are hidden from default listings and are read-only until unarchived. Idempotent on already-archived runs. Returns 409 if the run is not terminal.
* Marks a terminal run (`succeeded`, `failed`, or `dead`) as `archived`. Archived runs are hidden from default listings and are read-only until unarchived. Idempotent on already-archived runs. Returns 409 if the run is not terminal.
* @summary Archive Run
* @param {string} id Unique run identifier (ULID).
* @param {*} [options] Override http request option.
@ -189,7 +189,7 @@ export const RunsApiAxiosParamCreator = function (configuration?: Configuration)
/**
* Creates a new workflow run in `submitted` status from a self-contained manifest.
* @summary Create Run
* @param {RunManifest} runManifest
* @param {RunManifest} runManifest
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
@ -231,7 +231,7 @@ export const RunsApiAxiosParamCreator = function (configuration?: Configuration)
* Creates a pull request for a completed run on GitHub and persists the record on the server.
* @summary Create Run Pull Request
* @param {string} id Unique run identifier (ULID).
* @param {CreateRunPullRequestRequest} createRunPullRequestRequest
* @param {CreateRunPullRequestRequest} createRunPullRequestRequest
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
@ -318,10 +318,10 @@ export const RunsApiAxiosParamCreator = function (configuration?: Configuration)
};
},
/**
* Creates a new run from a checkpoint of the source run. The source run is left untouched.
* Creates a new run from a checkpoint of the source run. The source run is left untouched.
* @summary Fork Run
* @param {string} id Unique run identifier (ULID).
* @param {ForkRequest} [forkRequest]
* @param {ForkRequest} [forkRequest]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
@ -401,7 +401,7 @@ export const RunsApiAxiosParamCreator = function (configuration?: Configuration)
};
},
/**
* Returns checkpoint timeline entries read from the run metadata branch. This endpoint does not rebuild missing metadata branches.
* Returns checkpoint timeline entries read from the run metadata branch. This endpoint does not rebuild missing metadata branches.
* @summary Get Run Timeline
* @param {string} id Unique run identifier (ULID).
* @param {*} [options] Override http request option.
@ -541,7 +541,7 @@ export const RunsApiAxiosParamCreator = function (configuration?: Configuration)
* Merges the stored pull request for a run on GitHub.
* @summary Merge Run Pull Request
* @param {string} id Unique run identifier (ULID).
* @param {MergeRunPullRequestRequest} mergeRunPullRequestRequest
* @param {MergeRunPullRequestRequest} mergeRunPullRequestRequest
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
@ -625,7 +625,7 @@ export const RunsApiAxiosParamCreator = function (configuration?: Configuration)
/**
* Validates and renders a workflow manifest as SVG without creating a run.
* @summary Render Workflow Graph
* @param {RenderWorkflowGraphRequest} renderWorkflowGraphRequest
* @param {RenderWorkflowGraphRequest} renderWorkflowGraphRequest
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
@ -787,10 +787,10 @@ export const RunsApiAxiosParamCreator = function (configuration?: Configuration)
};
},
/**
* Creates a new run from an earlier checkpoint of a terminal source run, archives the source run, and records `run.superseded_by` on the source after archive succeeds. Returns 207 when the new run was created but the source archive step failed.
* Creates a new run from an earlier checkpoint of a terminal source run, archives the source run, and records `run.superseded_by` on the source after archive succeeds. Returns 207 when the new run was created but the source archive step failed.
* @summary Rewind Run
* @param {string} id Unique run identifier (ULID).
* @param {RewindRequest} [rewindRequest]
* @param {RewindRequest} [rewindRequest]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
@ -832,7 +832,7 @@ export const RunsApiAxiosParamCreator = function (configuration?: Configuration)
/**
* Validates a workflow manifest without creating a run.
* @summary Validate Workflow Manifest
* @param {RunManifest} runManifest
* @param {RunManifest} runManifest
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
@ -874,7 +874,7 @@ export const RunsApiAxiosParamCreator = function (configuration?: Configuration)
* Starts a submitted run, queuing it for execution. Provide `resume=true` to resume an interrupted run from checkpoint. Returns 409 if the run is not startable.
* @summary Start Run
* @param {string} id Unique run identifier (ULID).
* @param {StartRunRequest} [startRunRequest]
* @param {StartRunRequest} [startRunRequest]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
@ -914,7 +914,7 @@ export const RunsApiAxiosParamCreator = function (configuration?: Configuration)
};
},
/**
* Restores an archived run to its prior terminal status. Idempotent on runs that are terminal but not archived (returns the current status without emitting an event). Returns 409 if the run is active.
* Restores an archived run to its prior terminal status. Idempotent on runs that are terminal but not archived (returns the current status without emitting an event). Returns 409 if the run is active.
* @summary Unarchive Run
* @param {string} id Unique run identifier (ULID).
* @param {*} [options] Override http request option.
@ -1003,7 +1003,7 @@ export const RunsApiFp = function(configuration?: Configuration) {
const localVarAxiosParamCreator = RunsApiAxiosParamCreator(configuration)
return {
/**
* Marks a terminal run (`succeeded`, `failed`, or `dead`) as `archived`. Archived runs are hidden from default listings and are read-only until unarchived. Idempotent on already-archived runs. Returns 409 if the run is not terminal.
* Marks a terminal run (`succeeded`, `failed`, or `dead`) as `archived`. Archived runs are hidden from default listings and are read-only until unarchived. Idempotent on already-archived runs. Returns 409 if the run is not terminal.
* @summary Archive Run
* @param {string} id Unique run identifier (ULID).
* @param {*} [options] Override http request option.
@ -1044,7 +1044,7 @@ export const RunsApiFp = function(configuration?: Configuration) {
/**
* Creates a new workflow run in `submitted` status from a self-contained manifest.
* @summary Create Run
* @param {RunManifest} runManifest
* @param {RunManifest} runManifest
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
@ -1058,7 +1058,7 @@ export const RunsApiFp = function(configuration?: Configuration) {
* Creates a pull request for a completed run on GitHub and persists the record on the server.
* @summary Create Run Pull Request
* @param {string} id Unique run identifier (ULID).
* @param {CreateRunPullRequestRequest} createRunPullRequestRequest
* @param {CreateRunPullRequestRequest} createRunPullRequestRequest
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
@ -1083,10 +1083,10 @@ export const RunsApiFp = function(configuration?: Configuration) {
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
* Creates a new run from a checkpoint of the source run. The source run is left untouched.
* Creates a new run from a checkpoint of the source run. The source run is left untouched.
* @summary Fork Run
* @param {string} id Unique run identifier (ULID).
* @param {ForkRequest} [forkRequest]
* @param {ForkRequest} [forkRequest]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
@ -1110,7 +1110,7 @@ export const RunsApiFp = function(configuration?: Configuration) {
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
* Returns checkpoint timeline entries read from the run metadata branch. This endpoint does not rebuild missing metadata branches.
* Returns checkpoint timeline entries read from the run metadata branch. This endpoint does not rebuild missing metadata branches.
* @summary Get Run Timeline
* @param {string} id Unique run identifier (ULID).
* @param {*} [options] Override http request option.
@ -1155,7 +1155,7 @@ export const RunsApiFp = function(configuration?: Configuration) {
* Merges the stored pull request for a run on GitHub.
* @summary Merge Run Pull Request
* @param {string} id Unique run identifier (ULID).
* @param {MergeRunPullRequestRequest} mergeRunPullRequestRequest
* @param {MergeRunPullRequestRequest} mergeRunPullRequestRequest
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
@ -1181,7 +1181,7 @@ export const RunsApiFp = function(configuration?: Configuration) {
/**
* Validates and renders a workflow manifest as SVG without creating a run.
* @summary Render Workflow Graph
* @param {RenderWorkflowGraphRequest} renderWorkflowGraphRequest
* @param {RenderWorkflowGraphRequest} renderWorkflowGraphRequest
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
@ -1231,10 +1231,10 @@ export const RunsApiFp = function(configuration?: Configuration) {
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
* Creates a new run from an earlier checkpoint of a terminal source run, archives the source run, and records `run.superseded_by` on the source after archive succeeds. Returns 207 when the new run was created but the source archive step failed.
* Creates a new run from an earlier checkpoint of a terminal source run, archives the source run, and records `run.superseded_by` on the source after archive succeeds. Returns 207 when the new run was created but the source archive step failed.
* @summary Rewind Run
* @param {string} id Unique run identifier (ULID).
* @param {RewindRequest} [rewindRequest]
* @param {RewindRequest} [rewindRequest]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
@ -1247,7 +1247,7 @@ export const RunsApiFp = function(configuration?: Configuration) {
/**
* Validates a workflow manifest without creating a run.
* @summary Validate Workflow Manifest
* @param {RunManifest} runManifest
* @param {RunManifest} runManifest
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
@ -1261,7 +1261,7 @@ export const RunsApiFp = function(configuration?: Configuration) {
* Starts a submitted run, queuing it for execution. Provide `resume=true` to resume an interrupted run from checkpoint. Returns 409 if the run is not startable.
* @summary Start Run
* @param {string} id Unique run identifier (ULID).
* @param {StartRunRequest} [startRunRequest]
* @param {StartRunRequest} [startRunRequest]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
@ -1272,7 +1272,7 @@ export const RunsApiFp = function(configuration?: Configuration) {
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
* Restores an archived run to its prior terminal status. Idempotent on runs that are terminal but not archived (returns the current status without emitting an event). Returns 409 if the run is active.
* Restores an archived run to its prior terminal status. Idempotent on runs that are terminal but not archived (returns the current status without emitting an event). Returns 409 if the run is active.
* @summary Unarchive Run
* @param {string} id Unique run identifier (ULID).
* @param {*} [options] Override http request option.
@ -1307,7 +1307,7 @@ export const RunsApiFactory = function (configuration?: Configuration, basePath?
const localVarFp = RunsApiFp(configuration)
return {
/**
* Marks a terminal run (`succeeded`, `failed`, or `dead`) as `archived`. Archived runs are hidden from default listings and are read-only until unarchived. Idempotent on already-archived runs. Returns 409 if the run is not terminal.
* Marks a terminal run (`succeeded`, `failed`, or `dead`) as `archived`. Archived runs are hidden from default listings and are read-only until unarchived. Idempotent on already-archived runs. Returns 409 if the run is not terminal.
* @summary Archive Run
* @param {string} id Unique run identifier (ULID).
* @param {*} [options] Override http request option.
@ -1339,7 +1339,7 @@ export const RunsApiFactory = function (configuration?: Configuration, basePath?
/**
* Creates a new workflow run in `submitted` status from a self-contained manifest.
* @summary Create Run
* @param {RunManifest} runManifest
* @param {RunManifest} runManifest
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
@ -1350,7 +1350,7 @@ export const RunsApiFactory = function (configuration?: Configuration, basePath?
* Creates a pull request for a completed run on GitHub and persists the record on the server.
* @summary Create Run Pull Request
* @param {string} id Unique run identifier (ULID).
* @param {CreateRunPullRequestRequest} createRunPullRequestRequest
* @param {CreateRunPullRequestRequest} createRunPullRequestRequest
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
@ -1369,10 +1369,10 @@ export const RunsApiFactory = function (configuration?: Configuration, basePath?
return localVarFp.deleteRun(id, force, options).then((request) => request(axios, basePath));
},
/**
* Creates a new run from a checkpoint of the source run. The source run is left untouched.
* Creates a new run from a checkpoint of the source run. The source run is left untouched.
* @summary Fork Run
* @param {string} id Unique run identifier (ULID).
* @param {ForkRequest} [forkRequest]
* @param {ForkRequest} [forkRequest]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
@ -1390,7 +1390,7 @@ export const RunsApiFactory = function (configuration?: Configuration, basePath?
return localVarFp.getRunPullRequest(id, options).then((request) => request(axios, basePath));
},
/**
* Returns checkpoint timeline entries read from the run metadata branch. This endpoint does not rebuild missing metadata branches.
* Returns checkpoint timeline entries read from the run metadata branch. This endpoint does not rebuild missing metadata branches.
* @summary Get Run Timeline
* @param {string} id Unique run identifier (ULID).
* @param {*} [options] Override http request option.
@ -1426,7 +1426,7 @@ export const RunsApiFactory = function (configuration?: Configuration, basePath?
* Merges the stored pull request for a run on GitHub.
* @summary Merge Run Pull Request
* @param {string} id Unique run identifier (ULID).
* @param {MergeRunPullRequestRequest} mergeRunPullRequestRequest
* @param {MergeRunPullRequestRequest} mergeRunPullRequestRequest
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
@ -1446,7 +1446,7 @@ export const RunsApiFactory = function (configuration?: Configuration, basePath?
/**
* Validates and renders a workflow manifest as SVG without creating a run.
* @summary Render Workflow Graph
* @param {RenderWorkflowGraphRequest} renderWorkflowGraphRequest
* @param {RenderWorkflowGraphRequest} renderWorkflowGraphRequest
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
@ -1484,10 +1484,10 @@ export const RunsApiFactory = function (configuration?: Configuration, basePath?
return localVarFp.retrieveRunGraph(id, options).then((request) => request(axios, basePath));
},
/**
* Creates a new run from an earlier checkpoint of a terminal source run, archives the source run, and records `run.superseded_by` on the source after archive succeeds. Returns 207 when the new run was created but the source archive step failed.
* Creates a new run from an earlier checkpoint of a terminal source run, archives the source run, and records `run.superseded_by` on the source after archive succeeds. Returns 207 when the new run was created but the source archive step failed.
* @summary Rewind Run
* @param {string} id Unique run identifier (ULID).
* @param {RewindRequest} [rewindRequest]
* @param {RewindRequest} [rewindRequest]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
@ -1497,7 +1497,7 @@ export const RunsApiFactory = function (configuration?: Configuration, basePath?
/**
* Validates a workflow manifest without creating a run.
* @summary Validate Workflow Manifest
* @param {RunManifest} runManifest
* @param {RunManifest} runManifest
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
@ -1508,7 +1508,7 @@ export const RunsApiFactory = function (configuration?: Configuration, basePath?
* Starts a submitted run, queuing it for execution. Provide `resume=true` to resume an interrupted run from checkpoint. Returns 409 if the run is not startable.
* @summary Start Run
* @param {string} id Unique run identifier (ULID).
* @param {StartRunRequest} [startRunRequest]
* @param {StartRunRequest} [startRunRequest]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
@ -1516,7 +1516,7 @@ export const RunsApiFactory = function (configuration?: Configuration, basePath?
return localVarFp.startRun(id, startRunRequest, options).then((request) => request(axios, basePath));
},
/**
* Restores an archived run to its prior terminal status. Idempotent on runs that are terminal but not archived (returns the current status without emitting an event). Returns 409 if the run is active.
* Restores an archived run to its prior terminal status. Idempotent on runs that are terminal but not archived (returns the current status without emitting an event). Returns 409 if the run is active.
* @summary Unarchive Run
* @param {string} id Unique run identifier (ULID).
* @param {*} [options] Override http request option.
@ -1543,7 +1543,7 @@ export const RunsApiFactory = function (configuration?: Configuration, basePath?
*/
export class RunsApi extends BaseAPI {
/**
* Marks a terminal run (`succeeded`, `failed`, or `dead`) as `archived`. Archived runs are hidden from default listings and are read-only until unarchived. Idempotent on already-archived runs. Returns 409 if the run is not terminal.
* Marks a terminal run (`succeeded`, `failed`, or `dead`) as `archived`. Archived runs are hidden from default listings and are read-only until unarchived. Idempotent on already-archived runs. Returns 409 if the run is not terminal.
* @summary Archive Run
* @param {string} id Unique run identifier (ULID).
* @param {*} [options] Override http request option.
@ -1578,7 +1578,7 @@ export class RunsApi extends BaseAPI {
/**
* Creates a new workflow run in `submitted` status from a self-contained manifest.
* @summary Create Run
* @param {RunManifest} runManifest
* @param {RunManifest} runManifest
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
@ -1590,7 +1590,7 @@ export class RunsApi extends BaseAPI {
* Creates a pull request for a completed run on GitHub and persists the record on the server.
* @summary Create Run Pull Request
* @param {string} id Unique run identifier (ULID).
* @param {CreateRunPullRequestRequest} createRunPullRequestRequest
* @param {CreateRunPullRequestRequest} createRunPullRequestRequest
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
@ -1611,10 +1611,10 @@ export class RunsApi extends BaseAPI {
}
/**
* Creates a new run from a checkpoint of the source run. The source run is left untouched.
* Creates a new run from a checkpoint of the source run. The source run is left untouched.
* @summary Fork Run
* @param {string} id Unique run identifier (ULID).
* @param {ForkRequest} [forkRequest]
* @param {ForkRequest} [forkRequest]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
@ -1634,7 +1634,7 @@ export class RunsApi extends BaseAPI {
}
/**
* Returns checkpoint timeline entries read from the run metadata branch. This endpoint does not rebuild missing metadata branches.
* Returns checkpoint timeline entries read from the run metadata branch. This endpoint does not rebuild missing metadata branches.
* @summary Get Run Timeline
* @param {string} id Unique run identifier (ULID).
* @param {*} [options] Override http request option.
@ -1673,7 +1673,7 @@ export class RunsApi extends BaseAPI {
* Merges the stored pull request for a run on GitHub.
* @summary Merge Run Pull Request
* @param {string} id Unique run identifier (ULID).
* @param {MergeRunPullRequestRequest} mergeRunPullRequestRequest
* @param {MergeRunPullRequestRequest} mergeRunPullRequestRequest
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
@ -1695,7 +1695,7 @@ export class RunsApi extends BaseAPI {
/**
* Validates and renders a workflow manifest as SVG without creating a run.
* @summary Render Workflow Graph
* @param {RenderWorkflowGraphRequest} renderWorkflowGraphRequest
* @param {RenderWorkflowGraphRequest} renderWorkflowGraphRequest
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
@ -1737,10 +1737,10 @@ export class RunsApi extends BaseAPI {
}
/**
* Creates a new run from an earlier checkpoint of a terminal source run, archives the source run, and records `run.superseded_by` on the source after archive succeeds. Returns 207 when the new run was created but the source archive step failed.
* Creates a new run from an earlier checkpoint of a terminal source run, archives the source run, and records `run.superseded_by` on the source after archive succeeds. Returns 207 when the new run was created but the source archive step failed.
* @summary Rewind Run
* @param {string} id Unique run identifier (ULID).
* @param {RewindRequest} [rewindRequest]
* @param {RewindRequest} [rewindRequest]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
@ -1751,7 +1751,7 @@ export class RunsApi extends BaseAPI {
/**
* Validates a workflow manifest without creating a run.
* @summary Validate Workflow Manifest
* @param {RunManifest} runManifest
* @param {RunManifest} runManifest
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
@ -1763,7 +1763,7 @@ export class RunsApi extends BaseAPI {
* Starts a submitted run, queuing it for execution. Provide `resume=true` to resume an interrupted run from checkpoint. Returns 409 if the run is not startable.
* @summary Start Run
* @param {string} id Unique run identifier (ULID).
* @param {StartRunRequest} [startRunRequest]
* @param {StartRunRequest} [startRunRequest]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
@ -1772,7 +1772,7 @@ export class RunsApi extends BaseAPI {
}
/**
* Restores an archived run to its prior terminal status. Idempotent on runs that are terminal but not archived (returns the current status without emitting an event). Returns 409 if the run is active.
* Restores an archived run to its prior terminal status. Idempotent on runs that are terminal but not archived (returns the current status without emitting an event). Returns 409 if the run is active.
* @summary Unarchive Run
* @param {string} id Unique run identifier (ULID).
* @param {*} [options] Override http request option.

View file

@ -15,7 +15,7 @@
/**
* Aggregate `+/-` line counts across all files in a diff (or the unified patch in degraded mode). Binary, sensitive, symlink, and submodule files contribute 0/0 since they have no line-level diff. Both fields are 0 for empty / pre-start envelopes.
* Aggregate `+/-` line counts across all files in a diff (or the unified patch in degraded mode). Binary, sensitive, symlink, and submodule files contribute 0/0 since they have no line-level diff. Both fields are 0 for empty / pre-start envelopes.
*/
export interface DiffStats {
/**

View file

@ -5,7 +5,7 @@
* 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
@ -27,4 +27,3 @@ export interface ForkRequest {
*/
'push'?: boolean | null;
}

View file

@ -5,7 +5,7 @@
* 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
@ -22,4 +22,3 @@ export interface ForkResponse {
'new_run_id': string;
'target': string;
}

View file

@ -5,7 +5,7 @@
* 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
@ -39,5 +39,3 @@ export const InstallObjectStoreInputCredentialModeEnum = {
} as const;
export type InstallObjectStoreInputCredentialModeEnum = typeof InstallObjectStoreInputCredentialModeEnum[keyof typeof InstallObjectStoreInputCredentialModeEnum];

View file

@ -5,7 +5,7 @@
* 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
@ -38,5 +38,3 @@ export const InstallObjectStoreSummaryCredentialModeEnum = {
} as const;
export type InstallObjectStoreSummaryCredentialModeEnum = typeof InstallObjectStoreSummaryCredentialModeEnum[keyof typeof InstallObjectStoreSummaryCredentialModeEnum];

View file

@ -5,7 +5,7 @@
* 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
@ -21,4 +21,3 @@ export interface InstallPrefill {
'canonical_url': string;
'object_store_local_root': string;
}

View file

@ -5,7 +5,7 @@
* 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
@ -27,4 +27,3 @@ export interface RewindRequest {
*/
'push'?: boolean | null;
}

View file

@ -5,7 +5,7 @@
* 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
@ -24,4 +24,3 @@ export interface RewindResponse {
'archived': boolean;
'archive_error'?: string | null;
}

View file

@ -5,7 +5,7 @@
* 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
@ -23,4 +23,3 @@ export interface RunSupersededByProps {
'target_node_id': string;
'target_visit': number;
}

View file

@ -5,7 +5,7 @@
* 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
@ -23,4 +23,3 @@ export interface TimelineEntryResponse {
'visit': number;
'run_commit_sha'?: string | null;
}