Skip to content

bug(cli): stop uploads when Git filtering fails or selects no files #3847

Description

@alangou

User Story

As an OpenShell user uploading files to a sandbox, I want the default .gitignore filtering to be respected, so that only the files I intended to upload are transferred.

Problem Statement

Uploads use Git to apply filtering by default, but currently fall back to uploading the selected path without filtering when:

  • The Git check fails, for example because Git is unavailable. The filtering error is discarded and the upload proceeds without a warning about the fallback.
  • Filtering succeeds but selects no files. The CLI prints a warning and proceeds with an unfiltered upload.

This affects both sandbox upload and sandbox create --upload. The CLI already has --no-git-ignore for explicitly requesting an unfiltered upload.

This came up during Codex-assisted review of PR #3795, where Git needed to be added to the Snap package definition for the upload conformance tests to pass. Packaging Git addresses that particular trigger, but leaves the fallback behavior in place.

Impact / Why This Matters

The CLI can transfer ignored local files that the user did not intend to include. A warning after filtering selects nothing does not give the user a chance to stop that upload.

Users can work around this by staging only the intended files in a separate directory. That requires manual checking and copying despite filtering being enabled by default. Installing Git avoids the missing-executable case but does not cover other Git failures or an empty filtered selection.

Acceptance Criteria

  • When filtering is enabled and Git filtering fails, the affected upload stops before transferring files and reports the reason.
  • When filtering selects no files, the affected upload stops without falling back to an unfiltered transfer.
  • Diagnostics explain that --no-git-ignore can be used for an intentional unfiltered upload.
  • The behavior is consistent for sandbox upload and sandbox create --upload.
  • Explicit --no-git-ignore continues to allow unfiltered uploads.
  • Regression coverage includes unavailable/failing Git, an empty filtered selection, a normal filtered upload, and the explicit override. Behavior outside a Git repository is defined explicitly.
  • Relevant CLI documentation reflects the resulting behavior.

Reproduction Steps

Proposed reproduction with dummy files and a disposable sandbox; not run end-to-end during issue preparation:

  1. Initialize a temporary Git repository, add runs/ to .gitignore, and create runs/marker.txt containing dummy text.
  2. Run openshell sandbox upload <sandbox> <repo>/runs <destination> without --no-git-ignore.
  3. Observe the warning that filtering excluded all files, followed by an unfiltered upload of the selected directory.
  4. Separately, run an upload of the repository with Git unavailable to the CLI process, while keeping other upload prerequisites available. The current planner silently selects an unfiltered upload.
  5. Check the equivalent behavior using sandbox create --upload.

Expected: stop on filtering failure or an empty selection; require --no-git-ignore for an intentional unfiltered retry.

Environment

  • Product: OpenShell CLI.
  • Source inspected: 9f60f55c6b0811b1651099b50e4618d435ebc02e.
  • Discovery context: Snap packaging and Ubuntu VM conformance work in PR test(tmachine): build and test local Snap packages #3795.
  • Original binary version and exact OS version: not recorded in the report.

Code References

Static inspection confirms the fallback in crates/openshell-cli/src/run.rs:

  • sandbox_upload_plan() discards errors from git_sync_files() through an if let Ok(...) condition and falls through to Regular.
  • Both callers handle GitFilteredEmpty by warning and calling the unfiltered sandbox_sync_up().
  • sandbox_upload_plan_falls_back_when_all_files_gitignored currently tests the empty-selection fallback and will need updating.

Activity

  1. mnkj0021 commented on Sep 29, 2026

    @mnkj0021

    I would like to work on this. I checked current open PRs and did not find an implementation covering the fail-closed upload behavior. I will keep the change focused on stopping Git-filtered uploads on filtering errors or empty selections, preserve the explicit --no-git-ignore override, and update regression coverage for both upload entry points.

  2. mnkj0021 commented on Sep 29, 2026

    @mnkj0021

    I reviewed CONTRIBUTING after the initial triage. Since this issue does not yet have an accepted lifecycle state and first-time contributors require a maintainer vouch before submitting, I will wait for that project-side gate rather than start substantial implementation prematurely.

  3. alangou commented on Sep 29, 2026

    @alangou
    ContributorAuthor

    🏗️ build-plan

    Implementation Plan

    Issue type: fix
    Complexity: Low
    Confidence: High

    Summary

    Make the shared upload planner return an error when Git filtering fails or selects no files. Both upload entry points will require the existing --no-git-ignore override for intentional unfiltered uploads; preserve the existing symlink handling.

    Scope and Implementation Steps

    1. Update sandbox_upload_plan in crates/openshell-cli/src/run.rs, retain the underlying error with actionable guidance, and remove the empty-selection fallback variant and both callers' fallback branches.
    2. Update planner unit tests and CLI subprocess regression tests for ignored/empty selections, unavailable/failing Git, non-repository paths, successful filtering, and explicit override.
    3. Change the shared file-transfer conformance scenario to verify rejection, no remote output, and successful explicit unfiltered retry.
    4. Update sandbox upload documentation, the gateway architecture transfer overview, and the public CLI skill.

    Test Plan

    • Run focused CLI unit and subprocess tests, conformance crate checks, project tests, and pre-commit checks.
    • Run the Git-filtering conformance scenario against a gateway if the local runtime is available.
    • Run full local CI before opening a PR; report environment blockers precisely if any.

    Risks and Open Questions

    • Non-repository paths also require --no-git-ignore, because Git cannot apply repository filtering there.
    • Creation-time planning remains after provisioning; failure stops the affected transfer, not sandbox creation or earlier successful uploads.
    • No changes to gateway configuration, isolation, or symlink semantics are planned.

    Documentation Impact

    Update docs/how-it-works/sandboxes/overview.mdx, architecture/gateway.md, and skills/openshell-cli/SKILL.md. Navigation is unchanged.


    Revision 1 — initial plan. Direct implementation request; lifecycle and queue labels left unchanged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions