From d8d858b6276b51d63ef3a7267bf95028897a526e Mon Sep 17 00:00:00 2001 From: Cyborg Viktor <307551610+vpetersson-bot@users.noreply.github.com> Date: Tue, 1 Sep 2026 11:30:58 +0000 Subject: [PATCH] docs: VCS detection everywhere, and /workspace is the mount Catches the sbomify-action docs up with the CI runtime platform layer (sbomify-action#401) and the audit trail path change (#400). VCS metadata is no longer a GitHub/GitLab/Bitbucket/TeamCity feature. Platforms that publish no repository variables now read the git checkout, so Jenkins, CircleCI, Azure Pipelines and any other container runner get provenance with no configuration -- the pages for all four told people to hand-write vcs_url into sbomify.json. A local run is the exception: it reads the checkout only under SBOMIFY_LOCAL_VCS=true, so an internal remote does not end up in a document that leaves the company. The image gained WORKDIR /workspace, so every docker run example loses its -w. The old `-v "$PWD:/github/workspace" -w /github/workspace` still resolves and the generic runner page says so, along with the trap that comes with it: outputs are written relative to the working directory, so a mount without a matching -w leaves the SBOM inside the container. TeamCity's `-w /github/workspace` was wrong before this branch and is gone from all four places it appeared. The Docker Wrapper mounts the checkout and runs the script inside it; overriding -w pointed the run at a directory that is not the checkout, which the same page contradicted two paragraphs later. Also: Bitbucket Data Center gets no guessed commit URL, the wizard refuses on any recognised CI platform rather than $CI and $GITHUB_ACTIONS alone, WORKING_DIR confinement is GitHub Actions only, and audit trail paths are recorded relative to the working directory. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01KpQTA8RTVfX4wm5is4S4MQ --- content/sbomify-action/_index.md | 14 ++++--- content/sbomify-action/advanced.md | 5 ++- content/sbomify-action/augmentation.md | 39 ++++++++++++++----- content/sbomify-action/configuration.md | 6 ++- content/sbomify-action/how-it-works.md | 2 +- content/sbomify-action/quickstart.md | 8 ++-- content/sbomify-action/runtimes/_index.md | 25 ++++++------ .../sbomify-action/runtimes/azure-devops.md | 16 ++++---- content/sbomify-action/runtimes/bitbucket.md | 2 + content/sbomify-action/runtimes/circleci.md | 10 +++-- content/sbomify-action/runtimes/docker.md | 33 +++++++++------- .../sbomify-action/runtimes/github-actions.md | 3 +- content/sbomify-action/runtimes/jenkins.md | 12 ++++-- content/sbomify-action/runtimes/local.md | 20 +++++++--- content/sbomify-action/runtimes/teamcity.md | 9 ++--- 15 files changed, 121 insertions(+), 83 deletions(-) diff --git a/content/sbomify-action/_index.md b/content/sbomify-action/_index.md index 2791732..c54ca13 100644 --- a/content/sbomify-action/_index.md +++ b/content/sbomify-action/_index.md @@ -63,17 +63,19 @@ The core tool behaves identically everywhere. What differs is how you invoke it, | [GitHub Actions](/sbomify-action/runtimes/github-actions/) | Native action | OIDC or token | Yes | Generates workflow | Yes | | [GitLab CI](/sbomify-action/runtimes/gitlab-ci/) | Container image | Token | Yes | No | No | | [Bitbucket](/sbomify-action/runtimes/bitbucket/) | Container image | Token | Yes | No | No | -| [Jenkins](/sbomify-action/runtimes/jenkins/) | Container image | Token | Manual | No | No | -| [CircleCI](/sbomify-action/runtimes/circleci/) | Container image | Token | Manual | No | No | -| [Azure DevOps](/sbomify-action/runtimes/azure-devops/) | Container image | Token | Manual | No | No | -| [Any container runner](/sbomify-action/runtimes/docker/) | Container image | Token | Manual | No | No | +| [Jenkins](/sbomify-action/runtimes/jenkins/) | Container image | Token | From git | No | No | +| [CircleCI](/sbomify-action/runtimes/circleci/) | Container image | Token | From git | No | No | +| [Azure DevOps](/sbomify-action/runtimes/azure-devops/) | Container image | Token | From git | No | No | +| [Any container runner](/sbomify-action/runtimes/docker/) | Container image | Token | From git | No | No | | [TeamCity](/sbomify-action/runtimes/teamcity/) | Container image | Token | Git roots | No | No | -| [Local machine](/sbomify-action/runtimes/local/) | `uvx` or `pipx` | Token | Manual | Yes | No | +| [Local machine](/sbomify-action/runtimes/local/) | `uvx` or `pipx` | Token | Opt-in | Yes | No | -**Manual** means the runtime does not expose enough environment information for automatic detection, so you set `vcs_url`, `vcs_commit_sha` and `vcs_ref` in [`sbomify.json`](/sbomify-action/augmentation/) instead. Everything else works the same. +**Yes** means the runtime publishes repository URL, commit SHA and ref as environment variables and they are read from there. **From git** means it does not, so the action reads the checkout it is running in - no configuration either way, as long as the `.git` directory is present and the repository has a remote. **Git roots** means TeamCity, which is VCS-agnostic: detection runs only when the repository URL positively identifies Git, and stays silent otherwise rather than recording a Subversion revision as if it were a commit. See [TeamCity](/sbomify-action/runtimes/teamcity/#vcs-information). +**Opt-in** means a local run reads the checkout only when you set `SBOMIFY_LOCAL_VCS=true`, so an internal remote does not end up in a document by accident. `vcs_url`, `vcs_commit_sha` and `vcs_ref` in [`sbomify.json`](/sbomify-action/augmentation/) override whatever is detected, on every runtime. + OIDC trusted publishing and build provenance attestation are GitHub-only today because they depend on GitHub-issued identity tokens. Support for other runtimes will follow as those platforms expose equivalent primitives. ## Documentation diff --git a/content/sbomify-action/advanced.md b/content/sbomify-action/advanced.md index eadb72a..fa698ab 100644 --- a/content/sbomify-action/advanced.md +++ b/content/sbomify-action/advanced.md @@ -100,6 +100,8 @@ Three outputs: Four categories are tracked: overrides from the CLI or environment, augmentation values and their source, per-component enrichment additions, and sanitization fixes such as PURL normalisation. Timestamps are UTC, ISO 8601. +File paths in the trail are recorded relative to the working directory, and anything outside it is reduced to its file name. The trail is meant to be handed to someone who did not run the build, and the absolute path of your lock file tells them nothing while publishing the build machine's directory layout and username. + Archive `audit_trail.txt` alongside your SBOM. Together they answer "where did every field in this document come from?" - which is the question that actually gets asked in an audit. ## Caching @@ -148,9 +150,8 @@ generate-sbom: docker volume create sbomify-cache docker run --rm \ - -v "$(pwd):/github/workspace" \ + -v "$(pwd):/workspace" \ -v sbomify-cache:/cache \ - -w /github/workspace \ -e SBOMIFY_CACHE_DIR=/cache/sbomify \ -e SYFT_CACHE_DIR=/cache/syft \ -e LOCK_FILE=requirements.txt \ diff --git a/content/sbomify-action/augmentation.md b/content/sbomify-action/augmentation.md index 6750067..ea8e2a3 100644 --- a/content/sbomify-action/augmentation.md +++ b/content/sbomify-action/augmentation.md @@ -99,14 +99,20 @@ By default augmentation only fills fields that are empty. Set `OVERRIDE_SBOM_MET ## Automatic VCS detection -When running in supported CI environments, repository URL, commit SHA and branch or tag are detected and added automatically. No configuration needed. +Repository URL, commit SHA and branch or tag are detected and added automatically on every CI runtime. No configuration needed. -| Runtime | Detected | Notes | -| ------------------- | ----------------------------------------- | ---------------------------------------------------- | -| GitHub Actions | Repository URL, commit SHA, branch or tag | Works with GitHub Enterprise Server | -| GitLab CI | Project URL, commit SHA, ref name | Works with self-managed instances | -| Bitbucket Pipelines | Repository URL, commit SHA, branch or tag | | -| TeamCity | Repository URL, commit SHA, branch or tag | Git roots only - see [below](#teamcity-is-different) | +Where a vendor publishes those details as environment variables, they are read from there. Everywhere else the action reads them from the git checkout it is running in, which is why Jenkins, CircleCI, Azure Pipelines and any other container runner get provenance without you writing it out by hand. + +| Runtime | Source | Notes | +| ------------------------------------------------------------------------------------------------------ | ------------------------------------------------ | ------------------------------------------------------------------- | +| GitHub Actions | Runner environment | Works with GitHub Enterprise Server | +| GitLab CI | Job environment | Works with self-managed instances | +| Bitbucket Pipelines | Step environment | Bitbucket Cloud; Data Center needs `vcs_url` in `sbomify.json` | +| TeamCity | Build properties file | Git roots only - see [below](#teamcity-is-different) | +| Jenkins, CircleCI, Azure Pipelines, Buildkite, Drone, Travis CI, AppVeyor, AWS CodeBuild, any other CI | The git checkout (`git remote`, `git rev-parse`) | Needs the `.git` directory in the container and a configured remote | +| Your own machine | The git checkout, opt-in | Set `SBOMIFY_LOCAL_VCS=true` - see [below](#local-runs-are-opt-in) | + +Each records repository URL, commit SHA and branch or tag. A browsable commit URL is added as well for github.com, gitlab.com and bitbucket.org, plus self-hosted GitHub and GitLab, whose commit paths match their cloud products. Everything else - Bitbucket Data Center included, since it lays commit URLs out differently from Bitbucket Cloud - gets the repository URL and the SHA without a link, rather than a guessed one that 404s. What gets written: @@ -121,9 +127,16 @@ TeamCity is VCS-agnostic, and a root can just as easily be Subversion, Perforce TeamCity exposes no parameter saying which VCS a root uses. Detection therefore runs only when the repository URL positively identifies Git, and emits nothing otherwise. A self-hosted Git server whose URL has neither a `.git` suffix nor a recognised host cannot be detected; set `SBOMIFY_VCS_URL` (and `SBOMIFY_VCS_REF`) and it is trusted as given. See the [TeamCity runtime guide](/sbomify-action/runtimes/teamcity/#vcs-information). -### Other runtimes +### Runtimes read from the checkout + +Jenkins, CircleCI, Azure Pipelines and any other container runner have no vendor integration, and none is needed: they check out a git repository and run a command in it, so the action asks `git` directly. Two conditions have to hold, and both are the default: + +- **The `.git` directory has to be there.** A shallow clone is fine; an exported tarball or a mount of only your lockfile is not. +- **The repository needs a remote.** `origin` is used if present, otherwise the first remote. A checkout with no remote has no URL worth recording, so nothing is emitted. -Jenkins, CircleCI, Azure DevOps and plain container runs do not expose enough standard environment information for reliable detection. Set the values yourself: +A runner is recognised as CI when it sets `CI=true` or a vendor variable of its own (`JENKINS_URL`, `CIRCLECI`, `TF_BUILD`, `BUILDKITE`, `DRONE`, `TRAVIS`, `APPVEYOR`, `CODEBUILD_BUILD_ID`). Almost every runner sets one; a bare `docker run` from a shell script sets neither and is treated as a local run. + +If any of that does not hold, or the remote URL is not the one you want in the document, set the fields yourself: ```json { @@ -133,7 +146,13 @@ Jenkins, CircleCI, Azure DevOps and plain container runs do not expose enough st } ``` -Most CI systems expose the commit SHA in some environment variable, so this is usually a small template change in your pipeline definition. +`sbomify.json` takes priority over detection, so this is also how you replace an internal remote URL with the public one. + +### Local runs are opt-in + +On your own machine nothing is read from the checkout unless you ask for it. The same lock file would otherwise produce a different SBOM depending on whether a remote happened to be configured, and an internal remote would be written into a document that often leaves the company. + +Set `SBOMIFY_LOCAL_VCS=true` to opt in, or state the fields in `sbomify.json` as above. On CI it stays automatic - that is the point of it. ### Overriding or disabling diff --git a/content/sbomify-action/configuration.md b/content/sbomify-action/configuration.md index 9d65e6a..08c08e1 100644 --- a/content/sbomify-action/configuration.md +++ b/content/sbomify-action/configuration.md @@ -59,9 +59,10 @@ Non-SBOM `BOM_TYPE` values are uploaded verbatim to sbomify: augmentation, enric | `COMPONENT_PURL` | none | Add or override the component PURL. | | `ADDITIONAL_PACKAGES` | none | Inline PURLs to inject, comma or newline separated. | | `ADDITIONAL_PACKAGES_FILE` | `additional_packages.txt` | Path to a file of PURLs, one per line. | -| `DISABLE_VCS_AUGMENTATION` | `false` | Disable automatic VCS detection from the CI environment. | +| `DISABLE_VCS_AUGMENTATION` | `false` | Disable automatic VCS detection, whether it comes from the CI environment or the git checkout. | +| `SBOMIFY_LOCAL_VCS` | `false` | Read VCS details from the git checkout on a non-CI run. Detection is automatic on CI and opt-in locally. | | `SUBMODULE_PATH` | none | Treat the component as a git submodule pinned at this path. Resolves the pin to a version and reuses an existing SBOM at that version if there is one. Requires `LOCK_FILE` and the `sbomify` destination. | -| `WORKING_DIR` | none | Working directory. On GitHub Actions prefer the `working-dir` input. | +| `WORKING_DIR` | none | Working directory. Relative paths resolve against the current directory, or against the runner workspace on GitHub Actions, where the path must also stay inside it. Prefer the `working-dir` input there. | ## Uploading @@ -150,6 +151,7 @@ You do not set these. They are read from the environment to detect VCS informati - **GitLab CI** - `CI_PROJECT_URL`, `CI_PROJECT_PATH`, `CI_SERVER_URL`, `CI_COMMIT_SHA`, `CI_COMMIT_REF_NAME`, `CI_PIPELINE_ID`, `CI_PROJECT_VISIBILITY` - **Bitbucket** - `BITBUCKET_WORKSPACE`, `BITBUCKET_REPO_SLUG`, `BITBUCKET_COMMIT`, `BITBUCKET_BRANCH`, `BITBUCKET_TAG`, `BITBUCKET_GIT_HTTP_ORIGIN` - **TeamCity** - `TEAMCITY_VERSION`, `BUILD_VCS_NUMBER` (and `BUILD_VCS_NUMBER_` on multi-root builds), `TEAMCITY_BUILD_PROPERTIES_FILE` +- **Every other CI system** - `CI`, plus the vendor marker it sets: `JENKINS_URL` or `JENKINS_HOME`, `CIRCLECI`, `TF_BUILD`, `BUILDKITE`, `DRONE`, `TRAVIS`, `APPVEYOR`, `CODEBUILD_BUILD_ID`. These only name the platform in logs and telemetry - the repository details come from the git checkout. The matching checkout-path variables (`WORKSPACE`, `CIRCLE_WORKING_DIRECTORY`, `BUILD_REPOSITORY_LOCALPATH`, `SYSTEM_DEFAULTWORKINGDIRECTORY`, `BUILDKITE_BUILD_CHECKOUT_PATH`, `DRONE_WORKSPACE`, `TRAVIS_BUILD_DIR`, `APPVEYOR_BUILD_FOLDER`, `CODEBUILD_SRC_DIR`) are used when they point at a directory that exists inside the container. The two OIDC request variables only exist when the workflow grants `permissions: id-token: write`. diff --git a/content/sbomify-action/how-it-works.md b/content/sbomify-action/how-it-works.md index 1d9b89a..824fa22 100644 --- a/content/sbomify-action/how-it-works.md +++ b/content/sbomify-action/how-it-works.md @@ -97,7 +97,7 @@ This matters for compliance: component hashes are a [CISA 2025](/compliance/cisa ## 2. Augmentation -Adds organisational metadata - supplier, authors, licenses, lifecycle phase, security contact, support dates - and VCS information detected from the CI environment. +Adds organisational metadata - supplier, authors, licenses, lifecycle phase, security contact, support dates - and VCS information detected from the CI environment, or from the git checkout on runtimes that publish none. Sources are consulted in priority order, and **local values always win**: diff --git a/content/sbomify-action/quickstart.md b/content/sbomify-action/quickstart.md index bd7344f..936495d 100644 --- a/content/sbomify-action/quickstart.md +++ b/content/sbomify-action/quickstart.md @@ -20,8 +20,7 @@ Run it from the root of your repository: ```bash docker run --rm -it \ - -v "$(pwd):/github/workspace" \ - -w /github/workspace \ + -v "$(pwd):/workspace" \ ghcr.io/sbomify/sbomify-action \ sbomify-action wizard ``` @@ -54,7 +53,7 @@ Either way there is nothing else to install - whatever generator your project ne ### Things worth knowing -- The wizard is **interactive**, so the `-it` flags are required, and it refuses to launch in CI (it checks `$CI` and `$GITHUB_ACTIONS`). Run it on your machine and commit the result. +- The wizard is **interactive**, so the `-it` flags are required, and it refuses to launch on any environment it recognises as CI - `CI=true`, or a vendor marker such as `GITHUB_ACTIONS`, `GITLAB_CI` or `JENKINS_URL`. Run it on your machine and commit the result. - The volume mount is what lets it write the generated workflow back into your repository. Without it, the wizard runs but produces nothing you keep. - It only manages `.github/workflows/sboms.yml`, and marks files it generated with a header. It will never overwrite a workflow you wrote by hand. - It pins the action to a specific commit SHA at generation time, which is the recommended practice. @@ -83,8 +82,7 @@ On any runtime other than GitHub Actions, the same configuration is passed to th ```bash docker run --rm \ - -v "$(pwd):/github/workspace" \ - -w /github/workspace \ + -v "$(pwd):/workspace" \ -e LOCK_FILE=requirements.txt \ -e OUTPUT_FILE=sbom.cdx.json \ -e ENRICH=true \ diff --git a/content/sbomify-action/runtimes/_index.md b/content/sbomify-action/runtimes/_index.md index 5b68094..73696df 100644 --- a/content/sbomify-action/runtimes/_index.md +++ b/content/sbomify-action/runtimes/_index.md @@ -19,9 +19,9 @@ If your platform can run a container, it is supported - even if it does not have - [**GitHub Actions**](/sbomify-action/runtimes/github-actions/) - native action, OIDC trusted publishing, build provenance attestation - [**GitLab CI**](/sbomify-action/runtimes/gitlab-ci/) - container image, automatic VCS detection, self-managed supported - [**Bitbucket Pipelines**](/sbomify-action/runtimes/bitbucket/) - container image via a Docker pipe, automatic VCS detection -- [**Jenkins**](/sbomify-action/runtimes/jenkins/) - declarative and scripted pipelines -- [**CircleCI**](/sbomify-action/runtimes/circleci/) - container executor -- [**Azure DevOps**](/sbomify-action/runtimes/azure-devops/) - container job or Docker task +- [**Jenkins**](/sbomify-action/runtimes/jenkins/) - declarative and scripted pipelines, VCS detected from the checkout +- [**CircleCI**](/sbomify-action/runtimes/circleci/) - container executor, VCS detected from the checkout +- [**Azure DevOps**](/sbomify-action/runtimes/azure-devops/) - container job or Docker task, VCS detected from the checkout - [**TeamCity**](/sbomify-action/runtimes/teamcity/) - Docker Wrapper build feature or Kotlin DSL - [**Any container runner**](/sbomify-action/runtimes/docker/) - Drone, Woodpecker, Buildkite, Concourse, or a plain shell - [**Local machine**](/sbomify-action/runtimes/local/) - `uvx`, `pipx` or Docker on your laptop @@ -33,17 +33,19 @@ If your platform can run a container, it is supported - even if it does not have | GitHub Actions | Native action | OIDC or token | Yes | Generates workflow | Yes | | GitLab CI | Container image | Token | Yes | No | No | | Bitbucket | Container image | Token | Yes | No | No | -| Jenkins | Container image | Token | Manual | No | No | -| CircleCI | Container image | Token | Manual | No | No | -| Azure DevOps | Container image | Token | Manual | No | No | -| Any container runner | Container image | Token | Manual | No | No | +| Jenkins | Container image | Token | From git | No | No | +| CircleCI | Container image | Token | From git | No | No | +| Azure DevOps | Container image | Token | From git | No | No | +| Any container runner | Container image | Token | From git | No | No | | [TeamCity](/sbomify-action/runtimes/teamcity/) | Container image | Token | Git roots | No | No | -| Local machine | `uvx` or `pipx` | Token | Manual | Yes | No | +| Local machine | `uvx` or `pipx` | Token | Opt-in | Yes | No | -**VCS auto-detect** means the action reads repository URL, commit SHA and branch from the environment without configuration. Where it says _Manual_, the platform does not expose that information in a standard enough form, so you set `vcs_url`, `vcs_commit_sha` and `vcs_ref` in [`sbomify.json`](/sbomify-action/augmentation/#automatic-vcs-detection) instead. It is a few lines, and everything else behaves the same. +**VCS auto-detect** means the action records repository URL, commit SHA and branch without configuration. _Yes_ is read from the platform's own environment variables. _From git_ is read from the checkout the job is running in, which covers every CI system with no vendor integration of its own - it needs the `.git` directory to be present and the repository to have a remote, both of which a normal CI checkout gives you. _Git roots_ is TeamCity, which is VCS-agnostic and can be backed by Subversion, Perforce or TFVC as easily as Git. Detection runs only when the repository URL positively identifies Git, and emits nothing otherwise rather than recording a changelist number as a commit SHA. See [TeamCity](/sbomify-action/runtimes/teamcity/#vcs-information). +_Opt-in_ is a run on your own machine: it reads the checkout only when you set `SBOMIFY_LOCAL_VCS=true`, so an internal remote is never written into a document by accident. On every runtime, `vcs_url`, `vcs_commit_sha` and `vcs_ref` in [`sbomify.json`](/sbomify-action/augmentation/#automatic-vcs-detection) override what was detected. + **OIDC trusted publishing** and **attestation** are GitHub-only today because both depend on GitHub-issued identity tokens. Other runtimes authenticate with an API token, and can sign with [cosign](/faq/how-do-i-sign-an-sbom/) rather than GitHub's provenance tooling. Support will expand as platforms expose equivalent primitives. ## The universal pattern @@ -52,8 +54,7 @@ Every non-GitHub runtime is a variation on this: ```bash docker run --rm \ - -v "$(pwd):/github/workspace" \ - -w /github/workspace \ + -v "$(pwd):/workspace" \ -e LOCK_FILE=requirements.txt \ -e OUTPUT_FILE=sbom.cdx.json \ -e ENRICH=true \ @@ -61,7 +62,7 @@ docker run --rm \ ghcr.io/sbomify/sbomify-action ``` -Mount your repository, set the working directory, pass configuration as environment variables. The image entrypoint is `sbomify-action`, so no command is needed unless you want a subcommand such as `wizard` or `yocto`. +Mount your repository at `/workspace` - the image's working directory, so no `-w` is needed - and pass configuration as environment variables. Any other mount point works as long as `-w` points at it, including the `/github/workspace` older examples used. The image entrypoint is `sbomify-action`, so no command is needed unless you want a subcommand such as `wizard` or `yocto`. Whatever your platform's syntax for "run this container with these variables" is, that is your integration. diff --git a/content/sbomify-action/runtimes/azure-devops.md b/content/sbomify-action/runtimes/azure-devops.md index 5fb4576..544ac6b 100644 --- a/content/sbomify-action/runtimes/azure-devops.md +++ b/content/sbomify-action/runtimes/azure-devops.md @@ -4,10 +4,10 @@ url: /sbomify-action/runtimes/azure-devops/ aliases: - /guides/sbomify-action/runtimes/azure-devops/ title: "SBOM Generation in Azure DevOps" -description: "Run the sbomify action in Azure Pipelines as a container job or Docker task, with variable groups, caching and manual VCS configuration." +description: "Run the sbomify action in Azure Pipelines as a container job or Docker task, with variable groups, caching and automatic VCS detection." keywords: ["Azure DevOps SBOM", "Azure Pipelines SBOM", "CycloneDX Azure"] section: sbomify-action -tldr: "Run the container image as a container job, or invoke it with the Docker task. Set VCS details in sbomify.json, since Azure's variables are not auto-detected." +tldr: "Run the container image as a container job, or invoke it with the Docker task. Repository details are detected from the git checkout; sbomify.json overrides them." --- Azure Pipelines can run the container image either as a container job, which is cleaner, or through the Docker task. @@ -51,8 +51,7 @@ steps: inputs: command: run arguments: > - -v $(Build.SourcesDirectory):/github/workspace - -w /github/workspace + -v $(Build.SourcesDirectory):/workspace -e LOCK_FILE=requirements.txt -e OUTPUT_FILE=sbom.cdx.json -e ENRICH=true @@ -131,7 +130,9 @@ Set `GITHUB_TOKEN` even though you are not on GitHub. License databases are down ## VCS information -Azure DevOps does not expose repository details in the form the action auto-detects. Set them in `sbomify.json`, generated from the build variables: +Repository URL, commit SHA and branch are detected automatically, read from the git checkout in `$(Build.SourcesDirectory)`. Nothing to configure: `checkout: self` leaves a full git work tree, and the Docker task example above mounts that directory into the container. + +Two cases still want `sbomify.json`. One is a pipeline whose source is not a git repository - a TFVC repository, or artifacts downloaded rather than checked out. The other is an Azure Repos remote whose URL you would rather record differently. Generate the file from the build variables: ```yaml - script: | @@ -147,7 +148,7 @@ Azure DevOps does not expose repository details in the form the action auto-dete displayName: Write SBOM metadata ``` -Then set `AUGMENT: "true"`. See [augmentation](/sbomify-action/augmentation/). +Then set `AUGMENT: "true"`; `sbomify.json` takes priority over detection. See [augmentation](/sbomify-action/augmentation/). ## Container images @@ -165,8 +166,7 @@ steps: command: run arguments: > -v /var/run/docker.sock:/var/run/docker.sock - -v $(Build.SourcesDirectory):/github/workspace - -w /github/workspace + -v $(Build.SourcesDirectory):/workspace -e DOCKER_IMAGE=my-app:$(Build.BuildId) -e OUTPUT_FILE=container-sbom.cdx.json -e ENRICH=true diff --git a/content/sbomify-action/runtimes/bitbucket.md b/content/sbomify-action/runtimes/bitbucket.md index 3ff8916..d75a57b 100644 --- a/content/sbomify-action/runtimes/bitbucket.md +++ b/content/sbomify-action/runtimes/bitbucket.md @@ -144,6 +144,8 @@ Enable the Docker service: Automatic. Repository URL, commit SHA and branch or tag are read from `BITBUCKET_GIT_HTTP_ORIGIN`, `BITBUCKET_COMMIT`, `BITBUCKET_BRANCH` and `BITBUCKET_TAG`. Nothing to configure. +This is Bitbucket Cloud. **Data Center** exposes a different set of variables, so set `vcs_url` in [`sbomify.json`](/sbomify-action/augmentation/) there - and note that its commit URLs live under `/projects//repos//commits/`, which the action will not guess: you get the repository URL and the SHA without a browsable link. + ## Monorepos ```yaml diff --git a/content/sbomify-action/runtimes/circleci.md b/content/sbomify-action/runtimes/circleci.md index 2786ca1..cf90988 100644 --- a/content/sbomify-action/runtimes/circleci.md +++ b/content/sbomify-action/runtimes/circleci.md @@ -4,10 +4,10 @@ url: /sbomify-action/runtimes/circleci/ aliases: - /guides/sbomify-action/runtimes/circleci/ title: "SBOM Generation in CircleCI" -description: "Run the sbomify action in CircleCI using the container image as a Docker executor, with caching, contexts and manual VCS configuration." +description: "Run the sbomify action in CircleCI using the container image as a Docker executor, with caching, contexts and automatic VCS detection." keywords: ["CircleCI SBOM", "CircleCI CycloneDX", "SBOM pipeline"] section: sbomify-action -tldr: "Use the container image as the Docker executor and run sbomify-action. Set VCS details in sbomify.json, since CircleCI's variables are not auto-detected." +tldr: "Use the container image as the Docker executor and run sbomify-action. Repository details are detected from the git checkout; sbomify.json overrides them." --- CircleCI runs the container image as a Docker executor. @@ -124,7 +124,9 @@ workflows: ## VCS information -CircleCI does not expose repository details in the form the action auto-detects, so set them in `sbomify.json`: +Repository URL, commit SHA and branch are detected automatically, read from the git checkout that `checkout` leaves in the working directory. CircleCI's own variables are not used - the checkout is a better source, and it is there on every job that runs `checkout`. + +Set the fields in `sbomify.json` when you want something other than the remote recorded, or when a job builds from a workspace attachment rather than a git checkout: ```json { @@ -134,7 +136,7 @@ CircleCI does not expose repository details in the form the action auto-detects, } ``` -To fill these from the build, write the file in a step first: +`sbomify.json` wins over detection. To fill it from the build, write the file in a step first: ```yaml - run: diff --git a/content/sbomify-action/runtimes/docker.md b/content/sbomify-action/runtimes/docker.md index 43a9a20..24f52de 100644 --- a/content/sbomify-action/runtimes/docker.md +++ b/content/sbomify-action/runtimes/docker.md @@ -7,7 +7,7 @@ title: "SBOM Generation on Any Container Runner" description: "Run the sbomify action with plain Docker or Podman on any CI platform - Drone, Woodpecker, TeamCity, Buildkite, Concourse - or from a shell script." keywords: ["Docker SBOM", "Podman SBOM", "Drone CI SBOM", "Buildkite SBOM", "TeamCity SBOM"] section: sbomify-action -tldr: "If your platform can run a container, it is supported. Mount your repository at /github/workspace, pass configuration as environment variables, and run the image." +tldr: "If your platform can run a container, it is supported. Mount your repository at /workspace, pass configuration as environment variables, and run the image." --- The container image is the universal integration. Any platform that can run a container can run this, whether or not it has a dedicated page here. @@ -16,8 +16,7 @@ The container image is the universal integration. Any platform that can run a co ```bash docker run --rm \ - -v "$(pwd):/github/workspace" \ - -w /github/workspace \ + -v "$(pwd):/workspace" \ -e LOCK_FILE=requirements.txt \ -e OUTPUT_FILE=sbom.cdx.json \ -e ENRICH=true \ @@ -25,11 +24,10 @@ docker run --rm \ ghcr.io/sbomify/sbomify-action ``` -Three things matter: +Two things matter: -1. **Mount your repository.** `/github/workspace` is the conventional path, but any path works as long as `-w` matches. -2. **Set the working directory** with `-w` so relative lockfile paths resolve. -3. **Pass configuration as environment variables.** The image entrypoint is `sbomify-action`, so no command is needed. +1. **Mount your repository at `/workspace`.** That is the image's working directory, so no `-w` is needed. Any other mount point works as long as `-w` points at it - including an existing `-v "$(pwd):/github/workspace" -w /github/workspace`, which keeps working unchanged. Keep the mount and the `-w` in step: output paths resolve against the working directory, so a mount without a matching `-w` leaves your SBOM inside the container. +2. **Pass configuration as environment variables.** The image entrypoint is `sbomify-action`, so no command is needed. Podman works identically - substitute `podman run`. @@ -37,8 +35,7 @@ Podman works identically - substitute `podman run`. ```bash docker run --rm \ - -v "$(pwd):/github/workspace" \ - -w /github/workspace \ + -v "$(pwd):/workspace" \ -e TOKEN="$SBOMIFY_TOKEN" \ -e COMPONENT_ID=your-component-id \ -e LOCK_FILE=requirements.txt \ @@ -57,9 +54,8 @@ Use a named volume so the license database survives between runs: docker volume create sbomify-cache docker run --rm \ - -v "$(pwd):/github/workspace" \ + -v "$(pwd):/workspace" \ -v sbomify-cache:/cache \ - -w /github/workspace \ -e SBOMIFY_CACHE_DIR=/cache/sbomify \ -e SYFT_CACHE_DIR=/cache/syft \ -e SBOMIFY_TOOL_CACHE=/cache/runtimes \ @@ -80,8 +76,7 @@ Scanning an image needs access to a Docker daemon: ```bash docker run --rm \ -v /var/run/docker.sock:/var/run/docker.sock \ - -v "$(pwd):/github/workspace" \ - -w /github/workspace \ + -v "$(pwd):/workspace" \ -e DOCKER_IMAGE=my-app:latest \ -e OUTPUT_FILE=container-sbom.cdx.json \ -e ENRICH=true \ @@ -134,7 +129,7 @@ steps: plugins: - docker#v5.11.0: image: "ghcr.io/sbomify/sbomify-action" - workdir: /github/workspace + workdir: /workspace environment: - LOCK_FILE=requirements.txt - OUTPUT_FILE=sbom.cdx.json @@ -172,6 +167,14 @@ jobs: **A plain shell script** - the `docker run` invocation at the top of this page works in cron, a Makefile, or a deployment script. +## VCS detection + +Repository URL, commit SHA and branch are detected from the git checkout you mounted, so a plain `docker run` on any CI system records provenance without configuration. It needs the `.git` directory inside the mount - `-v "$(pwd):/workspace"` from a repository root gives you that - and a remote on the repository. + +One thing to know: the action treats a run as CI when the environment sets `CI=true` or a vendor variable it recognises (`JENKINS_URL`, `CIRCLECI`, `TF_BUILD`, `BUILDKITE`, `DRONE`, `TRAVIS`, `APPVEYOR`, `CODEBUILD_BUILD_ID`). Nearly every CI system sets one of those. If yours does not - a cron job or a shell script on a build box, say - pass `-e CI=true`, or `-e SBOMIFY_LOCAL_VCS=true` to get the same detection without claiming to be CI. Otherwise the run counts as local, where reading the checkout is opt-in. + +`sbomify.json` overrides whatever is detected. See [augmentation](/sbomify-action/augmentation/#automatic-vcs-detection). + ## What is in the image The image is deliberately small: Python, the sbomify CLI (which brings `cyclonedx-py` with it), `conan` for C and C++ metadata, and `git`. @@ -188,5 +191,5 @@ The container runs as root, because it needs to write to the mounted workspace. ## Next steps - [Configuration reference](/sbomify-action/configuration/) - every option -- [Augmentation](/sbomify-action/augmentation/) - setting VCS details manually +- [Augmentation](/sbomify-action/augmentation/) - your business metadata, and overriding detected VCS details - [Advanced](/sbomify-action/advanced/) - caching, audit trail, troubleshooting diff --git a/content/sbomify-action/runtimes/github-actions.md b/content/sbomify-action/runtimes/github-actions.md index 6519130..250840e 100644 --- a/content/sbomify-action/runtimes/github-actions.md +++ b/content/sbomify-action/runtimes/github-actions.md @@ -209,8 +209,7 @@ The wizard generates a complete workflow, including SHA pins and matrix entries ```bash docker run --rm -it \ - -v "$(pwd):/github/workspace" \ - -w /github/workspace \ + -v "$(pwd):/workspace" \ ghcr.io/sbomify/sbomify-action \ sbomify-action wizard ``` diff --git a/content/sbomify-action/runtimes/jenkins.md b/content/sbomify-action/runtimes/jenkins.md index 5e48c7f..b8ba914 100644 --- a/content/sbomify-action/runtimes/jenkins.md +++ b/content/sbomify-action/runtimes/jenkins.md @@ -4,10 +4,10 @@ url: /sbomify-action/runtimes/jenkins/ aliases: - /guides/sbomify-action/runtimes/jenkins/ title: "SBOM Generation in Jenkins" -description: "Run the sbomify action in Jenkins declarative and scripted pipelines, with credentials, caching and manual VCS configuration." +description: "Run the sbomify action in Jenkins declarative and scripted pipelines, with credentials, caching and VCS detection from the checkout." keywords: ["Jenkins SBOM", "Jenkins pipeline SBOM", "CycloneDX Jenkins"] section: sbomify-action -tldr: "Use the container image as a pipeline agent. Jenkins does not expose standard VCS environment variables, so set repository details in sbomify.json." +tldr: "Use the container image as a pipeline agent. Repository details are detected from the git checkout in the workspace; sbomify.json overrides them if you need something else recorded." --- Jenkins runs the container image as a pipeline agent. Both declarative and scripted pipelines work. @@ -100,7 +100,11 @@ node { ## VCS information -Jenkins does not expose repository details in a standard enough form to detect reliably - the available variables depend on which SCM plugin and job type you use. Set them explicitly in `sbomify.json`: +Repository URL, commit SHA and branch are detected automatically, read from the git checkout in the workspace. Jenkins exposes no repository variables worth trusting - which ones exist depends on the SCM plugin and the job type - so the action asks `git` directly instead. Nothing to configure. + +Two things have to be true, and a normal `checkout scm` gives you both: the `.git` directory is present in the workspace the container sees, and the repository has a remote (`origin`, or the first one configured). If either is missing, nothing is emitted rather than a partial claim. + +Set the fields in `sbomify.json` when you want something other than the remote recorded - an internal mirror rewritten to its public URL, for example: ```json { @@ -110,7 +114,7 @@ Jenkins does not expose repository details in a standard enough form to detect r } ``` -To populate them from the build, write the file in an earlier stage: +`sbomify.json` wins over detection. To populate it from the build, write the file in an earlier stage: ```groovy stage('Prepare SBOM metadata') { diff --git a/content/sbomify-action/runtimes/local.md b/content/sbomify-action/runtimes/local.md index 977127e..e183347 100644 --- a/content/sbomify-action/runtimes/local.md +++ b/content/sbomify-action/runtimes/local.md @@ -20,8 +20,7 @@ Closest to what CI does, which makes it the best choice for reproducing a pipeli ```bash docker run --rm \ - -v "$(pwd):/github/workspace" \ - -w /github/workspace \ + -v "$(pwd):/workspace" \ -e LOCK_FILE=requirements.txt \ -e OUTPUT_FILE=sbom.cdx.json \ -e ENRICH=true \ @@ -123,7 +122,17 @@ Be deliberate about uploading from a laptop. An SBOM generated locally reflects ## VCS information -Nothing is auto-detected locally. Set the values in `sbomify.json` if you need them: +Nothing is read from your checkout unless you ask for it. On CI, repository URL, commit SHA and ref are detected automatically; locally that is deliberately off, because the same lock file would otherwise produce a different SBOM depending on whether a remote happened to be configured, and an internal remote would be written into a document that often gets shared. + +Opt in when you want it: + +```bash +SBOMIFY_LOCAL_VCS=true uvx sbomify-action --lock-file requirements.txt --enrich +``` + +The values come from the checkout in your working directory: `origin` (or the first remote), `HEAD`, and the current branch or the exact tag when HEAD is detached. + +Or state them yourself in `sbomify.json`, which takes priority either way: ```json { @@ -141,8 +150,7 @@ When CI produces something you did not expect, reproduce it locally with the sam ```bash docker run --rm \ - -v "$(pwd):/github/workspace" \ - -w /github/workspace \ + -v "$(pwd):/workspace" \ -e LOCK_FILE=requirements.txt \ -e OUTPUT_FILE=sbom.cdx.json \ -e ENRICH=true \ @@ -153,7 +161,7 @@ docker run --rm \ `VERBOSE=true` shows which generator ran, which enrichment sources answered, and where time went. Check `audit_trail.txt` afterwards for the full list of changes. -Two differences from CI worth keeping in mind: VCS auto-detection will not fire locally, and enrichment coverage may differ if CI is hitting [GitHub API rate limits](/sbomify-action/enrichment/#license-database-rate-limits) that your machine is not. +Two differences from CI worth keeping in mind: VCS detection is opt-in locally (`SBOMIFY_LOCAL_VCS=true`) where CI does it automatically, and enrichment coverage may differ if CI is hitting [GitHub API rate limits](/sbomify-action/enrichment/#license-database-rate-limits) that your machine is not. ## Next steps diff --git a/content/sbomify-action/runtimes/teamcity.md b/content/sbomify-action/runtimes/teamcity.md index 14c1227..cc93650 100644 --- a/content/sbomify-action/runtimes/teamcity.md +++ b/content/sbomify-action/runtimes/teamcity.md @@ -18,9 +18,7 @@ In the build configuration: 1. Add a **Command Line** build step. 2. Set **Custom script** to `sbomify-action`. -3. Add the **Docker Wrapper** build feature to that step, with: - - **Docker image**: `ghcr.io/sbomify/sbomify-action` - - **Additional docker run arguments**: `-w /github/workspace` +3. Add the **Docker Wrapper** build feature to that step, with **Docker image** set to `ghcr.io/sbomify/sbomify-action`. No extra run arguments are needed: the wrapper mounts the checkout directory and runs the script inside it. 4. Add the configuration as environment variables under **Parameters**, prefixed `env.`: ```text @@ -54,7 +52,6 @@ object GenerateSbom : BuildType({ name = "Generate SBOM" scriptContent = "sbomify-action" dockerImage = "ghcr.io/sbomify/sbomify-action" - dockerRunParameters = "-w /github/workspace" } } @@ -108,7 +105,7 @@ env.GITHUB_TOKEN = %github.token% Mount that directory into the container by adding it to the Docker Wrapper's run arguments: ```text --w /github/workspace -v %system.agent.home.dir%/cache:/cache +-v %system.agent.home.dir%/cache:/cache ``` Two things are worth caching here. The [tool runtimes](/sbomify-action/advanced/#tool-runtimes) are downloaded on first use, so without a cache every build re-fetches them. And `GITHUB_TOKEN` matters even though you are not on GitHub: license databases come from GitHub Releases, unauthenticated requests are capped at 60 per hour per IP, and a pool of agents behind one NAT address exhausts that quickly. When it happens, enrichment degrades silently. See [license database rate limits](/sbomify-action/enrichment/#license-database-rate-limits). @@ -159,7 +156,7 @@ Then set `env.AUGMENT = true`. See [augmentation](/sbomify-action/augmentation/) Scanning an image needs access to a Docker daemon. TeamCity agents that already run Docker builds have one; add the socket to the wrapper's run arguments: ```text --w /github/workspace -v /var/run/docker.sock:/var/run/docker.sock +-v /var/run/docker.sock:/var/run/docker.sock ``` ```text