Skip to content

feat(preprod): Add upload-options endpoint for snapshot uploads#108312

Merged
lcian merged 7 commits intomasterfrom
feat/preprod-upload-options-endpoint
Feb 20, 2026
Merged

feat(preprod): Add upload-options endpoint for snapshot uploads#108312
lcian merged 7 commits intomasterfrom
feat/preprod-upload-options-endpoint

Conversation

@lcian
Copy link
Copy Markdown
Member

@lcian lcian commented Feb 16, 2026

Adds a new GET endpoint at /api/0/projects/{org}/{project}/preprodartifacts/snapshots/upload-options/ that returns objectstore upload configuration to the client.

The response is wrapped under an objectstore key to act as a discriminator for forward compatibility if the backing storage service changes. It includes:

  • url: the objectstore URL to use (currently the regional proxy URL)
  • scopes: arbitrary key/value pairs (currently org and project as string IDs)
  • expirationPolicy: formatted using objectstore_client's format_expiration utility, currently hardcoded

Also introduces a reusable ObjectstoreUploadOptions TypedDict in src/sentry/objectstore/types.py for other endpoints that will need to return similar upload configuration.

New project-scoped endpoint that returns all configuration needed by
sentry-cli to upload preprod snapshots in a single request, reducing
round-trips from multiple API calls to one.
@github-actions github-actions bot added the Scope: Backend Automatically applied to PRs that change backend components label Feb 16, 2026
@github-actions github-actions bot added the Scope: Frontend Automatically applied to PRs that change frontend components label Feb 16, 2026
@github-actions
Copy link
Copy Markdown
Contributor

🚨 Warning: This pull request contains Frontend and Backend changes!

It's discouraged to make changes to Sentry's Frontend and Backend in a single pull request. The Frontend and Backend are not atomically deployed. If the changes are interdependent of each other, they must be separated into two pull requests and be made forward or backwards compatible, such that the Backend or Frontend can be safely deployed independently.

Have questions? Please ask in the #discuss-dev-infra channel.

@lcian lcian marked this pull request as ready for review February 20, 2026 10:08
@lcian lcian requested a review from a team as a code owner February 20, 2026 10:08
@lcian
Copy link
Copy Markdown
Member Author

lcian commented Feb 20, 2026

bugbot run

@lcian
Copy link
Copy Markdown
Member Author

lcian commented Feb 20, 2026

@sentry review

Copy link
Copy Markdown
Contributor

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

@lcian
Copy link
Copy Markdown
Member Author

lcian commented Feb 20, 2026

bugbot run

@lcian
Copy link
Copy Markdown
Member Author

lcian commented Feb 20, 2026

@sentry review

},
expirationPolicy=format_expiration(
TimeToLive(timedelta(days=396))
), # Hardcoded for now
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Expiration policy inconsistent with server-side preprod TTL

Medium Severity

The expirationPolicy is hardcoded to TimeToLive(timedelta(days=396)) (≈13 months), but _PREPROD_USECASE in src/sentry/objectstore/__init__.py defines the server-side preprod TTL as TimeToLive(timedelta(days=30)). The snapshot endpoint (preprod_artifact_snapshot.py) writes manifests using get_preprod_session() which uses the 30-day TTL. Clients are told their uploads last 396 days, but server-side snapshot manifests expire in 30 days — the manifests would disappear long before the referenced data, creating an inconsistency.

Additional Locations (1)

Fix in Cursor Fix in Web

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For @rbro112

@lcian
Copy link
Copy Markdown
Member Author

lcian commented Feb 20, 2026

bugbot run

Copy link
Copy Markdown
Contributor

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

@lcian lcian merged commit 08d01e0 into master Feb 20, 2026
78 checks passed
@lcian lcian deleted the feat/preprod-upload-options-endpoint branch February 20, 2026 13:08
priscilawebdev pushed a commit that referenced this pull request Feb 24, 2026
)

Adds a new GET endpoint at
`/api/0/projects/{org}/{project}/preprodartifacts/snapshots/upload-options/`
that returns objectstore upload configuration to the client.

The response is wrapped under an `objectstore` key to act as a
discriminator for forward compatibility if the backing storage service
changes. It includes:
- `url`: the objectstore URL to use (currently the regional proxy URL)
- `scopes`: arbitrary key/value pairs (currently org and project as
string IDs)
- `expirationPolicy`: formatted using objectstore_client's
format_expiration utility, currently hardcoded

Also introduces a reusable `ObjectstoreUploadOptions` TypedDict in
`src/sentry/objectstore/types.py` for other endpoints that will need to
return similar upload configuration.

---------

Co-authored-by: getsantry[bot] <66042841+getsantry[bot]@users.noreply.github.com>
mchen-sentry pushed a commit that referenced this pull request Feb 24, 2026
)

Adds a new GET endpoint at
`/api/0/projects/{org}/{project}/preprodartifacts/snapshots/upload-options/`
that returns objectstore upload configuration to the client.

The response is wrapped under an `objectstore` key to act as a
discriminator for forward compatibility if the backing storage service
changes. It includes:
- `url`: the objectstore URL to use (currently the regional proxy URL)
- `scopes`: arbitrary key/value pairs (currently org and project as
string IDs)
- `expirationPolicy`: formatted using objectstore_client's
format_expiration utility, currently hardcoded

Also introduces a reusable `ObjectstoreUploadOptions` TypedDict in
`src/sentry/objectstore/types.py` for other endpoints that will need to
return similar upload configuration.

---------

Co-authored-by: getsantry[bot] <66042841+getsantry[bot]@users.noreply.github.com>
@github-actions github-actions bot locked and limited conversation to collaborators Mar 8, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

claude-code-assisted Scope: Backend Automatically applied to PRs that change backend components Scope: Frontend Automatically applied to PRs that change frontend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants