Skip to content

snapshots upload --selective with an empty image dir creates no snapshot even when --all-image-file-names-file lists the full suite #3391

Description

@joshdholtz

Problem Statement

Summary

sentry-cli snapshots upload given an empty directory prints "No image files found" and returns early without creating a snapshot, even when --all-image-file-names-file is passed with the complete image list. This makes it impossible to record an "all unchanged" build for a selective upload.

Context

We use selective uploads for PR visual diffing: on each PR we diff against a baseline and upload only changed/added images with --selective --all-image-file-names-file <all names>. The names file is meant to let Sentry tell "skipped" (unchanged, still present) apart from "removed".

Problem

For any PR that changes no images, the selective staging directory is empty. snapshots upload early-returns: in src/commands/snapshots/upload.rs, the if images.is_empty() { ... return Ok(()) } guard runs before --all-image-file-names-file is parsed and before the manifest is POSTed. Result: the PR gets no snapshot build at all, so there is nothing for reviewers/checks to see, and the "everything unchanged" state cannot be represented.

Expected

When --all-image-file-names-file (or --all-image-file-names) is provided, a selective upload with zero image files should still create a snapshot/manifest that references the full name list as unchanged, instead of early-returning.

Version

sentry-cli 3.6.0

Workaround

We currently skip the upload entirely when nothing changed, accepting that all-unchanged PRs have no snapshot build.

Solution Brainstorm

When --all-image-file-names/--all-image-file-names-file is present, treat the name list (not the on-disk image count) as the source of truth for what the snapshot should contain, so an empty upload directory is a valid "everything unchanged" case rather than a no-op.

Concretely, in src/commands/snapshots/upload.rs::execute, the early if images.is_empty() { return Ok(()) } guard fires before --all-image-file-names-file is parsed and before the manifest is POSTed. A zero-image selective upload with a full name list could instead build and POST a manifest with no changed image entries, letting the server record every listed name as unchanged/skipped.

Options, roughly in order of preference:

  1. Skip the empty-dir early return when a full name list is provided, and POST an empty-images manifest (selective: true, full all_image_file_names). The server already knows how to reconcile skipped vs removed from that list.
  2. Add an explicit flag (e.g. --allow-empty) that opts into creating an all-unchanged snapshot.
  3. At minimum, exit non-zero (or warn loudly) when --selective + a names file is given but zero images are uploaded, so callers know no snapshot was created instead of it silently succeeding.

Our current workaround is to detect the zero-change case ourselves and skip the upload, which leaves those PRs without a snapshot build.

Metadata

Metadata

Assignees

No one assigned

    Projects

    Status
    Waiting for: Product Owner

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions