Skip to content

Commit dcc24dd

Browse files
feat(snapshots): Use retention endpoint for objectstore expiration policy
Fetch the snapshot retention value from the organization's preprod retention endpoint instead of using the expiration policy from the upload-options response. This allows the retention period to be configured per-organization via the backend. Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 3d06806 commit dcc24dd

File tree

3 files changed

+24
-5
lines changed

3 files changed

+24
-5
lines changed

src/api/data_types/snapshots.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@ pub struct CreateSnapshotResponse {
1212
pub image_count: u64,
1313
}
1414

15+
/// Response from the preprod retention endpoint.
16+
#[derive(Debug, Deserialize)]
17+
#[serde(rename_all = "camelCase")]
18+
pub struct PreprodRetentionResponse {
19+
pub snapshots: u64,
20+
}
21+
1522
// Keep in sync with https://github.com/getsentry/sentry/blob/master/src/sentry/preprod/snapshots/manifest.py
1623
/// Manifest describing a set of snapshot images for an app.
1724
#[derive(Debug, Serialize)]

src/api/mod.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1006,6 +1006,12 @@ impl AuthenticatedApi<'_> {
10061006
);
10071007
self.get(&path)?.convert()
10081008
}
1009+
1010+
/// Fetches the preprod retention policy for an organization.
1011+
pub fn fetch_preprod_retention(&self, org: &str) -> ApiResult<PreprodRetentionResponse> {
1012+
let path = format!("/organizations/{}/preprod/retention/", PathArg(org),);
1013+
self.get(&path)?.convert()
1014+
}
10091015
}
10101016

10111017
/// Available datasets for fetching organization events
@@ -2035,5 +2041,4 @@ pub struct SnapshotsUploadOptions {
20352041
pub struct ObjectstoreUploadOptions {
20362042
pub url: String,
20372043
pub scopes: Vec<(String, String)>,
2038-
pub expiration_policy: String,
20392044
}

src/commands/build/snapshots.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::collections::HashMap;
22
use std::fs;
33
use std::path::{Path, PathBuf};
4-
use std::str::FromStr as _;
4+
use std::time::Duration;
55

66
use anyhow::{Context as _, Result};
77
use clap::{Arg, ArgMatches, Command};
@@ -91,14 +91,20 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
9191

9292
validate_image_sizes(&images)?;
9393

94+
// Fetch retention policy for snapshot uploads
95+
let api = Api::current();
96+
let authenticated_api = api.authenticated()?;
97+
let retention = authenticated_api.fetch_preprod_retention(&org)?;
98+
debug!("Snapshot retention: {} days", retention.snapshots);
99+
94100
// Upload image files to objectstore
95101
println!(
96102
"{} Uploading {} image {}",
97103
style(">").dim(),
98104
style(images.len()).yellow(),
99105
if images.len() == 1 { "file" } else { "files" }
100106
);
101-
let manifest_entries = upload_images(images, &org, &project)?;
107+
let manifest_entries = upload_images(images, &org, &project, retention.snapshots)?;
102108

103109
// Build manifest from discovered images
104110
let manifest = SnapshotsManifest {
@@ -226,13 +232,14 @@ fn upload_images(
226232
images: Vec<ImageInfo>,
227233
org: &str,
228234
project: &str,
235+
retention_days: u64,
229236
) -> Result<HashMap<String, ImageMetadata>> {
230237
let api = Api::current();
231238
let authenticated_api = api.authenticated()?;
232239
let options = authenticated_api.fetch_snapshots_upload_options(org, project)?;
233240

234-
let expiration = ExpirationPolicy::from_str(&options.objectstore.expiration_policy)
235-
.context("Failed to parse expiration policy from upload options")?;
241+
let expiration =
242+
ExpirationPolicy::TimeToLive(Duration::from_secs(retention_days * 24 * 60 * 60));
236243

237244
let client = ClientBuilder::new(options.objectstore.url)
238245
.token({

0 commit comments

Comments
 (0)