feat: add gc command and fix Docker-Content-Digest for Helm OCI

- Add nora gc --dry-run command for orphaned blob cleanup
- Fix Docker-Content-Digest header in blob upload response (enables Helm OCI push)
- Mark-and-sweep GC: list blobs, parse manifests, find/delete orphans

DevITWay
This commit is contained in:
2026-03-03 10:28:39 +00:00
parent e34032d08f
commit f560e5f76b
3 changed files with 144 additions and 1 deletions

View File

@@ -11,6 +11,7 @@ mod health;
mod metrics;
mod migrate;
mod openapi;
mod gc;
mod rate_limit;
mod registry;
mod repo_index;
@@ -61,6 +62,12 @@ enum Commands {
#[arg(short, long)]
input: PathBuf,
},
/// Garbage collect orphaned blobs
Gc {
/// Dry run - show what would be deleted without deleting
#[arg(long, default_value = "false")]
dry_run: bool,
},
/// Migrate artifacts between storage backends
Migrate {
/// Source storage: local or s3
@@ -143,6 +150,17 @@ async fn main() {
std::process::exit(1);
}
}
Some(Commands::Gc { dry_run }) => {
let result = gc::run_gc(&storage, dry_run).await;
println!("GC Summary:");
println!(" Total blobs: {}", result.total_blobs);
println!(" Referenced: {}", result.referenced_blobs);
println!(" Orphaned: {}", result.orphaned_blobs);
println!(" Deleted: {}", result.deleted_blobs);
if dry_run && !result.orphan_keys.is_empty() {
println!("\nRun without --dry-run to delete orphaned blobs.");
}
}
Some(Commands::Migrate { from, to, dry_run }) => {
let source = match from.as_str() {
"local" => Storage::new_local(&config.storage.path),