Skip to content

Latest commit

 

History

History
200 lines (145 loc) · 8.39 KB

File metadata and controls

200 lines (145 loc) · 8.39 KB

Manifest

socket manifest <subcommand> generates declarative dependency manifests (pom.xml, requirements.txt, etc.) for ecosystems whose canonical build system does not ship one out of the box. The resulting files are consumed by socket scan create's server-side per-ecosystem parsers.

Subcommands

Sections are sorted alphabetically by subcommand name.

socket manifest auto

Auto-detect the build system in the target directory and run the matching manifest generator. Useful when you do not want to spell out the language.

socket manifest bazel [beta]

Generates Bazel SBOM manifests (Maven maven_install.json and/or PyPI requirements.txt) by running bazel query against discovered ecosystem hubs in a Bazel workspace. Output is consumed by socket scan create and closes the inline-declaration gap that lockfile-only parsing misses for Bazel monorepos.

Note: This command generates dependency manifests for Bazel workspaces (Maven and PyPI). It does not run reachability analysis.

Usage

socket manifest bazel [options] [DIR=.]

Options

  • --bazel <path> — path to bazel/bazelisk binary; default $(which bazelisk) || $(which bazel).
  • --bazel-rc <path> — path to additional .bazelrc fragments forwarded to bazel.
  • --bazel-flags <str> — flags forwarded to every bazel invocation (single quoted string).
  • --bazel-output-base <dir> — Bazel --output_base for read-only-cache CI environments.
  • --ecosystem <name> — ecosystem(s) to extract; repeatable. Supported values: maven, pypi. When omitted, Maven is generated by default; PyPI is explicit opt-in.
  • --out <dir> — output directory; default ./.socket/bazel-manifests/.
  • --dry-run, --verbose — standard diagnostic flags.

Upload: This subcommand only generates manifests. To generate and upload in one step, use socket scan create --auto-manifest . — it detects the workspace, generates Bazel Maven manifests, and uploads the result. Generate Bazel PyPI manifests explicitly with socket manifest bazel --ecosystem pypi, then scan the generated output with socket scan create.

Examples

# Generate the default Bazel Maven manifest from the current workspace.
socket manifest bazel .

# Generate only the PyPI manifest.
socket manifest bazel . --ecosystem pypi

# Generate both Maven and PyPI manifests explicitly.
socket manifest bazel . --ecosystem maven --ecosystem pypi

# Use bazelisk explicitly.
socket manifest bazel --bazel=/usr/local/bin/bazelisk .

Python/PyPI Extraction

When --ecosystem pypi is selected, the command:

  1. Discovers rules_python pip hubs from Bazel's mod show_extension output when available, with bounded static parsing of MODULE.bazel (pip.parse(hub_name = "...")) and legacy WORKSPACE (pip_parse(name = "...") / pip_install(name = "...")) retained as fallback. Hub names are never hardcoded; custom names like my_pypi are detected automatically.
  2. Validates each candidate hub by probing it with bazel query for :pkg targets / alias( rules. Invalid candidates are dropped.
  3. Runs bazel query 'deps(kind("py_library|py_binary|py_test", //...))' to determine which PyPI packages are actually reached by Python rules in the repo (test dependencies included for whole-repo scope).
  4. Reads requirements_lock.txt (the path discovered from pip.parse(requirements_lock = "...")) for canonical pinned versions. When the lockfile is unavailable, falls back to parsing pypi_name= and pypi_version= tags from the spoke py_library rules in the hub-and-spoke architecture.
  5. Emits a sorted canonical requirements.txt containing name==version lines for every reached package.

PyPI Name and Version Semantics

  • PEP 503 normalization. Package matching uses PEP 503 normalization (lowercase, then any run of -, _, or . is collapsed to a single -). Bazel target names use underscores (charset_normalizer); PyPI canonical names use hyphens (charset-normalizer). The emitted requirements.txt always uses the canonical hyphenated form.
  • Lockfile pins win. When the lockfile and spoke-repo tags disagree on a version, the lockfile wins because that is the version Bazel actually resolves at analysis time. A --verbose warning is logged for the divergence.
  • Conflict detection. When two reached packages normalize to the same PyPI name with different versions, the command fails clearly: a single requirements.txt cannot represent both versions, and silently picking one would produce a misleading SBOM.

Unsupported PyPI Forms

The PyPI extractor is intentionally narrow in this phase:

  • Direct URL, editable (-e), and unpinned requirements are not emitted. Only canonical name==version lines from the resolved lockfile are produced. Repositories that rely on unpinned or URL-pinned requirements will see those packages omitted from requirements.txt.
  • Private corpus validation requires authenticated GitHub access. When credentials are unavailable, the bazel-bench harness's private PyPI case skips cleanly with a distinct reason rather than failing.
  • Whole-repo extraction. The initial PyPI implementation emits one whole-workspace manifest. Per-target PyPI slicing is not currently supported.

Cross-Language Edges

Bazel repos with cross-language dependencies (e.g. rust_librarypy_library via PyO3 / cffi / etc.) are not traversed by the PyPI extractor in this phase. The PyPI extractor only covers Python rule dependencies reachable from py_library, py_binary, and py_test targets. Cross-language edges are assigned to Phase 4. The bazel-bench fixture constructed/python-pypi includes Go/Rust sidecars as validation context only; they are intentionally not asserted by the PyPI correctness cases.

Requirements

  • bazel or bazelisk on PATH (or pass --bazel <path>).
  • Network access on cold cache. Bazel and rules_jvm_external / rules_python own their own retry policy for transient resolution failures — socket manifest bazel does not retry on top of them.
  • Writable Bazel output base; pass --bazel-output-base for read-only-cache CI.
  • For PyPI extraction: a Python 3 interpreter on PATH so the rules_python toolchain can analyze the workspace.

This is the user-visible entry point for Bazel SBOM support (Maven and PyPI); the [beta] label and "Bazel SBOM support" wording must stay consistent across release notes and docs.

socket manifest cdxgen

Wraps the upstream cdxgen CycloneDX BOM generator for repos that already have a working cdxgen configuration.

socket manifest conda [beta]

Converts a Conda environment.yml file to a Python requirements.txt so the Socket scan pipeline can consume the resulting manifest.

socket manifest gradle [beta]

Uses Gradle (via the project's gradlew) to emit a pom.xml per subproject, then feeds those files into the Socket scan pipeline. Mirrors the kotlin and scala flows.

socket manifest kotlin [beta]

Uses Gradle to generate a manifest file (pom.xml) for a Kotlin project; the underlying flow is identical to the gradle subcommand.

socket manifest maven [beta]

Generates a Socket facts file (.socket.facts.json) from a Maven pom.xml project, using mvn (override with --bin, e.g. a project ./mvnw wrapper). Pass extra options through to maven with --maven-opts (e.g. --maven-opts="-P release -s settings.xml").

socket manifest scala [beta]

Generates a manifest file (pom.xml) from Scala's build.sbt file.

socket manifest setup

Starts an interactive configurator that writes default flag values for socket manifest into a socket.json in the current directory.

Dev

Run it like these examples:

# Scala:
npm run bs manifest scala -- --bin ~/apps/sbt/bin/sbt ~/socket/repos/scala/akka
# Gradle/Kotlin
npm run bs manifest yolo -- --cwd  ~/socket/repos/kotlin/kotlinx.coroutines

And upload with this:

npm exec socket scan create -- --repo=example-repo --branch=example-branch --tmp --cwd ~/repos/scala/akka example-org .
npm exec socket scan create -- --repo=example-repo --branch=example-branch --tmp --cwd ~/repos/kotlin/kotlinx.coroutines .

(The cwd option for create is necessary because we can't go to the dir and run npm exec).

Prod

User flow look something like this:

socket manifest scala .
socket manifest kotlin .
socket manifest yolo

socket scan create --repo=example-repo --branch=example-branch --tmp example-org .