mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-10-08 03:10:26 +00:00
Keep local artifacts under the storage directory
Servers have always moved a local artifact store under the storage directory at startup, whatever `local.root` said. Browser-wizard installs write `local.root = "<storage>/objects"`, so honoring that root would move their store and hide every artifact already written, with nothing to migrate it. Restore the storage-directory override for local roots and leave honoring custom roots to a change that migrates existing objects. Installer metadata still goes through the override, so it lands where the server reads. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
2e500b0e2f
commit
ead2ca53b8
4 changed files with 24 additions and 30 deletions
|
|
@ -247,10 +247,6 @@ prefix = "artifacts"
|
|||
root = "/var/lib/fabro/objects"
|
||||
```
|
||||
|
||||
A custom local artifact root is preserved at startup and when `--storage-dir`
|
||||
changes the server's storage directory. When `local.root` is omitted, the
|
||||
default `<storage_root>/objects/artifacts` location follows that override.
|
||||
|
||||
The wizard only covers AWS S3 bucket/region plus one of:
|
||||
|
||||
- runtime credentials already supplied by the deployment environment
|
||||
|
|
|
|||
|
|
@ -16,14 +16,14 @@ async fn artifact_worker_captures_large_files_in_the_configured_local_store() {
|
|||
return;
|
||||
}
|
||||
let context = test_context!();
|
||||
let objects = context.temp_dir.join("selected-artifact-root");
|
||||
let settings = format!(
|
||||
"\n[server.artifacts]\nprovider = \"local\"\nprefix = \"selected-prefix\"\n[server.artifacts.local]\nroot = {:?}\n",
|
||||
objects.to_str().unwrap()
|
||||
);
|
||||
// RunningServer also passes --storage-dir. The explicit artifact directory
|
||||
// must still receive the captures, independently of the database root.
|
||||
let server = RunningServer::start_with(&settings, &[]).await;
|
||||
let server = RunningServer::start_with(
|
||||
"\n[server.artifacts]\nprovider = \"local\"\nprefix = \"selected-prefix\"\n",
|
||||
&[],
|
||||
)
|
||||
.await;
|
||||
// RunningServer explicitly selects --storage-dir, which also selects the
|
||||
// local artifact root. Inspect that resolved backend, outside the sandbox.
|
||||
let objects = server.storage_dir.join("objects/artifacts");
|
||||
let workspace = artifact_workspace(&context);
|
||||
tokio::fs::write(workspace.join("workflow.fabro"), r#"digraph Capture {
|
||||
graph [goal="Capture binary files", default_max_retries=0]
|
||||
|
|
@ -58,13 +58,6 @@ async fn artifact_worker_captures_large_files_in_the_configured_local_store() {
|
|||
serde_json::to_value(rebuilt.unwrap().artifacts).unwrap(),
|
||||
projection["artifacts"]
|
||||
);
|
||||
assert!(
|
||||
!server
|
||||
.storage_dir
|
||||
.join(format!("objects/artifacts/selected-prefix/{run_id}"))
|
||||
.exists(),
|
||||
"captures must not be redirected to the default artifact directory"
|
||||
);
|
||||
|
||||
for (path, size) in [
|
||||
("medium.bin", 3 * 1024 * 1024),
|
||||
|
|
|
|||
|
|
@ -1348,16 +1348,18 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn runtime_server_settings_preserve_custom_artifact_root() {
|
||||
fn runtime_server_settings_keep_local_artifacts_under_storage_dir() {
|
||||
// Servers have always kept local artifacts under the storage
|
||||
// directory, including installs whose settings name a `local.root`.
|
||||
let settings = server_settings(
|
||||
r#"
|
||||
_version = 1
|
||||
[server.storage]
|
||||
root = "/srv/from-disk"
|
||||
[server.artifacts]
|
||||
prefix = "selected-prefix"
|
||||
prefix = "artifacts"
|
||||
[server.artifacts.local]
|
||||
root = "/mnt/artifact-files"
|
||||
root = "/srv/from-disk/objects"
|
||||
"#,
|
||||
);
|
||||
for storage_root in ["/srv/from-disk", "/srv/from-runtime"] {
|
||||
|
|
@ -1365,7 +1367,13 @@ root = "/mnt/artifact-files"
|
|||
.clone()
|
||||
.with_storage_override(Path::new(storage_root));
|
||||
assert_eq!(resolved.server.storage.root, storage_root);
|
||||
assert_eq!(resolved.server.artifacts, settings.server.artifacts);
|
||||
assert_eq!(resolved.server.artifacts.prefix, "artifacts");
|
||||
assert_eq!(
|
||||
resolved.server.artifacts.store,
|
||||
fabro_types::settings::ObjectStoreSettings::Local {
|
||||
root: format!("{storage_root}/objects/artifacts"),
|
||||
}
|
||||
);
|
||||
// Startup and config reload can apply the same override again.
|
||||
assert_eq!(
|
||||
resolved
|
||||
|
|
|
|||
|
|
@ -16,14 +16,11 @@ pub struct ServerSettings {
|
|||
impl ServerSettings {
|
||||
#[must_use]
|
||||
pub fn with_storage_override(mut self, path: &Path) -> Self {
|
||||
// Only the derived default follows the storage directory. A custom
|
||||
// artifact location is independent of the database and runtime root.
|
||||
let default_artifact_root =
|
||||
ServerArtifactsSettings::default_local_root(Path::new(&self.server.storage.root));
|
||||
// The local artifact store always lives under the storage directory.
|
||||
// A configured `local.root` has never moved it, and existing objects
|
||||
// are only found there.
|
||||
if let ObjectStoreSettings::Local { root } = &mut self.server.artifacts.store {
|
||||
if *root == default_artifact_root {
|
||||
*root = ServerArtifactsSettings::default_local_root(path);
|
||||
}
|
||||
*root = ServerArtifactsSettings::default_local_root(path);
|
||||
}
|
||||
self.server.storage.root = path.display().to_string();
|
||||
self
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue