diff --git a/doc/cli/cloud-security.md b/doc/cli/cloud-security.md index 83ecbbb3..3c86af61 100644 --- a/doc/cli/cloud-security.md +++ b/doc/cli/cloud-security.md @@ -308,6 +308,33 @@ limacharlie cloudsec code autofix # open the upgrade PR limacharlie cloudsec code ingest --repo acme/api --source sarif --file report.sarif ``` +For a repository created through ingest, a CI push that names a branch should +send its default branch too: + +```bash +limacharlie cloudsec code ingest --repo acme/api --source sarif --file report.sarif \ + --ref refs/heads/main --default-branch main +``` + +Only a push for the known default branch can reconcile the repository's findings. +An explicit branch without a stored default branch is refused for a connected +repository or a new repository created through ingest. A legacy ingest-created +repository with prior findings or a scan stamp but no stored default records +activity only, with `default_branch_unknown` in the response. A repository +first seen through a pull request can establish its default on a later matching +branch push. A connected repository's default +branch is recorded from its source-control provider; +older rows may need a collector refresh. Until then, omit `--ref` to assert +that the document describes the default branch. `--default-branch` on the +same explicit push cannot establish that fact. A pull-request, feature-branch +or tag push can still report activity, but it does not alter the +repository's findings when the default is known; use `code pr-check` for a +pull request. An omitted ref or literal `HEAD` retains the legacy assertion that the document +describes the default branch. A branch claiming a default that conflicts with +the stored branch records activity only. After a rename, a repository created +through ingest can restate it with one ref-less push and the new +`--default-branch`; a connected repository uses the provider's next refresh. + `code ingest` (and `code scan --ingest`) retries a push the service answers with HTTP 429, which means the organization already has as many pushes in progress as it may, or the request quota is spent. It waits at least the response's `Retry-After`, adds random jitter so a CI fan-out that was refused together does not come back together, and gives up after 5 retries or 10 minutes of waiting, exiting with the rate-limit error. A refused push recorded nothing, so the retry is safe. `code repos` reports `scan_status` as `scanned`, `partial` or `unknown`. `partial` means the scan tripped a limit, so the finding set is INCOMPLETE — not a clean bill. `unknown` means this view has no scan state and says so rather than guessing; `code status` is the authoritative view of the run. diff --git a/limacharlie/commands/cloudsec.py b/limacharlie/commands/cloudsec.py index 73bb0a68..43f63e41 100644 --- a/limacharlie/commands/cloudsec.py +++ b/limacharlie/commands/cloudsec.py @@ -2199,11 +2199,14 @@ def code_autofix(ctx, finding_id, repo, provider) -> None: help="Path to the document. A '.gz' file is sent compressed.") @click.option("--commit", default=None, help="The revision the document describes. Recorded, not verified.") -@click.option("--ref", default=None, help="The branch or tag, for context.") +@click.option("--ref", default=None, + help="The branch or tag the document describes. Only the default branch " + "updates repository findings; omit this for a connected repository " + "without a stored default branch.") @click.option("--default-branch", "default_branch", default=None, - help="The repository's shipping branch. Only worth sending for a " - "repository LimaCharlie does not collect — nothing else can " - "state it there.") + help="The repository's shipping branch. Send it with an explicit branch " + "ref for a repository created through ingest; on a connected " + "repository, an explicit ref alone cannot establish the default.") @click.option("--provider", default=None, help="Source-control provider the key belongs to (default github).") @click.option("--scanner-succeeded/--scanner-failed", "scanner_succeeded", default=None, diff --git a/limacharlie/sdk/cloudsec.py b/limacharlie/sdk/cloudsec.py index 3cb74047..668c456b 100644 --- a/limacharlie/sdk/cloudsec.py +++ b/limacharlie/sdk/cloudsec.py @@ -2965,10 +2965,14 @@ def ingest_code_results( commit: the revision the document describes. Recorded, not verified, and worth sending: it is what tells somebody reading a finding which checkout produced it. - default_branch: the repository's shipping branch. Only worth - sending for a repository LimaCharlie does not collect — - nothing else can state it there, and it is left unset rather - than guessed when you do not know it. + ref: the branch or tag the document describes. Only the known + default branch may reconcile repository findings. Omit this + to assert a whole-repository scan for a connected repository + with no stored default branch. + default_branch: the repository's shipping branch. Send this with + an explicit branch ref for a repository created through + ingest. A connected repository with no stored default branch + cannot establish it from an explicit ref alone. busy_retries: how many times to re-send the push when it is refused with 429 — the organization already has as many pushes in progress as it may (``error_code: "ingest_busy"``),