Repository: GoogleContainerTools/distroless Branch: main Commit: bab6ba66e024 Files: 204 Total size: 402.4 KB Directory structure: gitextract_vcjsnv1p/ ├── .bazelignore ├── .bazelrc ├── .bazelversion ├── .cloudbuild/ │ ├── cloudbuild.yaml │ ├── lifecycle_tag.sh │ ├── lifecycle_tag.yaml │ └── release.sh ├── .github/ │ ├── ISSUE_TEMPLATE/ │ │ ├── actionable-debian-cve.md │ │ ├── actionable-non-debian-cve.md │ │ └── bug_report.md │ ├── dependabot.yml │ └── workflows/ │ ├── buildifier.yaml │ ├── check-ldconfig.yaml │ ├── ci.bazelrc │ ├── ci.yaml │ ├── config-diff.yaml │ ├── examples.yaml │ ├── image-check.yaml │ ├── scorecards-analysis.yml │ ├── update-deb-package-non-snapshots.yml │ ├── update-deb-package-snapshots.yml │ └── update-node-archives.yml ├── .gitignore ├── .pre-commit-config.yaml ├── .prettierignore ├── BUILD ├── CONTRIBUTING.md ├── LICENSE ├── MODULE.bazel ├── PACKAGE_METADATA.md ├── README.md ├── RELEASES.md ├── SECURITY.md ├── SUPPORT_POLICY.md ├── WORKSPACE ├── base/ │ ├── BUILD │ ├── README.md │ ├── base.bzl │ ├── config.bzl │ ├── test.sh │ └── testdata/ │ ├── base.yaml │ └── debug.yaml ├── cc/ │ ├── BUILD │ ├── README.md │ ├── cc.bzl │ └── config.bzl ├── common/ │ ├── BUILD.bazel │ └── variables.bzl ├── cosign.pub ├── distro.bzl ├── downloader.cfg ├── examples/ │ ├── BUILD │ ├── cc/ │ │ ├── BUILD │ │ ├── Dockerfile │ │ ├── hello.c │ │ ├── hello_cc.cc │ │ └── testdata/ │ │ ├── hello_cc_debian12.yaml │ │ ├── hello_cc_debian13.yaml │ │ ├── hello_debian12.yaml │ │ └── hello_debian13.yaml │ ├── go/ │ │ ├── BUILD │ │ ├── Dockerfile │ │ ├── go.mod │ │ ├── main.go │ │ └── main_test.go │ ├── java/ │ │ ├── BUILD │ │ ├── Dockerfile │ │ ├── HelloJava.java │ │ └── testdata/ │ │ ├── hello_nonroot_debian13.yaml │ │ └── hello_root_debian13.yaml │ ├── nodejs/ │ │ ├── BUILD │ │ ├── Dockerfile │ │ ├── hello.js │ │ ├── hello_http.js │ │ ├── node-express/ │ │ │ ├── Dockerfile │ │ │ ├── hello_express.js │ │ │ └── package.json │ │ ├── package.json │ │ └── testdata/ │ │ └── hello.yaml │ ├── nonroot/ │ │ ├── BUILD │ │ └── testdata/ │ │ ├── user.go │ │ └── user.yaml │ ├── python3/ │ │ ├── BUILD │ │ ├── Dockerfile │ │ └── hello.py │ ├── python3-requirements/ │ │ ├── Dockerfile │ │ ├── README.md │ │ ├── psutil_example.py │ │ └── requirements.txt │ ├── rust/ │ │ ├── .dockerignore │ │ ├── BUILD │ │ ├── Cargo.toml │ │ ├── Dockerfile │ │ └── src/ │ │ └── main.rs │ └── test.sh ├── experimental/ │ ├── BUILD │ └── busybox/ │ ├── BUILD │ └── commands.bzl ├── java/ │ ├── BUILD │ ├── README.md │ ├── config.bzl │ ├── control │ ├── java.bzl │ ├── jre_ver.bzl │ └── testdata/ │ ├── CheckCerts.java │ ├── CheckEncoding.java │ ├── CheckLibharfbuzz.java │ ├── java17_debian13.yaml │ ├── java17_debug_debian13.yaml │ ├── java21_debian13.yaml │ ├── java21_debug_debian13.yaml │ ├── java25_debian13.yaml │ ├── java25_debug_debian13.yaml │ ├── java_base.yaml │ ├── java_base_debug.yaml │ ├── java_certs.yaml │ ├── java_encoding.yaml │ └── java_libharfbuzz.yaml ├── knife ├── knife.d/ │ ├── update_java_versions.sh │ └── update_node_archives.js ├── nodejs/ │ ├── BUILD │ ├── README.md │ ├── config.bzl │ ├── control │ ├── nodejs.bzl │ └── testdata/ │ ├── check_certificate.js │ ├── check_certificate.yaml │ ├── check_headers.yaml │ ├── check_npm.yaml │ ├── nodejs20.yaml │ ├── nodejs22.yaml │ └── nodejs24.yaml ├── private/ │ ├── extensions/ │ │ ├── BUILD.bazel │ │ ├── busybox.bzl │ │ ├── node.bzl │ │ └── version.bzl │ ├── oci/ │ │ ├── BUILD.bazel │ │ ├── cc_image.bzl │ │ ├── defs.bzl │ │ ├── digest.bzl │ │ ├── go_image.bzl │ │ ├── java_image.bzl │ │ ├── rust_image.bzl │ │ ├── sign_and_push.bzl │ │ └── sign_and_push.sh.tpl │ ├── pkg/ │ │ ├── BUILD.bazel │ │ ├── debian_spdx.bzl │ │ ├── debian_spdx.go │ │ ├── oci_image_spdx.bzl │ │ ├── oci_image_spdx.go │ │ └── test/ │ │ └── oci_image/ │ │ ├── BUILD.bazel │ │ ├── fat_image_sbom.spdx.json │ │ ├── image_amd64.spdx.json │ │ └── image_arm64.spdx.json │ ├── repos/ │ │ └── deb/ │ │ ├── BUILD.bazel │ │ ├── bookworm.lock.json │ │ ├── bookworm.yaml │ │ ├── bookworm_python.lock.json │ │ ├── bookworm_python.yaml │ │ ├── deb.MODULE.bazel │ │ ├── package.BUILD.tmpl │ │ ├── trixie.lock.json │ │ ├── trixie.yaml │ │ ├── trixie_adoptium.lock.json │ │ ├── trixie_adoptium.yaml │ │ ├── trixie_java.lock.json │ │ ├── trixie_java.yaml │ │ ├── trixie_python.lock.json │ │ └── trixie_python.yaml │ ├── stamp.bash │ ├── tools/ │ │ ├── diff/ │ │ │ ├── BUILD.bazel │ │ │ └── diff.bash │ │ └── lifecycle/ │ │ ├── BUILD.bazel │ │ ├── defs.bzl │ │ ├── tag.bzl │ │ ├── tag.sh │ │ └── tag.sh.README.md │ └── util/ │ ├── BUILD │ ├── deb.bzl │ ├── extract.bzl │ ├── java_cacerts.bzl │ ├── merge_providers.bzl │ └── tar.bzl ├── python3/ │ ├── BUILD │ ├── README.md │ ├── config.bzl │ ├── ldconfig/ │ │ ├── ld.so.cache.amd64 │ │ ├── ld.so.cache.arm64 │ │ └── ldconfig.sh │ ├── ldconfig.bzl │ ├── python.bzl │ └── testdata/ │ ├── debian12.yaml │ ├── debian13.yaml │ └── python3.yaml └── static/ ├── BUILD ├── config.bzl ├── nsswitch.conf ├── static.bzl └── testdata/ ├── check_certs.go ├── debian12.yaml ├── debian13.yaml ├── debug.yaml └── static.yaml ================================================ FILE CONTENTS ================================================ ================================================ FILE: .bazelignore ================================================ ================================================ FILE: .bazelrc ================================================ # Bazel settings that apply to this repository. # Take care to document any settings that you expect users to apply. # Settings that apply only to CI are in .github/workflows/ci.bazelrc # Allow DOCKER_HOST env to leak into test actions. test --test_env=DOCKER_HOST # Stamp build:release --workspace_status_command=./private/stamp.bash --stamp run:release --workspace_status_command=./private/stamp.bash --stamp test:release --workspace_status_command=./private/stamp.bash --stamp # Allow external dependencies to be retried. debian snapshot is unreliable and needs retries. common --experimental_repository_downloader_retries=20 common --experimental_downloader_config=downloader.cfg common --http_timeout_scaling=2.0 # Enable platform specific options build --enable_platform_specific_config # Use a hermetic Java version build --java_runtime_version=remotejdk_11 # Newer versions jdk creates collisions on /tmp # See: https://github.com/bazelbuild/bazel/issues/3236 # https://github.com/GoogleContainerTools/rules_distroless/actions/runs/7118944984/job/19382981899?pr=9#step:8:51 common:linux --sandbox_tmpfs_path=/tmp # Load any settings specific to the current user. # .bazelrc.user should appear in .gitignore so that settings are not shared with team members # This needs to be last statement in this # config, as the user configuration should be able to overwrite flags from this file. # See https://docs.bazel.build/versions/master/best-practices.html#bazelrc # (Note that we use .bazelrc.user so the file appears next to .bazelrc in directory listing, # rather than user.bazelrc as suggested in the Bazel docs) try-import %workspace%/.bazelrc.user ================================================ FILE: .bazelversion ================================================ 7.4.0 ================================================ FILE: .cloudbuild/cloudbuild.yaml ================================================ timeout: 10800s # 3 hours options: machineType: E2_HIGHCPU_32 logging: CLOUD_LOGGING_ONLY artifacts: objects: location: 'gs://${_ARTIFACTS_GCS_}/logs' paths: ['.logs/*.log'] steps: - name: gcr.io/cloud-builders/bazel@sha256:70e96d9faec4bab40a9d8d55d6b86ce2657927d8bca6bdc2dcb21a82b66dbdf7 # 5.4.0 env: - PROJECT_ID=${PROJECT_ID} - COMMIT_SHA=${COMMIT_SHA} - REGISTRY=gcr.io - REMOTE_CACHE_GCS=${_REMOTE_CACHE_GCS_} - KEYLESS=keyless@${PROJECT_ID}.iam.gserviceaccount.com entrypoint: bash args: [".cloudbuild/release.sh"] ================================================ FILE: .cloudbuild/lifecycle_tag.sh ================================================ #!/usr/bin/env bash set -o errexit -o nounset -o xtrace -o pipefail BAZELISK_VERSION="1.27.0" BAZELISK_SHA256="e1508323f347ad1465a887bc5d2bfb91cffc232d11e8e997b623227c6b32fb76" GGCR_VERSION="0.20.7" GGCR_SHA256="8ef3564d264e6b5ca93f7b7f5652704c4dd29d33935aff6947dd5adefd05953e" # install gcrane curl -fsSL "https://github.com/google/go-containerregistry/releases/download/v${GGCR_VERSION}/go-containerregistry_Linux_x86_64.tar.gz" -o ggcr.tar.gz echo "${GGCR_SHA256} ggcr.tar.gz" | sha256sum --check tar -xzf ggcr.tar.gz gcrane chmod a+x gcrane mv gcrane /usr/bin/gcrane # needs to be on path # we need jq too apt-get update apt-get -y install jq # install bazelisk (TODO: there's probably a better way to do this) curl -fsSL "https://github.com/bazelbuild/bazelisk/releases/download/v${BAZELISK_VERSION}/bazelisk-linux-amd64" -o bazelisk echo "${BAZELISK_SHA256} bazelisk" | sha256sum --check chmod a+x bazelisk echo "common --google_default_credentials" >> ~/.bazelrc echo "common --announce_rc" >> ~/.bazelrc ./bazelisk run :attach_lifecycle_tags --config=release ================================================ FILE: .cloudbuild/lifecycle_tag.yaml ================================================ timeout: 1800s # 30 minutes options: machineType: E2_MEDIUM logging: CLOUD_LOGGING_ONLY steps: - name: gcr.io/cloud-builders/bazel@sha256:70e96d9faec4bab40a9d8d55d6b86ce2657927d8bca6bdc2dcb21a82b66dbdf7 # 5.4.0 env: - PROJECT_ID=${PROJECT_ID} - REGISTRY=gcr.io entrypoint: bash args: [".cloudbuild/lifecycle_tag.sh"] ================================================ FILE: .cloudbuild/release.sh ================================================ #!/usr/bin/env bash set -o errexit -o xtrace -o pipefail BAZEL_REMOTE_VERSION="2.6.1" BAZEL_REMOTE_SHA256="025d53aeb03a7fdd4a0e76262a5ae9eeee9f64d53ca510deff1c84cf3f276784" BAZELISK_VERSION="1.27.0" BAZELISK_SHA256="e1508323f347ad1465a887bc5d2bfb91cffc232d11e8e997b623227c6b32fb76" # setup remote cache curl -fsSL "https://github.com/buchgr/bazel-remote/releases/download/v${BAZEL_REMOTE_VERSION}/bazel-remote-${BAZEL_REMOTE_VERSION}-linux-amd64" -o bazel-remote echo "${BAZEL_REMOTE_SHA256} bazel-remote" | sha256sum --check chmod +x bazel-remote mkdir .logs ./bazel-remote --max_size 8 --dir ~/.cache/bazel-remote --experimental_remote_asset_api --grpc_address 0.0.0.0:4700 --gcs_proxy.bucket $REMOTE_CACHE_GCS --gcs_proxy.use_default_credentials > .logs/bazel-remote.log 2>&1 & # install bazelisk (TODO: there's probably a better way to do this) curl -fsSL "https://github.com/bazelbuild/bazelisk/releases/download/v${BAZELISK_VERSION}/bazelisk-linux-amd64" -o bazelisk echo "${BAZELISK_SHA256} bazelisk" | sha256sum --check chmod a+x bazelisk # setup remote caching and remote asset API. echo "common --remote_cache=grpc://0.0.0.0:4700" >> ~/.bazelrc echo "common --experimental_remote_downloader=grpc://0.0.0.0:4700" >> ~/.bazelrc echo "common --google_default_credentials" >> ~/.bazelrc echo "common --announce_rc" >> ~/.bazelrc for i in $(seq 5); do ./bazelisk cquery 'kind(merge_providers, deps(kind(oci_image, ...)))' --output=label --config=release && break || sleep 20; done ./bazelisk run :sign_and_push --config=release -- --keyless $KEYLESS ================================================ FILE: .github/ISSUE_TEMPLATE/actionable-debian-cve.md ================================================ --- name: Actionable debian CVE about: A CVE from a debian package where a fix is available title: '' labels: '' assignees: '' --- - [ ] I have read the [SECURITY.md](https://github.com/GoogleContainerTools/distroless/blob/main/SECURITY.md) - [ ] I understand that this repo tracks debian package releases and cannot fix debian CVEs on its own - [ ] this CVE shows a fix is available in the appropriate debian version (bookworm) and channel (main, security) *and* it has been more than 48 hours. Please describe the image you encountered this with and a link to the debian security tracker https://security-tracker.debian.org/tracker/CVE-XXXX-YYYYY ================================================ FILE: .github/ISSUE_TEMPLATE/actionable-non-debian-cve.md ================================================ --- name: Actionable non debian CVE about: A CVE is an package imported into distroless that is not from debian title: '' labels: '' assignees: '' --- **CVE disclosure** A link to a public CVE disclosure **Name of image** The distroless image you are using **Link to updated package** A link to an available update for this package ================================================ FILE: .github/ISSUE_TEMPLATE/bug_report.md ================================================ --- name: Bug report about: There is an issue with how distroless is built title: '' labels: '' assignees: '' --- **Describe the bug** A clear and concise description of what the bug is. **To Reproduce** Steps to reproduce the behavior: **Expected behavior** A clear and concise description of what you expected to happen. **Console Output** If applicable, add information from your container run **Additional context** Add any other context about the problem here. ================================================ FILE: .github/dependabot.yml ================================================ version: 2 updates: - package-ecosystem: "gomod" directory: "/" schedule: interval: "daily" - package-ecosystem: "gomod" directory: "debian-package-manager/" schedule: interval: "daily" - package-ecosystem: "github-actions" directory: "/" schedule: interval: "daily" ================================================ FILE: .github/workflows/buildifier.yaml ================================================ name: Buildifier on: pull_request: branches: ["main"] permissions: contents: read jobs: autoformat: name: Auto-format and Check runs-on: ubuntu-latest steps: - name: Set up Go uses: actions/setup-go@v6 with: go-version: "1.25" - name: Check out code uses: actions/checkout@v6 - name: Install Dependencies run: | go install github.com/bazelbuild/buildtools/buildifier@3.2.0 - name: Run buildifier run: | ./knife lint --check ================================================ FILE: .github/workflows/check-ldconfig.yaml ================================================ name: Check ldconfig cache on: pull_request: branches: ["main"] push: branches: ["main"] permissions: contents: read jobs: check-ldconfig: name: Check ldconfig cache up to date runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v6 - name: Set up QEMU uses: docker/setup-qemu-action@v4 - name: Check ldconfig caches run: bazel test //python3:check_ldconfig_tests ================================================ FILE: .github/workflows/ci.bazelrc ================================================ build --announce_rc build --repository_cache=~/.cache/bazel-repo # intentionally disable build cache, it gets too big # build --disk_cache=~/.cache/bazel common --curses=no test --test_output=errors ================================================ FILE: .github/workflows/ci.yaml ================================================ name: CI on: workflow_dispatch: # Allow manual runs. pull_request: branches: ["main"] push: branches: ["main"] permissions: contents: read jobs: lockfile: name: Check lockfile up to date runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - name: Check lockfile run: bazel mod deps --lockfile_mode=error ci-build-test: name: CI build and unit test runs-on: distroless-ci-large-ubuntu-22.04 steps: - uses: actions/checkout@v6 - name: Mount bazel caches uses: actions/cache@v4 with: path: | ~/.cache/bazel-repo key: bazel-cache-deps-ci1-${{ github.sha }} restore-keys: | bazel-cache-deps-ci1-${{ github.sha }} bazel-cache-deps-ci1- - name: Fetch # this can take a long time if there are a lot of errors run: | for i in $(seq 10); do bazel --bazelrc=$GITHUB_WORKSPACE/.github/workflows/ci.bazelrc fetch //... && break || sleep 180; done - name: Build All Images run: | set -e targets=$(bazel query 'kind(oci_image, deps(:sign_and_push))') bazel --bazelrc=$GITHUB_WORKSPACE/.github/workflows/ci.bazelrc build $targets - name: Unit Tests run: bazel --bazelrc=$GITHUB_WORKSPACE/.github/workflows/ci.bazelrc test //... --build_tests_only - name: Build Examples run: bazel --bazelrc=$GITHUB_WORKSPACE/.github/workflows/ci.bazelrc build //examples/... ci-images: name: CI image tests runs-on: distroless-ci-large-ubuntu-22.04 steps: - uses: actions/checkout@v6 - name: Mount bazel caches uses: actions/cache@v4 with: path: | ~/.cache/bazel-repo key: bazel-cache-deps-ci2-${{ github.sha }} restore-keys: | bazel-cache-deps-ci2-${{ github.sha }} bazel-cache-deps-ci2- - name: Fetch run: | for i in $(seq 20); do bazel --bazelrc=$GITHUB_WORKSPACE/.github/workflows/ci.bazelrc cquery 'attr(tags, "amd64", ...)' && break sleep 10; done - name: Image Tests run: bazel --bazelrc=$GITHUB_WORKSPACE/.github/workflows/ci.bazelrc test $(bazel query 'attr(tags, "amd64", ...)') ================================================ FILE: .github/workflows/config-diff.yaml ================================================ name: Config Check on: workflow_dispatch: pull_request: branches: ["main"] concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true permissions: pull-requests: write jobs: diff: runs-on: ubuntu-latest steps: - name: Checkout PR Branch uses: actions/checkout@v6 with: ref: ${{ github.event.pull_request.head.sha }} path: pr_branch - name: Build :sign_and_push.query for PR run: | cd pr_branch bazel build :sign_and_push.query cp bazel-bin/sign_and_push_query ../pr_query_output.txt cd .. - name: Checkout main Branch uses: actions/checkout@v6 with: ref: main path: main_branch - name: Build :sign_and_push.query for main run: | cd main_branch bazel build :sign_and_push.query cp bazel-bin/sign_and_push_query ../main_query_output.txt cd .. - name: Diff the query outputs id: diff run: | # diff may exit with non-zero DIFF_OUTPUT=$(diff -u <(sort main_query_output.txt) <(sort pr_query_output.txt)) || true if [ "$DIFF_OUTPUT" ]; then echo "$DIFF_OUTPUT" echo "changed_build<> $GITHUB_OUTPUT echo "$DIFF_OUTPUT" >> $GITHUB_OUTPUT echo "EOF" >> $GITHUB_OUTPUT fi - uses: peter-evans/find-comment@v4 id: fc if: ${{ !github.event.pull_request.head.repo.fork }} with: issue-number: ${{ github.event.pull_request.number }} comment-author: "github-actions[bot]" body-includes: 🌳 🔧 Config Check - name: Report diff if: ${{ !github.event.pull_request.head.repo.fork && steps.diff.outputs.changed_build }} uses: peter-evans/create-or-update-comment@v5 with: comment-id: ${{ steps.fc.outputs.comment-id }} issue-number: ${{ github.event.pull_request.number }} body: | 🌳 🔧 Config Check This pull request has modified the root BUILD ```diff ${{steps.diff.outputs.changed_build}} ``` edit-mode: replace - name: Report no diff if: ${{ !github.event.pull_request.head.repo.fork && !steps.diff.outputs.changed_build }} uses: peter-evans/create-or-update-comment@v5 with: comment-id: ${{ steps.fc.outputs.comment-id }} issue-number: ${{ github.event.pull_request.number }} body: | 🌳 🔧 Config Check This pull request has not modified the root BUILD edit-mode: replace ================================================ FILE: .github/workflows/examples.yaml ================================================ name: Examples on: pull_request: branches: [ 'main' ] permissions: contents: read jobs: examples: name: Build and run examples runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - run: ./examples/test.sh ================================================ FILE: .github/workflows/image-check.yaml ================================================ name: Image Check on: workflow_dispatch: pull_request: branches: ["main"] concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true permissions: pull-requests: write jobs: diff: runs-on: distroless-ci-large-ubuntu-22.04 steps: - uses: actions/checkout@v6 - name: Set up Go uses: actions/setup-go@v6 with: go-version: "1.25" - uses: actions/cache@v4 with: path: | ~/.cache/bazel-repo key: bazel-cache-deps-ci2-${{ github.sha }} restore-keys: | bazel-cache-deps-ci2-${{ github.sha }} bazel-cache-deps-ci2- - name: Fetch run: | for i in $(seq 10); do bazel --bazelrc=$GITHUB_WORKSPACE/.github/workflows/ci.bazelrc cquery 'attr(tags, "amd64", ...)' && break sleep 10; done - name: Build all images run: bazel build //:sign_and_push - name: Install Deps run: | go install github.com/google/go-containerregistry/cmd/crane@main go install github.com/reproducible-containers/diffoci/cmd/diffoci@master go install filippo.io/mkcert@master sudo curl -fsSL "https://github.com/project-zot/zot/releases/download/v2.0.2-rc2/zot-linux-amd64-minimal" > /usr/local/bin/zot sudo chmod +x /usr/local/bin/zot - name: Diff All Images id: diff env: HEAD_REF: ${{ github.head_ref }} BASE_REF: ${{ github.event.pull_request.base.ref }} run: | ./private/tools/diff/diff.bash \ --query-bazel --registry-spawn-https \ --head-ref "$HEAD_REF" \ --base-ref "$BASE_REF" \ --set-github-output-on-diff \ --skip-image-index \ --jobs $(($(nproc --all) * 2)) \ --logs ./verbose.log \ --report ./report.log - uses: actions/upload-artifact@v7.0.0 id: report with: name: "Report" path: | ./verbose.log ./report.log - name: Write diff to job output for forks if: ${{ github.event.pull_request.head.repo.fork && steps.diff.outputs.changed_targets }} env: CHANGED: ${{ steps.diff.outputs.changed_targets }} run: | echo "This pull request has modified the following images:" echo "$CHANGED" - uses: peter-evans/find-comment@v4 id: fc if: ${{ !github.event.pull_request.head.repo.fork }} with: issue-number: ${{ github.event.pull_request.number }} comment-author: "github-actions[bot]" body-includes: 🌳 🔄 Image Check - name: Report diff if: ${{ !github.event.pull_request.head.repo.fork && steps.diff.outputs.changed_targets }} uses: peter-evans/create-or-update-comment@v5 with: comment-id: ${{ steps.fc.outputs.comment-id }} issue-number: ${{ github.event.pull_request.number }} body: | 🌳 🔄 Image Check This pull request has modified the following images: ```starlark ${{steps.diff.outputs.changed_targets}} ``` You can check the details in the report [here](${{steps.report.outputs.artifact-url}}) edit-mode: replace - name: Report no diff if: ${{ !github.event.pull_request.head.repo.fork && !steps.diff.outputs.changed_targets }} uses: peter-evans/create-or-update-comment@v5 with: comment-id: ${{ steps.fc.outputs.comment-id }} issue-number: ${{ github.event.pull_request.number }} body: | 🌳 🔄 Image Check This pull request doesn't make any changes to the images. 👍 You can check the details in the report [here](${{steps.report.outputs.artifact-url}}) edit-mode: replace ================================================ FILE: .github/workflows/scorecards-analysis.yml ================================================ name: Scorecards supply-chain security on: # Only the default branch is supported. branch_protection_rule: schedule: - cron: '38 10 * * 1' push: branches: [ main ] # Declare default permissions as read only. permissions: read-all jobs: analysis: name: Scorecards analysis runs-on: ubuntu-latest permissions: # Needed to upload the results to code-scanning dashboard. security-events: write id-token: write steps: - name: "Checkout code" uses: actions/checkout@v6 with: persist-credentials: false - name: "Run analysis" uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3 with: results_file: results.sarif results_format: sarif # Read-only PAT token. repo_token: ${{ secrets.SCORECARD_TOKEN }} # Publish the results to enable scorecard badges. For more details, see # https://github.com/ossf/scorecard-action#publishing-results. publish_results: true # Upload the results as artifacts (optional). - name: "Upload artifact" uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: SARIF file path: results.sarif retention-days: 5 # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" uses: github/codeql-action/upload-sarif@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6 with: sarif_file: results.sarif ================================================ FILE: .github/workflows/update-deb-package-non-snapshots.yml ================================================ name: update-non-snapshots on: # will send emails to last editor of this cron syntax (distroless-bot) schedule: - cron: "35 20 * * *" # allow this workflow to be manually run workflow_dispatch: permissions: contents: read jobs: build: runs-on: ubuntu-latest permissions: contents: write pull-requests: write steps: - uses: actions/checkout@v6 - name: Update non-snapshots run: ./knife update-non-snapshots - name: Check for changes run: | git status if [[ $(git status --porcelain) ]]; then echo "DISTROLESS_DIFF=true" >> "$GITHUB_ENV" else echo "No changes detected" exit 0 fi - name: Run update lockfile if: env.DISTROLESS_DIFF run: bazel mod deps --lockfile_mode=update - name: Create commits if: env.DISTROLESS_DIFF id: create-commits run: | git checkout -b update-non-snapshots # Set identity. git config --global user.email "distroless-bot@google.com" git config --global user.name "Distroless Bot" # Commit changes git add . git commit -s -m "Bumping non-snapshot packages to latest stable versions" git push --force origin HEAD - name: Create Pull Request if: env.DISTROLESS_DIFF env: GH_TOKEN: ${{ secrets.ACTIONS_TOKEN }} run: | BODY_FILE=$(mktemp) printf "Bumping non-snapshot packages to latest stable version\n" >> $BODY_FILE if ! OUTPUT=$(gh pr create -B main -H update-non-snapshots -t "Bumping non-snapshot packages to latest stable versions" --body-file "$BODY_FILE" 2>&1) ; then echo $OUTPUT if [[ "${OUTPUT}" =~ "already exists" ]]; then echo "PR already exists and it was updated. Ending successfully"; exit 0; else exit 1; fi fi ================================================ FILE: .github/workflows/update-deb-package-snapshots.yml ================================================ name: update-snapshots on: # will send emails to last editor of this cron syntax (distroless-bot) schedule: - cron: "35 20 * * *" # allow this workflow to be manually run workflow_dispatch: permissions: contents: read jobs: build: runs-on: ubuntu-latest permissions: contents: write pull-requests: write steps: - uses: actions/checkout@v6 - uses: actions/setup-go@v6 with: go-version: "1.25" - name: Update snapshots run: ./knife github-update-snapshots - name: Set up QEMU if: env.DISTROLESS_DIFF uses: docker/setup-qemu-action@v4 - name: Update ldconfig if: env.DISTROLESS_DIFF run: bazel run //python3:update_ldconfig - name: Run update sboms script if: env.DISTROLESS_DIFF run: | for i in $(seq 5); do bazel --bazelrc=$GITHUB_WORKSPACE/.github/workflows/ci.bazelrc fetch //private/pkg/test/oci_image:test_sboms && break || sleep 20; done bazel run @//private/pkg/test/oci_image:test_sboms - name: Run update lockfile if: env.DISTROLESS_DIFF run: bazel mod deps --lockfile_mode=update - name: Create commits if: env.DISTROLESS_DIFF id: create-commits run: | git checkout -b update-snapshots # Set identity. git config --global user.email "distroless-bot@google.com" git config --global user.name "Distroless Bot" # Commit changes git add . git commit -s -m "Bumping packages to latest stable versions" git push --force origin HEAD - name: Create Pull Request if: env.DISTROLESS_DIFF env: GH_TOKEN: ${{ secrets.ACTIONS_TOKEN }} run: | BODY_FILE=$(mktemp) printf "Bumping packages to latest stable version\n\`\`\`diff\n$DISTROLESS_DIFF\n\`\`\`\n" >> $BODY_FILE if ! OUTPUT=$(gh pr create -B main -H update-snapshots -t "Bumping packages to latest stable versions" --body-file "$BODY_FILE" 2>&1) ; then echo $OUTPUT if [[ "${OUTPUT}" =~ "already exists" ]]; then echo "PR already exists and it was updated. Ending successfully"; exit 0; else exit 1; fi fi ================================================ FILE: .github/workflows/update-node-archives.yml ================================================ name: update-node-packages on: # will send emails to last editor of this cron syntax (distroless-bot) schedule: - cron: "30 20 * * *" # allow this workflow to be manually run workflow_dispatch: permissions: contents: read jobs: build: runs-on: ubuntu-latest permissions: contents: write pull-requests: write steps: - uses: actions/checkout@v6 - uses: actions/setup-node@v6 - name: Update node archives run: ./knife update-node-archives - name: Check for changes run: | git status if [[ $(git status --porcelain) ]]; then echo "DISTROLESS_DIFF=true" >> "$GITHUB_ENV" else echo "No changes detected" exit 0 fi - name: Run update lockfile if: env.DISTROLESS_DIFF run: bazel mod deps --lockfile_mode=update - name: Create commits if: env.DISTROLESS_DIFF run: | git checkout -b update-node-archives # Set identity. git config --global user.email "distroless-bot@google.com" git config --global user.name "Distroless Bot" # Commit changes git add . git commit -s -m "Bumping node archives to latest stable versions" git push --force origin HEAD - name: Create Pull Request if: env.DISTROLESS_DIFF env: GH_TOKEN: ${{ secrets.ACTIONS_TOKEN }} run: | BODY_FILE=$(mktemp) if ! OUTPUT=$(gh pr create -B main -H update-node-archives --fill 2>&1) ; then echo $OUTPUT if [[ "${OUTPUT}" =~ "already exists" ]]; then echo "PR already exists and it was updated. Ending successfully"; exit 0; else exit 1; fi fi ================================================ FILE: .gitignore ================================================ # Ignore backup files. *~ # Ignore Vim swap files. .*.swp # Ignore files generated by IDEs. /.classpath /.factorypath .idea/ *.iml /.project /.settings /bazel.iml # Ignore all bazel-* symlinks. There is no full list since this can change # based on the name of the directory bazel is cloned into. /bazel-* # Ignore outputs generated during Bazel bootstrapping. /output/ # ignore user bazelrc .bazelrc.user *.log ================================================ FILE: .pre-commit-config.yaml ================================================ # See CONTRIBUTING.md for instructions. # See https://pre-commit.com for more information # See https://pre-commit.com/hooks.html for more hooks # Commitizen runs in commit-msg stage # but we don't want to run the other hooks on commit messages default_stages: [commit] # Use a slightly older version of node by default # as the default uses a very new version of GLIBC default_language_version: node: 16.18.0 repos: # Check formatting and lint for starlark code - repo: https://github.com/keith/pre-commit-buildifier rev: 6.1.0.1 hooks: - id: buildifier - id: buildifier-lint # Enforce that commit messages allow for later changelog generation - repo: https://github.com/commitizen-tools/commitizen rev: v2.18.0 hooks: # Requires that commitizen is already installed - id: commitizen stages: [commit-msg] - repo: https://github.com/pre-commit/mirrors-prettier rev: "v2.4.0" hooks: - id: prettier ================================================ FILE: .prettierignore ================================================ private/pkg/test/oci_image/* ================================================ FILE: BUILD ================================================ load("//base:config.bzl", "BASE_ARCHITECTURES", "BASE_DISTROS") load("//cc:config.bzl", "CC_ARCHITECTURES", "CC_DISTROS") load("//java:config.bzl", "JAVA_ARCHITECTURES", "JAVA_DISTROS", "JAVA_MAJOR_VERSIONS") load("//nodejs:config.bzl", "NODEJS_ARCHITECTURES", "NODEJS_DISTROS", "NODEJS_MAJOR_VERSIONS") load("//private/oci:defs.bzl", "sign_and_push_all") load("//private/tools/lifecycle:defs.bzl", "attach_lifecycle_tags") load("//python3:config.bzl", "PYTHON_ARCHITECTURES", "PYTHON_DISTROS") load("//static:config.bzl", "STATIC_ARCHITECTURES", "STATIC_DISTROS") package(default_visibility = ["//visibility:public"]) DEFAULT_DISTRO = "debian13" VARIANTS = [ ("latest", "", "root"), ("nonroot", "", "nonroot"), ("debug", "_debug", "root"), ("debug-nonroot", "_debug", "nonroot"), ] ############### # STATIC # ############### STATIC = { "{REGISTRY}/{PROJECT_ID}/static:" + tag_base + "-" + arch: "//static:static" + debug_mode + "_" + user + "_" + arch + "_" + DEFAULT_DISTRO for arch in STATIC_ARCHITECTURES[DEFAULT_DISTRO] for (tag_base, debug_mode, user) in VARIANTS } # oci_image_index STATIC |= { "{REGISTRY}/{PROJECT_ID}/static:" + tag_base: "//static:static" + debug_mode + "_" + user + "_" + DEFAULT_DISTRO for (tag_base, debug_mode, user) in VARIANTS } STATIC |= { "{REGISTRY}/{PROJECT_ID}/static-" + distro + ":" + tag_base + "-" + arch: "//static:static" + debug_mode + "_" + user + "_" + arch + "_" + distro for (tag_base, debug_mode, user) in VARIANTS for distro in STATIC_DISTROS for arch in STATIC_ARCHITECTURES[distro] } # oci_image_index STATIC |= { "{REGISTRY}/{PROJECT_ID}/static-" + distro + ":" + tag_base: "//static:static" + debug_mode + "_" + user + "_" + distro for (tag_base, debug_mode, user) in VARIANTS for distro in STATIC_DISTROS } ############### # BASE # ############### BASE = { "{REGISTRY}/{PROJECT_ID}/base:" + tag_base + "-" + arch: "//base:base" + debug_mode + "_" + user + "_" + arch + "_" + DEFAULT_DISTRO for arch in BASE_ARCHITECTURES[DEFAULT_DISTRO] for (tag_base, debug_mode, user) in VARIANTS } # oci_image_index BASE |= { "{REGISTRY}/{PROJECT_ID}/base:" + tag_base: "//base:base" + debug_mode + "_" + user + "_" + DEFAULT_DISTRO for (tag_base, debug_mode, user) in VARIANTS } BASE |= { "{REGISTRY}/{PROJECT_ID}/base-" + distro + ":" + tag_base + "-" + arch: "//base:base" + debug_mode + "_" + user + "_" + arch + "_" + distro for distro in BASE_DISTROS for arch in BASE_ARCHITECTURES[distro] for (tag_base, debug_mode, user) in VARIANTS } # oci_image_index BASE |= { "{REGISTRY}/{PROJECT_ID}/base-" + distro + ":" + tag_base: "//base:base" + debug_mode + "_" + user + "_" + distro for (tag_base, debug_mode, user) in VARIANTS for distro in BASE_DISTROS } ############### # BASE_NOSSL # ############### BASE_NOSSL = { "{REGISTRY}/{PROJECT_ID}/base-nossl:" + tag_base + "-" + arch: "//base:base_nossl" + debug_mode + "_" + user + "_" + arch + "_" + DEFAULT_DISTRO for arch in BASE_ARCHITECTURES[DEFAULT_DISTRO] for (tag_base, debug_mode, user) in VARIANTS } # oci_image_index BASE_NOSSL |= { "{REGISTRY}/{PROJECT_ID}/base-nossl:" + tag_base: "//base:base_nossl" + debug_mode + "_" + user + "_" + DEFAULT_DISTRO for (tag_base, debug_mode, user) in VARIANTS } BASE_NOSSL |= { "{REGISTRY}/{PROJECT_ID}/base-nossl-" + distro + ":" + tag_base + "-" + arch: "//base:base_nossl" + debug_mode + "_" + user + "_" + arch + "_" + distro for (tag_base, debug_mode, user) in VARIANTS for distro in BASE_DISTROS for arch in BASE_ARCHITECTURES[distro] } # oci_image_index BASE_NOSSL |= { "{REGISTRY}/{PROJECT_ID}/base-nossl-" + distro + ":" + tag_base: "//base:base_nossl" + debug_mode + "_" + user + "_" + distro for (tag_base, debug_mode, user) in VARIANTS for distro in BASE_DISTROS } ############### # CC # ############### CC = { "{REGISTRY}/{PROJECT_ID}/cc:" + tag_base + "-" + arch: "//cc:cc" + debug_mode + "_" + user + "_" + arch + "_" + DEFAULT_DISTRO for arch in CC_ARCHITECTURES[DEFAULT_DISTRO] for (tag_base, debug_mode, user) in VARIANTS } # oci_image_index CC |= { "{REGISTRY}/{PROJECT_ID}/cc:" + tag_base: "//cc:cc" + debug_mode + "_" + user + "_" + DEFAULT_DISTRO for (tag_base, debug_mode, user) in VARIANTS } CC |= { "{REGISTRY}/{PROJECT_ID}/cc-" + distro + ":" + tag_base + "-" + arch: "//cc:cc" + debug_mode + "_" + user + "_" + arch + "_" + distro for (tag_base, debug_mode, user) in VARIANTS for distro in CC_DISTROS for arch in CC_ARCHITECTURES[distro] } # oci_image_index CC |= { "{REGISTRY}/{PROJECT_ID}/cc-" + distro + ":" + tag_base: "//cc:cc" + debug_mode + "_" + user + "_" + distro for (tag_base, debug_mode, user) in VARIANTS for distro in CC_DISTROS } ############### # PYTHON 3 # ############### PYTHON3 = { "{REGISTRY}/{PROJECT_ID}/python3:" + tag_base + "-" + arch: "//python3:python3" + debug_mode + "_" + user + "_" + arch + "_" + DEFAULT_DISTRO for arch in PYTHON_ARCHITECTURES[DEFAULT_DISTRO] for (tag_base, debug_mode, user) in VARIANTS } # oci_image_index PYTHON3 |= { "{REGISTRY}/{PROJECT_ID}/python3:" + tag_base: "//python3:python3" + debug_mode + "_" + user + "_" + DEFAULT_DISTRO for (tag_base, debug_mode, user) in VARIANTS } PYTHON3 |= { "{REGISTRY}/{PROJECT_ID}/python3-" + distro + ":" + tag_base + "-" + arch: "//python3:python3" + debug_mode + "_" + user + "_" + arch + "_" + distro for distro in PYTHON_DISTROS for arch in PYTHON_ARCHITECTURES[distro] for (tag_base, debug_mode, user) in VARIANTS } # oci_image_index PYTHON3 |= { "{REGISTRY}/{PROJECT_ID}/python3-" + distro + ":" + tag_base: "//python3:python3" + debug_mode + "_" + user + "_" + distro for distro in PYTHON_DISTROS for (tag_base, debug_mode, user) in VARIANTS } ############### # NODEJS # ############### NODEJS = { "{REGISTRY}/{PROJECT_ID}/nodejs" + version + "-" + distro + ":" + tag_base + "-" + arch: "//nodejs:nodejs" + version + debug_mode + "_" + user + "_" + arch + "_" + distro for version in NODEJS_MAJOR_VERSIONS for distro in NODEJS_DISTROS for arch in NODEJS_ARCHITECTURES[distro][version] for (tag_base, debug_mode, user) in VARIANTS } # oci_image_index NODEJS |= { "{REGISTRY}/{PROJECT_ID}/nodejs" + version + "-" + distro + ":" + tag_base: "//nodejs:nodejs" + version + debug_mode + "_" + user + "_" + distro for version in NODEJS_MAJOR_VERSIONS for distro in NODEJS_DISTROS for (tag_base, debug_mode, user) in VARIANTS } NODEJS |= { "{REGISTRY}/{PROJECT_ID}/nodejs" + version + ":" + tag_base + "-" + arch: "//nodejs:nodejs" + version + debug_mode + "_" + user + "_" + arch + "_" + DEFAULT_DISTRO for version in NODEJS_MAJOR_VERSIONS for arch in NODEJS_ARCHITECTURES[DEFAULT_DISTRO][version] for (tag_base, debug_mode, user) in VARIANTS } # oci_image_index NODEJS |= { "{REGISTRY}/{PROJECT_ID}/nodejs" + version + ":" + tag_base: "//nodejs:nodejs" + version + debug_mode + "_" + user + "_" + DEFAULT_DISTRO for version in NODEJS_MAJOR_VERSIONS for (tag_base, debug_mode, user) in VARIANTS } ############### # JAVA_BASE # ############### JAVA_BASE = { "{REGISTRY}/{PROJECT_ID}/java-base:" + tag_base + "-" + arch: "//java:java_base" + debug_mode + "_" + user + "_" + arch + "_" + DEFAULT_DISTRO for arch in JAVA_ARCHITECTURES[DEFAULT_DISTRO] for (tag_base, debug_mode, user) in VARIANTS } JAVA_BASE |= { "{REGISTRY}/{PROJECT_ID}/java-base:" + tag_base: "//java:java_base" + debug_mode + "_" + user + "_" + DEFAULT_DISTRO for (tag_base, debug_mode, user) in VARIANTS } JAVA_BASE |= { "{REGISTRY}/{PROJECT_ID}/java-base-" + distro + ":" + tag_base + "-" + arch: "//java:java_base" + debug_mode + "_" + user + "_" + arch + "_" + distro for distro in JAVA_DISTROS for arch in JAVA_ARCHITECTURES[distro] for (tag_base, debug_mode, user) in VARIANTS } JAVA_BASE |= { "{REGISTRY}/{PROJECT_ID}/java-base-" + distro + ":" + tag_base: "//java:java_base" + debug_mode + "_" + user + "_" + distro for (tag_base, debug_mode, user) in VARIANTS for distro in JAVA_DISTROS } ############### # JAVA # ############### JAVA = { "{REGISTRY}/{PROJECT_ID}/java" + version + ":" + tag_base + "-" + arch: "//java:java" + version + debug_mode + "_" + user + "_" + arch + "_" + DEFAULT_DISTRO for version in JAVA_MAJOR_VERSIONS[DEFAULT_DISTRO] for arch in JAVA_ARCHITECTURES[DEFAULT_DISTRO] for (tag_base, debug_mode, user) in VARIANTS } # oci_image_index JAVA |= { "{REGISTRY}/{PROJECT_ID}/java" + version + ":" + tag_base: "//java:java" + version + debug_mode + "_" + user + "_" + DEFAULT_DISTRO for version in JAVA_MAJOR_VERSIONS[DEFAULT_DISTRO] for (tag_base, debug_mode, user) in VARIANTS } JAVA |= { "{REGISTRY}/{PROJECT_ID}/java" + version + "-" + distro + ":" + tag_base + "-" + arch: "//java:java" + version + debug_mode + "_" + user + "_" + arch + "_" + distro for distro in JAVA_DISTROS for version in JAVA_MAJOR_VERSIONS[distro] for arch in JAVA_ARCHITECTURES[distro] for (tag_base, debug_mode, user) in VARIANTS } # oci_image_index JAVA |= { "{REGISTRY}/{PROJECT_ID}/java" + version + "-" + distro + ":" + tag_base: "//java:java" + version + debug_mode + "_" + user + "_" + distro for (tag_base, debug_mode, user) in VARIANTS for distro in JAVA_DISTROS for version in JAVA_MAJOR_VERSIONS[distro] } ALL = {} ALL |= STATIC ALL |= BASE ALL |= BASE_NOSSL ALL |= CC ALL |= PYTHON3 ALL |= NODEJS ALL |= JAVA_BASE ALL |= JAVA # create additional tags by appending COMMIT_SHA to all tags # remove "latest" if they contain it (this is brittle if we make funky changes): # - image:latest -> image:{COMMIT_SHA} # - image:latest-xyz -> image:xyz-{COMMIT_SHA} COMMIT_SUFFIXED_TAGS = { (image_ref.replace("latest", "") + "-{COMMIT_SHA}").replace(":-", ":"): build_target for (image_ref, build_target) in ALL.items() } ALL |= COMMIT_SUFFIXED_TAGS sign_and_push_all( name = "sign_and_push", images = ALL, ) attach_lifecycle_tags( name = "attach_lifecycle_tags", images = ALL, ) ================================================ FILE: CONTRIBUTING.md ================================================ # How to become a contributor and submit your own code ## Contributor License Agreements We'd love to accept your patches! Before we can take them, we have to jump a couple of legal hurdles. Please fill out either the individual or corporate [Contributor License Agreement (CLA)](https://cla.developers.google.com/about). - If you are an individual writing original source code and you're sure you own the intellectual property, then you'll need to sign an [individual CLA](https://cla.developers.google.com/about/google-individual). - If you work for a company that wants to allow you to contribute your work, then you'll need to sign a [corporate CLA](https://cla.developers.google.com/about/google-corporate). Follow either of the two links above to access the appropriate CLA and instructions for how to sign and return it. Once we receive it, we'll be able to accept your pull requests. ## How to Build and Test 1. `bazel build //...` to build the whole project or ex:`bazel build //base:static_root_amd64_debian17` for a single image 2. For running tests, check `./knife test`. (`bazel test //...` will NOT run all tests, as many tests are marked "manual".) 3. For building and loading images to your local Docker engine, you need to add a new rule for that image to the BUILD: ```starlark load("@rules_oci//oci:defs.bzl", "oci_load") oci_load( name = "local_build", image = "//base:static_root_amd64_debian17", repo_tags = [], ) ``` then run the following command to load into the daemon ```shell bazel run //:local_build ``` ## Adding or removing Debian packages Whenever a change made to `common/*.yaml` manifests, the locking step has to be performed to regenerate lock files. This can be done by running; `./knife lock` ## Code style For styling Bazel files, install and run `buildifier` with: ```shell # Install buildifier version 3.2.0 go install github.com/bazelbuild/buildtools/buildifier@latest # This will automatically fix files. buildifier -mode=fix $(find . -name 'BUILD*' -o -name 'WORKSPACE*' -o -name '*.bzl' -type f) ``` For styling Python files, [install](https://www.pylint.org/#install) and run `pylint` with: ```shell # Install pylint sudo pip install pylint # Or sudo apt-get install pylint # Or on macos brew install pylint # Identify python style issues. find . -name "*.py" | xargs pylint --disable=R,C ``` ## Contributing a Patch 1. Submit an issue describing your proposed change to the repo in question. 1. The repo owner will respond to your issue promptly. 1. If your proposed change is accepted, and you haven't already done so, sign a Contributor License Agreement (see details above). 1. Fork the desired repo, develop and test your code changes. 1. Submit a pull request. ================================================ FILE: LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: MODULE.bazel ================================================ "distroless" module(name = "distroless") bazel_dep(name = "bazel_skylib", version = "1.8.2") bazel_dep(name = "aspect_bazel_lib", version = "2.21.1") bazel_dep(name = "rules_pkg", version = "1.1.0") bazel_dep(name = "platforms", version = "1.0.0") bazel_dep(name = "rules_go", version = "0.57.0") bazel_dep(name = "gazelle", version = "0.38.0") bazel_dep(name = "rules_rust", version = "0.63.0") bazel_dep(name = "container_structure_test", version = "1.19.1") bazel_dep(name = "rules_oci", version = "2.2.7") bazel_dep(name = "rules_distroless", version = "0.6.2") bazel_dep(name = "rules_python", version = "1.5.3") bazel_dep(name = "rules_cc", version = "0.2.4") ### OCI ### # Note: rules_oci registers toolchains in its MODULE.bazel # We import the repos to use crane in sign_and_push rule oci = use_extension("@rules_oci//oci:extensions.bzl", "oci") use_repo(oci, "oci_crane_toolchains") ### PYTHON ### python = use_extension("@rules_python//python/extensions:python.bzl", "python") python.toolchain( ignore_root_user_error = True, python_version = "3.11", ) ### GO #### go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps") go_deps.module( path = "github.com/spdx/tools-golang", sum = "h1:9B623Cfs+mclYK6dsae7gLSwuIBHvlgmEup87qpqsAQ=", version = "v0.3.1-0.20230104082527-d6f58551be3f", ) use_repo(go_deps, "com_github_spdx_tools_golang") ### BUSYBOX ### busybox = use_extension("//private/extensions:busybox.bzl", "busybox") busybox.archive() use_repo(busybox, "busybox_amd64", "busybox_arm", "busybox_arm64", "busybox_ppc64le", "busybox_riscv64", "busybox_s390x") ### JAVA ### ### NODE ### node = use_extension("//private/extensions:node.bzl", "node") node.archive() use_repo(node, "nodejs20_amd64", "nodejs20_arm", "nodejs20_arm64", "nodejs20_ppc64le", "nodejs20_s390x", "nodejs22_amd64", "nodejs22_arm", "nodejs22_arm64", "nodejs22_ppc64le", "nodejs22_s390x", "nodejs24_amd64", "nodejs24_arm64", "nodejs24_ppc64le", "nodejs24_s390x") ### DEBIAN ### include("//private/repos/deb:deb.MODULE.bazel") ================================================ FILE: PACKAGE_METADATA.md ================================================ # Package Metadata ## `dpkg` Metadata Structure Standard ### Overview This document defines the standard structure for `dpkg` metadata within Google Distroless Debian-based images. The goal is to provide a clear specification for tool authors and users, enabling consistent and accurate results for vulnerability (CVE) scanning and package analysis. ### Directory Structure Distroless Debian images differ from traditional Debian images in their handling of `dpkg` metadata. The relevant structure is as follows: ``` /var/lib/dpkg/ └── status.d/ ├── └── .md5sums ``` ### Details - **`/var/lib/dpkg/status.d/`** - Contains one file per installed package. - Each file is named after the package (e.g., `libc6`, `libssl1.1`). - **`/var/lib/dpkg/status.d/`** - Contains package metadata, equivalent to the output of: ``` dpkg-deb --field .deb > /var/lib/dpkg/status.d/ ``` - **`/var/lib/dpkg/status.d/.md5sums`** - Contains file checksums, equivalent to the output of: ``` dpkg-deb --control .deb CONTROL cp CONTROL/md5sums /var/lib/dpkg/status.d/.md5sums rm -rf CONTROL ``` ### Omitted Files Distroless images intentionally omit several files found in standard Debian images: - `/var/lib/dpkg/status` - **Not present.** Replaced by the `status.d` directory. - `/var/lib/dpkg/info/.list` - **Not present.** File lists can be inferred from the `.md5sums` files. - `/var/lib/dpkg/info/.md5sums` - **Not present.** Checksums are stored in `status.d/.md5sums`. - Other `/var/lib/dpkg/info/.*` files - **Not present.** Not required for CVE scanning. ### Rationale - **CVE Scanning Compatibility:** The provided metadata is sufficient for most vulnerability scanners to identify installed packages and their versions. - **Avoiding Conflicts:** Using the `status.d` directory exclusively prevents confusion or potential issues that could arise if files conflicted with default `dpkg` folders. This approach ensures compatibility, especially if `dpkg` is used directly within the image. ### Guidance for Tool Authors - Scan `/var/lib/dpkg/status.d/` for installed package metadata. - Use `` files for package details. - Use `.md5sums` for file checksums and file lists. - Do not expect `/var/lib/dpkg/status` or `/var/lib/dpkg/info/` files. ## Non-debian packages TODO ================================================ FILE: README.md ================================================ # "Distroless" Container Images. [![CI Build Status](https://github.com/GoogleContainerTools/distroless/actions/workflows/ci.yaml/badge.svg)](https://github.com/GoogleContainerTools/distroless/actions/workflows/ci.yaml) "Distroless" images contain only your application and its runtime dependencies. They do not contain package managers, shells or any other programs you would expect to find in a standard Linux distribution. For more information, see this [talk](https://swampup2017.sched.com/event/A6CW/distroless-docker-containerizing-apps-not-vms?iframe=no&w=100%&sidebar=yes&bg=no) ([video](https://www.youtube.com/watch?v=lviLZFciDv4)). ## Why should I use distroless images? Restricting what's in your runtime container to precisely what's necessary for your app is a best practice employed by Google and other tech giants that have used containers in production for many years. It improves the signal to noise of scanners (e.g. CVE) and reduces the burden of establishing provenance to just what you need. Distroless images are _very small_. The smallest distroless image, `gcr.io/distroless/static-debian12`, is around 2 MiB. That's about 50% of the size of `alpine` (~5 MiB), and less than 2% of the size of `debian` (124 MiB). ## How do I use distroless images? These images are built using [bazel](https://bazel.build), but they can also be used through other Docker image build tooling. ### What images are available? The following images are currently published and updated by the distroless project (see [SUPPORT_POLICY.md](SUPPORT_POLICY.md) for support timelines) These images refer to image indexes with references to all supported architectures. Architecture specific images can be directly referenced using an additional architecture suffix on the tag, like `gcr.io/distroless/static-debian12:latest-amd64` Any other tags are considered deprecated and are no longer updated #### Debian 12 | Image | Tags | Architecture Suffixes | | ------------------------------------- | ------------------------------------- | --------------------------------- | | gcr.io/distroless/static-debian12 | latest, nonroot, debug, debug-nonroot | amd64, arm64, arm, s390x, ppc64le | | gcr.io/distroless/base-debian12 | latest, nonroot, debug, debug-nonroot | amd64, arm64, arm, s390x, ppc64le | | gcr.io/distroless/base-nossl-debian12 | latest, nonroot, debug, debug-nonroot | amd64, arm64, arm, s390x, ppc64le | | gcr.io/distroless/cc-debian12 | latest, nonroot, debug, debug-nonroot | amd64, arm64, arm, s390x, ppc64le | | gcr.io/distroless/python3-debian12 | latest, nonroot, debug, debug-nonroot | amd64, arm64 | #### Debian 13 Debian 13 distroless images use the debian [UsrMerge](https://wiki.debian.org/UsrMerge) scheme. If you use `rules_distroless` to add packages to an image, set `mergedusr = True` in [`apt.install`](https://registry.bazel.build/docs/rules_distroless#apt_install). | Image | Tags | Architecture Suffixes | | ------------------------------------- | ------------------------------------- | ------------------------------------------ | | gcr.io/distroless/static-debian13 | latest, nonroot, debug, debug-nonroot | amd64, arm64, arm, s390x, ppc64le, riscv64 | | gcr.io/distroless/base-debian13 | latest, nonroot, debug, debug-nonroot | amd64, arm64, arm, s390x, ppc64le, riscv64 | | gcr.io/distroless/base-nossl-debian13 | latest, nonroot, debug, debug-nonroot | amd64, arm64, arm, s390x, ppc64le, riscv64 | | gcr.io/distroless/cc-debian13 | latest, nonroot, debug, debug-nonroot | amd64, arm64, arm, s390x, ppc64le, riscv64 | | gcr.io/distroless/java-base-debian13 | latest, nonroot, debug, debug-nonroot | amd64, arm64, s390x, ppc64le, riscv64 | | gcr.io/distroless/java17-debian13 | latest, nonroot, debug, debug-nonroot | amd64, arm64, s390x, ppc64le, riscv64 | | gcr.io/distroless/java21-debian13 | latest, nonroot, debug, debug-nonroot | amd64, arm64, s390x, ppc64le, riscv64 | | gcr.io/distroless/java25-debian13 | latest, nonroot, debug, debug-nonroot | amd64, arm64, s390x, ppc64le, riscv64 | | gcr.io/distroless/nodejs20-debian13 | latest, nonroot, debug, debug-nonroot | amd64, arm64, arm, s390x, ppc64le | | gcr.io/distroless/nodejs22-debian13 | latest, nonroot, debug, debug-nonroot | amd64, arm64, arm, s390x, ppc64le | | gcr.io/distroless/nodejs24-debian13 | latest, nonroot, debug, debug-nonroot | amd64, arm64, s390x, ppc64le | | gcr.io/distroless/python3-debian13 | latest, nonroot, debug, debug-nonroot | amd64, arm64 | ## Why is distroless still using `gcr.io` instead of `pkg.dev`? Distroless's serving infrastructure has moved to artifact registry but we still use the `gcr.io` domain. Users will get the benefits of the newer infrastructure without changing their builds. ## How do I verify distroless images? All distroless images are signed by [cosign](https://github.com/sigstore/cosign) with ephemeral keys (keyless). We recommend verifying any distroless image you use before building your image. You can verify the keyless signature of any distroless image with: ```sh cosign verify $IMAGE_NAME --certificate-oidc-issuer https://accounts.google.com --certificate-identity keyless@distroless.iam.gserviceaccount.com ``` ### Entrypoints Note that distroless images by default do not contain a shell. That means the Dockerfile `ENTRYPOINT` command, when defined, must be specified in `vector` form, to avoid the container runtime prefixing with a shell. This works: ```dockerfile ENTRYPOINT ["myapp"] ``` But this does not work: ```dockerfile ENTRYPOINT "myapp" ``` For the same reasons, if the entrypoint is set to the empty vector, the CMD command should be specified in `vector` form (see examples below). Note that by default static, base and cc images have the empty vector entrypoint. Images with an included language runtime have a language specific default (see: [java](java/README.md#usage), [nodejs](nodejs/README.md#usage), [python3](python3/README.md#usage)). ### Docker Docker multi-stage builds make using distroless images easy. Follow these steps to get started: - Pick the right base image for your application stack. - Write a multi-stage docker file. Note: This requires Docker 17.05 or higher. The basic idea is that you'll have one stage to build your application artifacts, and insert them into your runtime distroless image. If you'd like to learn more, please see the documentation on [multi-stage builds](https://docs.docker.com/engine/userguide/eng-image/multistage-build/). #### Examples with Docker Here's a quick example for go: ```dockerfile # Start by building the application. FROM golang:1.18 as build WORKDIR /go/src/app COPY . . RUN go mod download RUN CGO_ENABLED=0 go build -o /go/bin/app # Now copy it into our base image. FROM gcr.io/distroless/static-debian12 COPY --from=build /go/bin/app / CMD ["/app"] ``` You can find other examples here: - [Java](examples/java/Dockerfile) - [Python 3](examples/python3/Dockerfile) - [Go](examples/go/Dockerfile) - [Node.js](examples/nodejs/Dockerfile) - [Rust](examples/rust/Dockerfile) To run any example, go to the directory for the language and run: ```sh docker build -t myapp . docker run -t myapp ``` To run the [Node.js Express example app](examples/nodejs/node-express) and expose the container's ports: ```sh npm install # Install express and its transitive dependencies docker build -t myexpressapp . # Normal build command docker run -p 3000:3000 -t myexpressapp ``` This should expose the Express application to your `localhost:3000` ### Bazel For full documentation on how to use bazel to generate Container images, see the [bazel-contrib/rules_oci](https://github.com/bazel-contrib/rules_oci) repository. For documentation and example on how to create custom container images, see the [GoogleContainerTools/rules_distroless](https://github.com/GoogleContainerTools/rules_distroless) repository. Examples can be found in the [GoogleContainerTools/rules_distroless](https://github.com/GoogleContainerTools/rules_distroless/tree/main/examples) repository. #### Examples with Bazel We have some examples on how to run some common application stacks in the /examples directory. See here for: - [Java](examples/java/BUILD) - [Python 3](examples/python3/BUILD) - [Go](examples/go/BUILD) - [Node.js](examples/nodejs/BUILD) See here for examples on how to complete some common tasks in your image: - [Adding and running as a non-root user](examples/nonroot) - [Including Debian Packages](https://registry.bazel.build/docs/rules_distroless#module_extension-apt) - [Including CA certificates](https://registry.bazel.build/docs/rules_distroless#rule-cacerts) See here for more information on how these images are [built and released](RELEASES.md). ### Base Operating System Distroless images are based on Debian 12 (bookworm). Images are explicitly tagged with Debian version suffixes (e.g. `-debian12`). Specifying an image without the distribution will currently select `-debian12` images, but that will change in the future to a newer version of Debian. It can be useful to reference the distribution explicitly, to prevent breaking builds when the next Debian version is released. ### Operating System Updates for Security Fixes and CVEs Distroless tracks the upstream Debian releases, using [Github actions to automatically generate a pull request when there are updates](https://github.com/GoogleContainerTools/distroless/blob/main/.github/workflows/update-deb-package-snapshots.yml). ### Debug Images Distroless images are minimal and lack shell access. The `:debug` image set for each language provides a busybox shell to enter. For example: ```sh cd examples/python3/ ``` edit the `Dockerfile` to change the final image to `:debug`: ```dockerfile FROM gcr.io/distroless/python3-debian12:debug COPY . /app WORKDIR /app CMD ["hello.py", "/etc"] ``` then build and launch with a shell entrypoint: ```sh docker build -t my_debug_image . ``` ```sh $ docker run --entrypoint=sh -ti my_debug_image /app # ls BUILD Dockerfile hello.py ``` > Note: If the image you are using already has a tag, for example `gcr.io/distroless/java17-debian13:nonroot`, use the tag `debug-` instead, for example `gcr.io/distroless/java17-debian13:debug-nonroot`. > Note: [ldd](http://man7.org/linux/man-pages/man1/ldd.1.html) is not installed in the base image as it's a shell script, you can copy it in or download it. ### Who uses Distroless? - [Kubernetes](https://github.com/kubernetes/enhancements/blob/master/keps/sig-release/1729-rebase-images-to-distroless/README.md), since v1.15 - [Knative](https://knative.dev) - [Tekton](https://tekton.dev) - [Teleport](https://goteleport.com) - [BloodHound](https://github.com/SpecterOps/BloodHound) by [SpecterOps](https://specterops.io/) If your project uses Distroless, send a PR to add your project here! ## Community Discussion - [distroless-users Google Group](https://groups.google.com/forum/#!forum/distroless-users) - [Kubernetes slack #distroless channel](https://slack.k8s.io/) ================================================ FILE: RELEASES.md ================================================ # Release Process Images in this repository are built and released in the `gcr.io/distroless` repository on the [Google Container Registry](https://cloud.google.com/container-registry/). Images are automatically built and pushed every commit, according to the policy defined in [cloudbuild.yaml](.cloudbuild/cloudbuild.yaml). ================================================ FILE: SECURITY.md ================================================ # Security Policy ## Supported Versions Distroless currently tracks debian 12 ([bookworm](https://packages.debian.org/bookworm/allpackages)) and debian 13 ([trixie](https://packages.debian.org/trixie/allpackages)) packages. Debian package versions used for the current build are found in https://github.com/GoogleContainerTools/distroless/blob/main/private/repos/deb. It can be parsed and printed into simple json data by invoking `./knife deb-versions` at the root of this project. ## Reporting a Vulnerability If a distroless image you are using contains a CVE or other vulnerability: 1. ensure you are using a [currently supported image](https://github.com/GoogleContainerTools/distroless#what-images-are-available) 1. find the appropriate debian security-tracker notice: `https://security-tracker.debian.org/tracker/CVE-XXXX-YYYYY`, for [example](https://security-tracker.debian.org/tracker/CVE-2022-21476). 1. check if a fix is available for the appropriate debian version in the main/security channels (ex `trixie`, `trixie (security)`). 1. if a fix is not yet available, do not file a bug, track it in your internal tracker until one becomes available. 1. if a fix is available *and* it has been more than 48 hours, please let the team know by creating an issue and pointing to the CVE or vulnerability disclosure. ================================================ FILE: SUPPORT_POLICY.md ================================================ Distroless currently tracks Debian on their [standard support timeline](https://wiki.debian.org/DebianReleases#Production_Releases). The current estimation of end of life for images with the pattern: `gcr.io/distroless/-debian:(latest|nonroot|debug|debug-nonroot)` | Image | Debian 12 EOL | Debian 13 EOL | | ----------- | -------------- | --------------------------- | | static | Sept 2026 | debian 14 release day + 1yr | | base | Sept 2026 | debian 14 release day + 1yr | | base-nossl | Sept 2026 | debian 14 release day + 1yr | | cc | Sept 2026 | debian 14 release day + 1yr | | java* | Jan 2026 | debian 14 release day + 3mo | | node* | Jan 2026 | debian 14 release day + 3mo | | python* | April 2026 | debian 14 release day + 3mo | \* see below for language specific runtime notes ### Java Java will only support current LTS version distributed by debian [see here](https://wiki.debian.org/Java). ### Node Node version support is for even numbered releases (20, 22, 24, etc) that are current, active or in LTS maintenance. For more information, [see here](https://nodejs.org/en/about/previous-releases#release-schedule). ### Python (TBD) ### Images no longer supported A list of supported image tags is available here: https://github.com/GoogleContainerTools/distroless#what-images-are-available ================================================ FILE: WORKSPACE ================================================ load("@rules_oci//cosign:repositories.bzl", "cosign_register_toolchains") cosign_register_toolchains(name = "oci_cosign") ================================================ FILE: base/BUILD ================================================ load(":base.bzl", "base_image", "base_image_index", "base_nossl_image", "base_nossl_image_index") load(":config.bzl", "BASE_ARCHITECTURES", "BASE_DISTROS", "BASE_NOSSL_PACKAGES", "BASE_PACKAGES") package(default_visibility = ["//visibility:public"]) # base nossl [ base_nossl_image( arch = arch, distro = distro, packages = BASE_NOSSL_PACKAGES[distro], ) for distro in BASE_DISTROS for arch in BASE_ARCHITECTURES[distro] ] [ base_nossl_image_index( architectures = BASE_ARCHITECTURES[distro], distro = distro, ) for distro in BASE_DISTROS ] # base (with libssl) [ base_image( arch = arch, distro = distro, packages = BASE_PACKAGES[distro], ) for distro in BASE_DISTROS for arch in BASE_ARCHITECTURES[distro] ] [ base_image_index( architectures = BASE_ARCHITECTURES[distro], distro = distro, ) for distro in BASE_DISTROS ] ================================================ FILE: base/README.md ================================================ # Documentation for `gcr.io/distroless/base`, `gcr.io/distroless/base-nossl` and `gcr.io/distroless/static` ## Image Contents This image contains a minimal Linux, glibc-based system. It is intended for use directly by "mostly-statically compiled" languages like Go, Rust or D. Statically compiled applications (Go) that do not require libc can use the `gcr.io/distroless/static` image, which contains: * ca-certificates * A /etc/passwd entry for a root user * A /tmp directory * tzdata Applications that require libc but do not need libssl can use the `gcr.io/distroless/base-nossl`, which contains all of the packages in `gcr.io/distroless/static`, and * glibc Most other applications (and Go apps that require libc/cgo) should start with `gcr.io/distroless/base`, which contains all of the packages in `gcr.io/distroless/static`, and * glibc * libssl * for Debian 13 or later, libssl dependencies (zlib, libzstd) are also included. Note: Debian 13 base image does not include [OpenSSL legacy algorithms](https://docs.openssl.org/3.5/man7/OSSL_PROVIDER-legacy/#operations-and-algorithms). If you want to use them, you will need to add `openssl-legacy-provider` yourself. ## Usage Users are expected to include their compiled application and set the correct cmd in their image. ================================================ FILE: base/base.bzl ================================================ "defines a function to replicate the container images for different distributions" load("@container_structure_test//:defs.bzl", "container_structure_test") load("@rules_oci//oci:defs.bzl", "oci_image", "oci_image_index") load("//common:variables.bzl", "DEBUG_MODE", "USERS") load("//private/util:deb.bzl", "deb") def base_nossl_image_index(distro, architectures): """base nossl image index for a distro Args: distro: name of distribution architectures: all architectures included in index """ [ oci_image_index( name = "base_nossl" + mode + "_" + user + "_" + distro, images = [ "base_nossl" + mode + "_" + user + "_" + arch + "_" + distro for arch in architectures ], ) for user in USERS for mode in DEBUG_MODE ] def base_image_index(distro, architectures): """base image index for a distro Args: distro: name of distribution architectures: all architectures included in index """ [ oci_image_index( name = "base" + mode + "_" + user + "_" + distro, images = [ "base" + mode + "_" + user + "_" + arch + "_" + distro for arch in architectures ], ) for user in USERS for mode in DEBUG_MODE ] def base_nossl_image(distro, arch, packages): """base nossl and debug images and tests for a distro/arch Args: distro: name of the distribution arch: the target architecture """ [ oci_image( name = "base_nossl" + mode + "_" + user + "_" + arch + "_" + distro, base = "//static:static" + mode + "_" + user + "_" + arch + "_" + distro, tars = [ deb.package(arch, distro, pkg) for pkg in packages ], ) for user in USERS for mode in DEBUG_MODE ] # Check for common base files. container_structure_test( name = "base_nossl_" + arch + "_" + distro + "_test", configs = ["testdata/base.yaml"], image = ":base_nossl_root_" + arch + "_" + distro, tags = ["manual", arch], ) # Check for busybox container_structure_test( name = "base_nossl_debug_" + arch + "_" + distro + "_test", configs = ["testdata/debug.yaml"], image = ":base_nossl_debug_root_" + arch + "_" + distro, tags = ["manual", arch], ) def base_image(distro, arch, packages): """base and debug images and tests for a distro/arch Args: distro: name of the distribution arch: the target architecture """ LIBSSL = { "debian12": "libssl3", "debian13": "libssl3t64", } [ oci_image( name = "base" + mode + "_" + user + "_" + arch + "_" + distro, base = "//static:static" + mode + "_" + user + "_" + arch + "_" + distro, tars = [ deb.package(arch, distro, pkg) for pkg in packages ], ) for user in USERS for mode in DEBUG_MODE ] # Check for common base files. container_structure_test( name = "base_" + arch + "_" + distro + "_test", configs = ["testdata/base.yaml"], image = ":base_root_" + arch + "_" + distro, tags = ["manual", arch], ) # Check for busybox container_structure_test( name = "base_debug_" + arch + "_" + distro + "_test", configs = ["testdata/debug.yaml"], image = ":base_debug_root_" + arch + "_" + distro, tags = ["manual", arch], ) ================================================ FILE: base/config.bzl ================================================ BASE_DISTROS = ["debian12", "debian13"] BASE_ARCHITECTURES = { "debian12": ["amd64", "arm64", "arm", "s390x", "ppc64le"], "debian13": ["amd64", "arm64", "arm", "s390x", "ppc64le", "riscv64"], } BASE_PACKAGES = { "debian12": [ "libc6", "libssl3", ], "debian13": [ "libc6", "libssl3t64", "libzstd1", "zlib1g", ], } BASE_NOSSL_PACKAGES = { "debian12": [ "libc6", ], "debian13": [ "libc6", ], } ================================================ FILE: base/test.sh ================================================ $RUNFILES_DIR/runtimes_common/structure_tests/ext_run.sh \ -i bazel/base:cc \ -t $RUNFILES_DIR/distroless/base/base.tar \ -c $RUNFILES_DIR/distroless/base/testdata/base.yaml ================================================ FILE: base/testdata/base.yaml ================================================ schemaVersion: "1.0.0" fileExistenceTests: # Basic FS sanity checks. - name: root path: '/' shouldExist: true - name: tmp path: '/tmp' shouldExist: true - name: passwd path: '/etc/passwd' shouldExist: true - name: group path: '/etc/group' shouldExist: true - name: etc-os-release path: '/etc/os-release' shouldExist: true - name: certs path: '/etc/ssl/certs/ca-certificates.crt' shouldExist: true - name: certs_copyright path: '/usr/share/doc/ca-certificates/copyright' shouldExist: true - name: services path: '/etc/services' shouldExist: true - name: tzdata_copyright path: '/usr/share/doc/tzdata/copyright' shouldExist: true - name: tzdata_zoneinfo path: '/usr/share/zoneinfo' shouldExist: true - name: homedir path: '/root' shouldExist: true - name: nonroot-homedir path: '/home/nonroot' shouldExist: true - name: dpkg-status.d path: '/var/lib/dpkg/status.d/libc6' shouldExist: true fileContentTests: - name: 'known users' path: '/etc/passwd' expectedContents: ['^root:x:0:0:root:/root:/sbin/nologin\nnobody:x:65534:65534:nobody:/nonexistent:/sbin/nologin\nnonroot:x:65532:65532:nonroot:/home/nonroot:/sbin/nologin\n$'] - name: 'known groups' path: '/etc/group' expectedContents: ['^root:x:0:\nnobody:x:65534:\ntty:x:5:\nstaff:x:50:\nnonroot:x:65532:\n$'] - name: '/usr/lib/os-release pretty name' path: '/usr/lib/os-release' expectedContents: ['PRETTY_NAME="Distroless"'] # /etc/os-release is a symlink to /usr/lib/os-release, make sure they match. - name: '/etc/os-release pretty name' path: '/etc/os-release' expectedContents: ['PRETTY_NAME="Distroless"'] ================================================ FILE: base/testdata/debug.yaml ================================================ schemaVersion: "1.0.0" fileExistenceTests: # Basic FS sanity checks. - name: busybox path: '/busybox' shouldExist: true commandTests: - name: busybox command: ["/busybox/busybox"] expectedOutput: ['BusyBox v1\.37\.0'] ================================================ FILE: cc/BUILD ================================================ load(":cc.bzl", "cc_image", "cc_image_index") load(":config.bzl", "CC_ARCHITECTURES", "CC_DISTROS", "CC_PACKAGES") package(default_visibility = ["//visibility:public"]) [ cc_image( arch = arch, distro = distro, packages = CC_PACKAGES[distro], ) for distro in CC_DISTROS for arch in CC_ARCHITECTURES[distro] ] [ cc_image_index( architectures = CC_ARCHITECTURES[distro], distro = distro, ) for distro in CC_DISTROS ] ================================================ FILE: cc/README.md ================================================ # Documentation for `gcr.io/distroless/cc` ## Image Contents This image contains a minimal Linux, glibc runtime for "mostly-statically compiled" languages like Rust and D. Specifically, the image contains everything in the [base image](../base/README.md), plus: * libgcc1 and its dependencies. ## Usage Users are expected to include their compiled application and set the correct CMD in their image. ================================================ FILE: cc/cc.bzl ================================================ load("@rules_oci//oci:defs.bzl", "oci_image", "oci_image_index") load("//common:variables.bzl", "DEBUG_MODE", "USERS") load("//private/util:deb.bzl", "deb") def cc_image_index(distro, architectures): """cc image index for a distro Args: distro: name of distribution architectures: all architectures included in index """ [ oci_image_index( name = "cc" + mode + "_" + user + "_" + distro, images = [ "cc" + mode + "_" + user + "_" + arch + "_" + distro for arch in architectures ], ) for mode in DEBUG_MODE for user in USERS ] def cc_image(distro, arch, packages): """base nossl and debug images and tests for a distro/arch Args: distro: name of the distribution arch: the target architecture """ [ oci_image( name = "cc" + mode + "_" + user + "_" + arch + "_" + distro, base = "//base:base" + mode + "_" + user + "_" + arch + "_" + distro, tars = [ deb.package(arch, distro, pkg) for pkg in packages ], ) for mode in DEBUG_MODE for user in USERS ] ================================================ FILE: cc/config.bzl ================================================ CC_DISTROS = ["debian12", "debian13"] CC_ARCHITECTURES = { "debian12": ["amd64", "arm64", "arm", "s390x", "ppc64le"], "debian13": ["amd64", "arm64", "arm", "s390x", "ppc64le", "riscv64"], } CC_PACKAGES = { "debian12": [ "libgomp1", "libstdc++6", "libgcc-s1", "gcc-12-base", ], "debian13": [ "libgomp1", "libstdc++6", "libgcc-s1", "gcc-14-base", ], } ================================================ FILE: common/BUILD.bazel ================================================ load("@aspect_bazel_lib//lib:tar.bzl", "tar") load("@rules_distroless//distroless:defs.bzl", "cacerts", "group", "home", "locale", "os_release", "passwd") load("//:distro.bzl", "ALL_DISTROS", "VERSIONS") load("//private/util:deb.bzl", "deb") load(":variables.bzl", "NOBODY", "NONROOT", "OS_RELEASE", "ROOT", "quote") package(default_visibility = ["//visibility:public"]) COMMON_DISTROS = ALL_DISTROS COMMON_ARCHITECTURES = { "debian12": [ "amd64", "arm64", "arm", "s390x", "ppc64le", ], "debian13": [ "amd64", "arm64", "arm", "s390x", "ppc64le", "riscv64", ], } tar( name = "rootfs", srcs = [], args = [ "--format", "gnutar", ], compress = "gzip", mtree = ["./ type=dir uid=0 gid=0 mode=0755 time=0.0"], ) tar( name = "tmp", srcs = [], # original tmp.tar was created on a gnutar, mimic that. args = [ "--format", "gnutar", ], compress = "gzip", mtree = ["./tmp gname=root uname=root time=0.0 mode=1777 gid=0 uid=0 type=dir"], ) [ os_release( name = "os_release_%s" % dist, content = { key: quote(value.format( CODENAME = codename, VERSION = version, )) for (key, value) in OS_RELEASE.items() }, ) for (dist, codename, version) in VERSIONS ] [ locale( name = "locale_%s_%s" % (distro, arch), charset = "C.utf8", package = deb.data(arch, distro, "libc-bin"), ) for distro in COMMON_DISTROS for arch in COMMON_ARCHITECTURES[distro] ] [ cacerts( name = "cacerts_%s_%s" % (distro, arch), package = deb.data(arch, distro, "ca-certificates"), ) for distro in COMMON_DISTROS for arch in COMMON_ARCHITECTURES[distro] ] # create /etc/group with the root, tty, and staff groups group( name = "group", entries = [ { "name": "root", # root_group "gid": ROOT, "password": "x", }, { "name": "nobody", # nobody_group "gid": NOBODY, "password": "x", }, { "name": "tty", # tty_group "gid": 5, "password": "x", }, { "name": "staff", # staff_group "gid": 50, "password": "x", }, { "name": "nonroot", # nonroot_group "gid": NONROOT, "password": "x", }, ], ) passwd( name = "passwd", entries = [ { "gecos": ["root"], "gid": ROOT, "shell": "/sbin/nologin", "home": "/root", "uid": ROOT, "password": "x", "username": "root", }, { "gecos": ["nobody"], "gid": NOBODY, "home": "/nonexistent", "shell": "/sbin/nologin", "uid": NOBODY, "password": "x", "username": "nobody", }, { "gecos": ["nonroot"], "gid": NONROOT, "home": "/home/nonroot", "shell": "/sbin/nologin", "uid": NONROOT, "password": "x", "username": "nonroot", }, ], ) home( name = "home", dirs = [ { "home": "/root", "uid": ROOT, "gid": ROOT, "mode": 700, }, { "home": "/home", "uid": ROOT, "gid": ROOT, "mode": 755, }, { "home": "/home/nonroot", "uid": NONROOT, "gid": NONROOT, "mode": 700, }, ], ) ================================================ FILE: common/variables.bzl ================================================ "common variables" def quote(str): return '''"{}"'''.format(str) OS_RELEASE = dict( PRETTY_NAME = "Distroless", NAME = "Debian GNU/Linux", ID = "debian", VERSION_ID = "{VERSION}", VERSION = "Debian GNU/Linux {VERSION} ({CODENAME})", HOME_URL = "https://github.com/GoogleContainerTools/distroless", SUPPORT_URL = "https://github.com/GoogleContainerTools/distroless/blob/master/README.md", BUG_REPORT_URL = "https://github.com/GoogleContainerTools/distroless/issues/new", ) NOBODY = 65534 NONROOT = 65532 ROOT = 0 DEBUG_MODE = ["", "_debug"] USERS = ["root", "nonroot"] ================================================ FILE: cosign.pub ================================================ -----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEWZzVzkb8A+DbgDpaJId/bOmV8n7Q OqxYbK0Iro6GzSmOzxkn+N2AKawLyXi84WSwJQBK//psATakCgAQKkNTAA== -----END PUBLIC KEY----- ================================================ FILE: distro.bzl ================================================ VERSIONS = [ ("debian12", "bookworm", "12"), ("debian13", "trixie", "13"), ] VARIANTS = { "arm": "v7", "arm64": "v8", } ALL_ARCHITECTURES = ["amd64", "arm64", "arm", "s390x", "ppc64le", "riscv64"] ALL_DISTROS = ["debian12", "debian13"] ================================================ FILE: downloader.cfg ================================================ rewrite (mirrors\.kernel\.org)/gnu/(.*) https://ftp.gnu.org/gnu/$2 rewrite (mirrors\.kernel\.org)/gnu/(.*) https://ftpmirror.gnu.org/gnu/$2 ================================================ FILE: examples/BUILD ================================================ package(default_visibility = ["//visibility:public"]) ================================================ FILE: examples/cc/BUILD ================================================ # Public notice: this file is for internal documentation, testing, and # reference only. Note that repo maintainers can freely change any part of the # repository code at any time. load("@container_structure_test//:defs.bzl", "container_structure_test") load("//cc:config.bzl", DISTROS = "CC_DISTROS") load("//private/oci:defs.bzl", "cc_image") package(default_visibility = ["//visibility:public"]) [cc_image( name = "hello_" + distro, srcs = ["hello.c"], base = "//cc:cc_root_amd64_" + distro, ) for distro in DISTROS] [cc_image( name = "hello_cc_" + distro, srcs = ["hello_cc.cc"], base = "//cc:cc_root_amd64_" + distro, ) for distro in DISTROS] [container_structure_test( name = "hello_" + distro + "_test", size = "small", configs = ["testdata/hello_" + distro + ".yaml"], image = ":hello_" + distro, tags = [ "amd64", "manual", ], ) for distro in DISTROS] [container_structure_test( name = "hello_cc_" + distro + "_test", size = "small", configs = ["testdata/hello_cc_" + distro + ".yaml"], image = ":hello_cc_" + distro, tags = [ "amd64", "manual", ], ) for distro in DISTROS] ================================================ FILE: examples/cc/Dockerfile ================================================ FROM gcc:6 AS build-env COPY . /app WORKDIR /app RUN cc hello.c -o hello FROM gcr.io/distroless/cc COPY --from=build-env /app /app WORKDIR /app CMD ["./hello"] ================================================ FILE: examples/cc/hello.c ================================================ #include int main() { printf("Hello from distroless C!\n"); return 0; } ================================================ FILE: examples/cc/hello_cc.cc ================================================ #include int main() { std::cout << "Hello from distroless C++!" << std::endl; return 0; } ================================================ FILE: examples/cc/testdata/hello_cc_debian12.yaml ================================================ schemaVersion: "1.0.0" commandTests: - name: hello_cc command: ['/hello_cc_debian12_binary'] expectedOutput: ['Hello from distroless C\+\+!'] ================================================ FILE: examples/cc/testdata/hello_cc_debian13.yaml ================================================ schemaVersion: "1.0.0" commandTests: - name: hello_cc command: ['/hello_cc_debian13_binary'] expectedOutput: ['Hello from distroless C\+\+!'] ================================================ FILE: examples/cc/testdata/hello_debian12.yaml ================================================ schemaVersion: "1.0.0" commandTests: - name: hello command: ['/hello_debian12_binary'] expectedOutput: ['Hello from distroless C!'] ================================================ FILE: examples/cc/testdata/hello_debian13.yaml ================================================ schemaVersion: "1.0.0" commandTests: - name: hello command: ['/hello_debian13_binary'] expectedOutput: ['Hello from distroless C!'] ================================================ FILE: examples/go/BUILD ================================================ # Public notice: this file is for internal documentation, testing, and # reference only. Note that repo maintainers can freely change any part of the # repository code at any time. load("@rules_oci//oci:defs.bzl", "oci_load") load("//private/oci:defs.bzl", "go_image") package(default_visibility = ["//visibility:public"]) go_image( name = "go_example", srcs = ["main.go"], base = "//base:base_root_amd64_debian12", ) # Run # bazel run //examples/go:tarball # podman run localhost/distroless/examples/go:latest oci_load( name = "tarball", image = ":go_example", repo_tags = ["distroless/examples/go:latest"], ) ================================================ FILE: examples/go/Dockerfile ================================================ FROM golang:1.22 as build WORKDIR /go/src/app COPY . . RUN go mod download RUN go vet -v RUN go test -v RUN CGO_ENABLED=0 go build -o /go/bin/app FROM gcr.io/distroless/static-debian12 COPY --from=build /go/bin/app / CMD ["/app"] ================================================ FILE: examples/go/go.mod ================================================ module github.com/GoogleContainerTools/distroless/examples/go go 1.18 ================================================ FILE: examples/go/main.go ================================================ // Copyright 2017 Google Inc. All rights reserved. // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package main import "fmt" func main() { fmt.Println("Hello, world!") } ================================================ FILE: examples/go/main_test.go ================================================ package main import ( "testing" ) func Test1(t *testing.T) { } ================================================ FILE: examples/java/BUILD ================================================ # Public notice: this file is for internal documentation, testing, and # reference only. Note that repo maintainers can freely change any part of the # repository code at any time. load("@container_structure_test//:defs.bzl", "container_structure_test") load("//private/oci:defs.bzl", "java_image") package(default_visibility = ["//visibility:public"]) JAVA_VERSIONS_PER_DISTRO = [ ("17", "debian13"), ] [ java_image( name = "hello_java" + java_version + "_" + user + "_" + distro, srcs = ["HelloJava.java"], base = "//java:java" + java_version + "_" + user + "_amd64" + "_" + distro, main_class = "examples.HelloJava", ) for user in [ "root", "nonroot", ] for java_version, distro in JAVA_VERSIONS_PER_DISTRO ] [ container_structure_test( name = "hello_java" + java_version + "_" + user + "_" + distro + "_test", size = "small", configs = ["testdata/hello_" + user + "_" + distro + ".yaml"], image = ":hello_java" + java_version + "_" + user + "_" + distro, tags = [ "amd64", "manual", ], ) for user in [ "root", "nonroot", ] for java_version, distro in JAVA_VERSIONS_PER_DISTRO ] ================================================ FILE: examples/java/Dockerfile ================================================ FROM eclipse-temurin:17-jdk AS build-env COPY . /app/examples WORKDIR /app RUN javac examples/*.java RUN jar cfe main.jar examples.HelloJava examples/*.class FROM gcr.io/distroless/java17-debian13 COPY --from=build-env /app /app WORKDIR /app CMD ["main.jar"] ================================================ FILE: examples/java/HelloJava.java ================================================ package examples; public class HelloJava { public static void main(String[] args) { System.out.println("Hello world"); } } ================================================ FILE: examples/java/testdata/hello_nonroot_debian13.yaml ================================================ schemaVersion: "1.0.0" commandTests: - name: hello command: ['/usr/bin/java', '-cp', '/*', 'examples.HelloJava'] expectedOutput: ['Hello world'] ================================================ FILE: examples/java/testdata/hello_root_debian13.yaml ================================================ schemaVersion: "1.0.0" commandTests: - name: hello command: ['/usr/bin/java', '-cp', '/*', 'examples.HelloJava'] expectedOutput: ['Hello world'] ================================================ FILE: examples/nodejs/BUILD ================================================ # Public notice: this file is for internal documentation, testing, and # reference only. Note that repo maintainers can freely change any part of the # repository code at any time. load("@container_structure_test//:defs.bzl", "container_structure_test") load("@rules_oci//oci:defs.bzl", "oci_image") load("//private/util:tar.bzl", "tar") package(default_visibility = ["//visibility:public"]) ARCHITECTURES = [ "amd64", "arm64", ] DISTROS = [ "debian13", ] # These examples are adapted from: # https://howtonode.org/hello-node tar( name = "hello_tar", srcs = [ "hello.js", ], ) tar( name = "hello_http_tar", srcs = [ "hello_http.js", ], ) [ oci_image( name = "hello_" + user + "_" + arch + "_" + distro, base = "//nodejs:nodejs22_" + user + "_" + arch + "_" + distro, cmd = ["hello.js"], tars = [":hello_tar"], ) for user in [ "root", "nonroot", ] for arch in ARCHITECTURES for distro in DISTROS ] [ oci_image( name = "hello_http_" + user + "_" + arch + "_" + distro, base = "//nodejs:nodejs22_" + user + "_" + arch + "_" + distro, cmd = ["hello_http.js"], tars = [":hello_http_tar"], ) for user in [ "root", "nonroot", ] for arch in ARCHITECTURES for distro in DISTROS ] [ container_structure_test( name = "hello_" + user + "_" + arch + "_" + distro + "_test", configs = ["testdata/hello.yaml"], image = ":hello_" + user + "_" + arch + "_" + distro, tags = [ arch, "manual", ], ) for user in [ "root", "nonroot", ] for arch in ARCHITECTURES for distro in DISTROS ] ================================================ FILE: examples/nodejs/Dockerfile ================================================ FROM node:22 AS build-env COPY . /app WORKDIR /app RUN npm ci --omit=dev FROM gcr.io/distroless/nodejs22-debian13 COPY --from=build-env /app /app WORKDIR /app CMD ["hello.js"] ================================================ FILE: examples/nodejs/hello.js ================================================ console.log("Hello World"); ================================================ FILE: examples/nodejs/hello_http.js ================================================ // Load the http module to create an http server. var http = require('http'); // Configure our HTTP server to respond with Hello World to all requests. var server = http.createServer(function (request, response) { response.writeHead(200, {"Content-Type": "text/plain"}); response.end("Hello World\n"); }); // Listen on port 8000, IP defaults to 127.0.0.1 server.listen(8000); // Put a friendly message on the terminal console.log("Server running at http://127.0.0.1:8000/"); ================================================ FILE: examples/nodejs/node-express/Dockerfile ================================================ FROM node:22 AS build-env ADD . /app WORKDIR /app RUN npm install --omit=dev FROM gcr.io/distroless/nodejs22-debian13 COPY --from=build-env /app /app WORKDIR /app EXPOSE 3000 CMD ["hello_express.js"] ================================================ FILE: examples/nodejs/node-express/hello_express.js ================================================ const express = require('express') const app = express() const port = 3000 app.get('/', (req, res) => res.send('Hello World!')) app.listen(port, () => console.log(`Example app listening on port ${port}!`)) ================================================ FILE: examples/nodejs/node-express/package.json ================================================ { "name": "distroless-express", "version": "1.0.0", "description": "Distroless express node.js", "repository": { "type": "git", "url": "https://github.com/GoogleContainerTools/distroless.git" }, "dependencies": { "express": "4.20.0" }, "author": "Bryant Hagadorn", "license": "ISC" } ================================================ FILE: examples/nodejs/package.json ================================================ { "name": "nodejs", "version": "1.0.0", "description": "Example", "main": "hello.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC" } ================================================ FILE: examples/nodejs/testdata/hello.yaml ================================================ schemaVersion: "1.0.0" commandTests: - name: hello command: ["/nodejs/bin/node", "/hello.js"] expectedOutput: ['Hello World'] ================================================ FILE: examples/nonroot/BUILD ================================================ # Public notice: this file is for internal documentation, testing, and # reference only. Note that repo maintainers can freely change any part of the # repository code at any time. load("@container_structure_test//:defs.bzl", "container_structure_test") load("@rules_distroless//distroless:defs.bzl", "home", "passwd") load("@rules_go//go:def.bzl", "go_binary") load("@rules_oci//oci:defs.bzl", "oci_image") load("//:distro.bzl", DISTROS = "ALL_DISTROS") load("//private/util:tar.bzl", "tar") # Create a passwd file and home directory with a nonroot user and uid. passwd( name = "passwd", entries = [ { "gecos": ["nonroot"], "gid": 1000, "home": "/home", "shell": "/bin/bash", "uid": 1002, "username": "nonroot", }, ], ) home( name = "home", dirs = [ { "home": "/home", "uid": 1002, "gid": 1000, }, ], ) # Include it in our image as a tar. oci_image( name = "passwd_image", base = "//base:base_root_amd64_debian12", tars = [ ":passwd", ":home", ], user = "nonroot", visibility = ["//visibility:private"], ) # Simple go program to print out the username and uid. go_binary( name = "user", srcs = ["testdata/user.go"], goarch = "amd64", # Test image is linux based goos = "linux", pure = "on", ) tar( name = "user_tar", srcs = [":user"], ) [oci_image( name = "check_user_image_" + distro, base = ":passwd_image", tars = [":user_tar"], visibility = ["//visibility:private"], ) for distro in DISTROS] # Test to verify this works :) [container_structure_test( name = "check_user_" + distro + "_test", configs = ["testdata/user.yaml"], image = ":check_user_image_" + distro, tags = [ "amd64", "manual", ], visibility = ["//visibility:private"], ) for distro in DISTROS] ================================================ FILE: examples/nonroot/testdata/user.go ================================================ // Copyright 2017 Google Inc. All rights reserved. // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package main import ( "fmt" "io/ioutil" "os" "strconv" "strings" ) func main() { // We can't use user.Current here because it requires cgo. uid := strconv.Itoa(os.Getuid()) passwd, err := ioutil.ReadFile("/etc/passwd") if err != nil { fmt.Printf("Error reading /etc/passwd: %v", err) return } for _, line := range strings.Split(string(passwd), "\n") { if len(line) == 0 { continue } entries := strings.Split(line, ":") name, id := entries[0], entries[2] if id == uid { fmt.Println("User:", name) fmt.Println("Uid:", id) return } } } ================================================ FILE: examples/nonroot/testdata/user.yaml ================================================ schemaVersion: "1.0.0" commandTests: - name: user command: ['/user'] expectedOutput: ['User: nonroot', 'Uid: 1002'] ================================================ FILE: examples/python3/BUILD ================================================ # Public notice: this file is for internal documentation, testing, and # reference only. Note that repo maintainers can freely change any part of the # repository code at any time. load("@rules_oci//oci:defs.bzl", "oci_image", "oci_load") load("//private/util:tar.bzl", "tar") load("//python3:config.bzl", DISTROS = "PYTHON_DISTROS") tar( name = "hello_py", srcs = ["hello.py"], ) # This example runs a python program that walks the filesystem under "/etc" and prints every filename. [ oci_image( name = "hello_" + distro, base = "//python3:python3_root_amd64_" + distro, cmd = [ "hello.py", "/etc", ], tars = [ ":hello_py", ], ) for distro in DISTROS ] # Run # bazel run //examples/python3:tarball_debian12 # podman run localhost/distroless/examples/py:latest [ oci_load( name = "tarball_" + distro, image = ":hello_" + distro, repo_tags = ["distroless/examples/py:latest"], ) for distro in DISTROS ] ================================================ FILE: examples/python3/Dockerfile ================================================ FROM python:3-slim AS build-env COPY . /app WORKDIR /app FROM gcr.io/distroless/python3 COPY --from=build-env /app /app WORKDIR /app CMD ["hello.py", "/etc"] ================================================ FILE: examples/python3/hello.py ================================================ #!/bin/python # Copyright 2017 Google Inc. All rights reserved. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import argparse import os parser = argparse.ArgumentParser() parser.add_argument('root', type=str, help='The root directory to walk.') def main(args): """Prints the files that are inside the container, rooted at the first argument.""" for dirpath, _, files in os.walk(args.root): for f in files: print(os.path.join(dirpath, f)) if __name__ == "__main__": main(parser.parse_args()) ================================================ FILE: examples/python3-requirements/Dockerfile ================================================ # Build a virtualenv using the appropriate Debian release # * Install python3-venv for the built-in Python3 venv module (not installed by default) # * Install gcc libpython3-dev to compile C Python modules # * In the virtualenv: Update pip setuputils and wheel to support building new packages FROM debian:12-slim AS build RUN apt-get update && \ apt-get install --no-install-suggests --no-install-recommends --yes python3-venv gcc libpython3-dev && \ python3 -m venv /venv && \ /venv/bin/pip install --upgrade pip setuptools wheel # Build the virtualenv as a separate step: Only re-execute this step when requirements.txt changes FROM build AS build-venv COPY requirements.txt /requirements.txt RUN /venv/bin/pip install --disable-pip-version-check -r /requirements.txt # Copy the virtualenv into a distroless image FROM gcr.io/distroless/python3-debian12 COPY --from=build-venv /venv /venv COPY . /app WORKDIR /app ENTRYPOINT ["/venv/bin/python3", "psutil_example.py"] ================================================ FILE: examples/python3-requirements/README.md ================================================ # Python 3 with requirements.txt This is a Python 3 application that specifies third-party dependencies using requirements.txt. The psutil module it uses is a C module that must be compiled. This is the most annoying kind of dependency, since you need to build it in an environment where the C library and Python version match where it will run. It builds the final container in three stages: 1. `build`: Set up a Debian build environment that can compile Python C modules. 2. `build-venv`: Create a virtualenv using `requirements.txt`. 3. Output: Copy the venv and the code and build the final image. The first step is only re-executed if you edit `Dockerfile`. The second step is only re-executed if you change requirements.txt. The final step is very fast and will change on every code edit. ## Build and run 1. Build the image: `docker build . --tag=psutil-example` 2. Run it! `docker run --rm psutil-example` ## Example output ``` RSS: 13.0 MiB; SHARED: 5.7 MiB; VIRTUAL: 19.9 MiB ``` ## TODO: Bazel It would be nice if we could show how to build this container with Bazel, but I don't actually know how to do that. ================================================ FILE: examples/python3-requirements/psutil_example.py ================================================ #!/usr/bin/env python3 # Distroless's test.sh runs pylint on all python files, but this module will not exist # pylint: disable=import-error import psutil def mib(total_bytes): '''Converts bytes to MiB (float).''' return total_bytes / 1024 / 1024 def main(): current_process = psutil.Process() memory = current_process.memory_info() print(f'RSS: {mib(memory.rss):.1f} MiB; SHARED: {mib(memory.shared):.1f} MiB; VIRTUAL: {mib(memory.vms):.1f} MiB') if __name__ == '__main__': main() ================================================ FILE: examples/python3-requirements/requirements.txt ================================================ # this version of psutil does not ship binary wheels: must be compiled psutil==5.6.6 ================================================ FILE: examples/rust/.dockerignore ================================================ .git/ target/ ================================================ FILE: examples/rust/BUILD ================================================ # Public notice: this file is for internal documentation, testing, and # reference only. Note that repo maintainers can freely change any part of the # repository code at any time. # Rust load("//private/oci:defs.bzl", "rust_image") package(default_visibility = ["//visibility:public"]) # NOTE: Bazel Rust rules don't support cross-compilation yet, # so at this time it's required that you build on the same platform as the image rust_image( name = "rust_example", srcs = ["src/main.rs"], base = "//cc:cc_root_amd64_debian12", tags = [ "amd64", "manual", ], ) ================================================ FILE: examples/rust/Cargo.toml ================================================ [package] name = "hello-world-distroless" version = "0.1.0" authors = ["Bryant Hagadorn "] [dependencies] ================================================ FILE: examples/rust/Dockerfile ================================================ FROM rust:1 as build-env WORKDIR /app COPY . /app RUN cargo build --release FROM gcr.io/distroless/cc-debian12 COPY --from=build-env /app/target/release/hello-world-distroless / CMD ["./hello-world-distroless"] ================================================ FILE: examples/rust/src/main.rs ================================================ fn main() { println!("Hello World!"); } ================================================ FILE: examples/test.sh ================================================ #!/usr/bin/env bash set -euo pipefail for d in examples/*; do # Skip non-directories. if [[ ! -d "$d" ]]; then continue; fi # Skip if the directory doesn't have a Dockerfile. if [[ ! -f $d/Dockerfile ]]; then continue; fi # Skip these non-working examples. if [[ $d == "examples/cc" ]]; then continue; fi # Build the Dockerfile and run the image, or fail. echo ==================================== echo = building $d echo ==================================== docker build -t $d ./$d/ docker run $d done ================================================ FILE: experimental/BUILD ================================================ ================================================ FILE: experimental/busybox/BUILD ================================================ load("//:distro.bzl", BUSYBOX_ARCHITECTURES = "ALL_ARCHITECTURES") load(":commands.bzl", "busybox_layer") package(default_visibility = ["//static:__subpackages__"]) [ busybox_layer( name = "busybox_" + arch, busybox = "@busybox_" + arch + "//:file", compress = "gzip", ) for arch in BUSYBOX_ARCHITECTURES ] ================================================ FILE: experimental/busybox/commands.bzl ================================================ load("@aspect_bazel_lib//lib:tar.bzl", "tar") BUSYBOX_COMMANDS = [ "[", "[[", "acpid", "add-shell", "addgroup", "adduser", "adjtimex", "ar", "arp", "arping", "ash", "awk", "base64", "basename", "blkdiscard", "blkid", "blockdev", "bootchartd", "brctl", "bunzip2", "bzcat", "bzip2", "cal", "cat", "chat", "chattr", "chgrp", "chmod", "chown", "chpasswd", "chpst", "chroot", "chrt", "chvt", "cksum", "clear", "cmp", "comm", "conspy", "cp", "cpio", "crond", "crontab", "cryptpw", "cttyhack", "cut", "date", "dc", "dd", "deallocvt", "delgroup", "deluser", "depmod", "devmem", "df", "dhcprelay", "diff", "dirname", "dmesg", "dnsd", "dnsdomainname", "dos2unix", "dpkg", "dpkg-deb", "du", "dumpkmap", "dumpleases", "echo", "ed", "egrep", "eject", "env", "envdir", "envuidgid", "expand", "expr", "factor", "fakeidentd", "false", "fatattr", "fbset", "fbsplash", "fdflush", "fdformat", "fdisk", "fgconsole", "fgrep", "find", "findfs", "flash_eraseall", "flash_lock", "flash_unlock", "flashcp", "flock", "fold", "free", "freeramdisk", "fsck", "fsck.minix", "fsfreeze", "fstrim", "fsync", "ftpd", "ftpget", "ftpput", "fuser", "getopt", "getty", "grep", "groups", "gunzip", "gzip", "halt", "hd", "hdparm", "head", "hexdump", "hostid", "hostname", "httpd", "hush", "hwclock", "i2cdetect", "i2cdump", "i2cget", "i2cset", "id", "ifconfig", "ifenslave", "ifplugd", "inetd", "init", "inotifyd", "insmod", "install", "ionice", "iostat", "ip", "ipaddr", "ipcalc", "ipcrm", "ipcs", "iplink", "ipneigh", "iproute", "iprule", "iptunnel", "kbd_mode", "kill", "killall", "killall5", "klogd", "last", "less", "link", "linux32", "linux64", "linuxrc", "ln", "loadfont", "loadkmap", "logger", "login", "logname", "losetup", "lpd", "lpq", "lpr", "ls", "lsattr", "lsmod", "lsof", "lspci", "lsscsi", "lsusb", "lzcat", "lzma", "lzop", "lzopcat", "makedevs", "makemime", "man", "md5sum", "mdev", "mesg", "microcom", "mkdir", "mkdosfs", "mke2fs", "mkfifo", "mkfs.ext2", "mkfs.minix", "mkfs.vfat", "mknod", "mkpasswd", "mkswap", "mktemp", "modinfo", "modprobe", "more", "mount", "mountpoint", "mpstat", "mt", "mv", "nameif", "nbd-client", "nc", "netstat", "nice", "nl", "nmeter", "nohup", "nproc", "ntpd", "od", "openvt", "partprobe", "passwd", "paste", "patch", "pgrep", "pidof", "ping", "ping6", "pipe_progress", "pivot_root", "pkill", "pmap", "popmaildir", "poweroff", "powertop", "printenv", "printf", "ps", "pscan", "pstree", "pwd", "pwdx", "raidautorun", "rdate", "rdev", "readlink", "readprofile", "realpath", "reboot", "reformime", "remove-shell", "renice", "reset", "resize", "rev", "rm", "rmdir", "rmmod", "route", "rpm", "rpm2cpio", "rtcwake", "run-parts", "runlevel", "runsv", "runsvdir", "rx", "script", "scriptreplay", "sed", "sendmail", "seq", "setarch", "setconsole", "setfont", "setkeycodes", "setlogcons", "setpriv", "setserial", "setsid", "setuidgid", "sh", "sha1sum", "sha256sum", "sha3sum", "sha512sum", "showkey", "shred", "shuf", "slattach", "sleep", "smemcap", "softlimit", "sort", "split", "ssl_client", "start-stop-daemon", "stat", "strings", "stty", "su", "sulogin", "sum", "sv", "svc", "svlogd", "swapoff", "swapon", "switch_root", "sync", "sysctl", "syslogd", "tac", "tail", "tar", "taskset", "tcpsvd", "tee", "telnet", "telnetd", "test", "tftp", "tftpd", "time", "timeout", "top", "touch", "tr", "traceroute", "traceroute6", "true", "truncate", "tty", "ttysize", "tunctl", "tune2fs", "ubiattach", "ubidetach", "ubimkvol", "ubirename", "ubirmvol", "ubirsvol", "ubiupdatevol", "udhcpc", "udhcpd", "udpsvd", "uevent", "umount", "uname", "uncompress", "unexpand", "uniq", "unix2dos", "unlink", "unlzma", "unlzop", "unxz", "unzip", "uptime", "users", "usleep", "uudecode", "uuencode", "vconfig", "vi", "vlock", "volname", "w", "wall", "watch", "watchdog", "wc", "wget", "which", "who", "whoami", "whois", "xargs", "xxd", "xz", "xzcat", "yes", "zcat", "zcip", ] BUSYBOX_ARCHIVE_BUILD = """\ filegroup( name = "file", srcs = ["bin/busybox"], visibility = ["//visibility:public"] ) """ def busybox_layer(busybox, **kwargs): tar( srcs = [busybox], mtree = [ "./busybox/ uid=0 gid=0 mode=0755 time=0.0 type=dir", "./busybox/busybox uid=0 gid=0 mode=0755 time=0.0 type=file content=$(location {})".format(busybox), ] + [ "./busybox/{cmd} uid=0 gid=0 mode=0755 time=0.0 type=link link=/busybox/busybox".format(cmd = cmd) for cmd in BUSYBOX_COMMANDS ], **kwargs ) ================================================ FILE: java/BUILD ================================================ load(":config.bzl", "JAVA_ARCHITECTURES", "JAVA_BASE_PACKAGES", "JAVA_DISTROS") load(":java.bzl", "java_base_image", "java_base_image_index", "java_image", "java_image_index") package(default_visibility = ["//visibility:public"]) # publishable java base images [ java_base_image( distro, arch, JAVA_BASE_PACKAGES[distro], ) for distro in JAVA_DISTROS for arch in JAVA_ARCHITECTURES[distro] ] [ java_base_image_index( distro, JAVA_ARCHITECTURES[distro], ) for distro in JAVA_DISTROS ] # publishable java temurin images from adoptium deb repository ADOPTIUM_DEB_PER_DISTRO = [ ("17", "debian13"), ("21", "debian13"), ("25", "debian13"), ] [ java_image(distro, java_version, arch) for java_version, distro in ADOPTIUM_DEB_PER_DISTRO for arch in JAVA_ARCHITECTURES[distro] ] # all image indexes [ java_image_index( distro, java_version, JAVA_ARCHITECTURES[distro], ) for java_version, distro in ADOPTIUM_DEB_PER_DISTRO ] ================================================ FILE: java/README.md ================================================ # Documentation for `gcr.io/distroless/java` ## Image Contents This image contains a minimal Linux, OpenJDK-based runtime. Specifically, the image contains everything in the [base image](../base/README.md), plus: * Temurin OpenJDK 17 (`gcr.io/distroless/java17-debian13`) and its dependencies. * Temurin OpenJDK 21 (`gcr.io/distroless/java21-debian13`) and its dependencies * Temurin OpenJDK 25 (`gcr.io/distroless/java25-debian13`) and its dependencies ## Usage The entrypoint of this image is set to the equivalent of "java -jar", so this image expects users to supply a path to a JAR file in the CMD. ## Add another JAVA version To support a new JAVA version you need to do the following steps: - Add the new version to `ADOPTIUM_DEB_PER_DISTRO` in [java/BUILD](BUILD). - Add the new version to `JAVA_MAJOR_VERSIONS` in [java/config.bzl](config.bzl). - Add two yaml files in the [java/testdata](testdata) folder to prepare the tests, you can take inspiration on the other files. You can then ensure everything works on this folder with `bazel build //java:...` ================================================ FILE: java/config.bzl ================================================ JAVA_DISTROS = ["debian13"] JAVA_ARCHITECTURES = { "debian13": ["amd64", "arm64", "s390x", "ppc64le", "riscv64"], } JAVA_MAJOR_VERSIONS = { "debian13": ["17", "21", "25"], } JAVA_BASE_PACKAGES = { # debian 13 - temurin ships with libharfbuzz already "debian13": [ "zlib1g", "libjpeg62-turbo", "liblcms2-2", "libfreetype6", "fonts-dejavu-core", "fontconfig-config", "libexpat1", "libfontconfig1", "libuuid1", "libbrotli1", "libcrypt1", "libstdc++6", "libgcc-s1", "gcc-14-base", "libpng16-16t64", "libbz2-1.0", ], } ================================================ FILE: java/control ================================================ Package: Eclipse Temurin Version: {{VERSION}} Architecture: {{ARCHITECTURE}} Maintainer: Adoptium Working Group Homepage: https://adoptium.net SHA256: {{SHA256}} Description: Eclipse Temurin is the name of the OpenJDK distribution from Adoptium. ================================================ FILE: java/java.bzl ================================================ "java image definitions" load("@container_structure_test//:defs.bzl", "container_structure_test") load("@rules_oci//oci:defs.bzl", "oci_image", "oci_image_index") load("//common:variables.bzl", "DEBUG_MODE", "USERS") load("//java:jre_ver.bzl", "jre_ver") load("//private/oci:defs.bzl", oci_java_image = "java_image") load("//private/util:deb.bzl", "deb") load("//private/util:java_cacerts.bzl", "java_cacerts") load("//private/util:tar.bzl", "tar") def ca_certs(distro, arch): """java ca certs for a specific arch and distro """ if native.existing_rule("cacerts_java_" + arch + "_" + distro): return java_cacerts( name = "cacerts_java_" + arch + "_" + distro, archive = "//common:cacerts_" + distro + "_" + arch, ) def java_base_image_index(distro, architectures): """java base image index for a distro Args: distro: name of distribution architectures: all architectures included in index """ for mode in DEBUG_MODE: for user in USERS: oci_image_index( name = "java_base" + mode + "_" + user + "_" + distro, images = [ "java_base" + mode + "_" + user + "_" + arch + "_" + distro for arch in architectures ], ) def java_base_image(distro, arch, packages): """java base for a distro/arch Args: distro: name of distribution arch: the target arch packages: to add to the image (from a debianX_java repo) """ # pre-req ca_certs(distro, arch) for mode in DEBUG_MODE: for user in USERS: oci_image( name = "java_base" + mode + "_" + user + "_" + arch + "_" + distro, base = "//base:base_nossl" + mode + "_" + user + "_" + arch + "_" + distro, env = {"LANG": "C.UTF-8"}, tars = [ deb.package(arch, distro, pkg, "java") for pkg in packages ] + [ "//common:locale_" + distro + "_" + arch, ":cacerts_java_" + arch + "_" + distro, ], ) for mode in DEBUG_MODE: for user in USERS: container_structure_test( name = "java_base" + mode + "_" + user + "_" + arch + "_" + distro + "_test", configs = ["testdata/java_base" + mode + ".yaml"], image = ":java_base" + mode + "_" + user + "_" + arch + "_" + distro, tags = [ arch, "manual", ], ) def java_image_index(distro, java_version, architectures): """java and debug image indexes (applies to all java_image builds) Args: distro: name of distribution java_version: version of java architectures: all architectures included in index """ for user in USERS: for mode in DEBUG_MODE: oci_image_index( name = "java" + java_version + mode + "_" + user + "_" + distro, images = [ "java" + java_version + mode + "_" + user + "_" + arch + "_" + distro for arch in architectures ], ) def java_image(distro, java_version, arch): """java images from adoptium temurin deb distribution Args: distro: name of distribution java_version: version of java arch: the target arch """ # intermediary rule to configure jre symlinks tar( name = "temurin_" + java_version + "_jre_" + arch + "_" + distro, extension = "tar.gz", symlinks = { "/usr/bin/java": "/usr/lib/jvm/temurin-" + java_version + "-jre-" + arch + "/bin/java", "/etc/ssl/certs/adoptium/cacerts": "/etc/ssl/certs/java/cacerts", }, deps = [ deb.package( arch, distro, "temurin-" + java_version + "-jre", "adoptium", ), ], ) # intermediary rules to configure jdk symlinks tar( name = "temurin_" + java_version + "_jdk_" + arch + "_" + distro, extension = "tar.gz", symlinks = { "/usr/bin/java": "/usr/lib/jvm/temurin-" + java_version + "-jdk-" + arch + "/bin/java", "/etc/ssl/certs/adoptium/cacerts": "/etc/ssl/certs/java/cacerts", }, deps = [ deb.package( arch, distro, "temurin-" + java_version + "-jdk", "adoptium", ), ], ) # standard image builds for user in USERS: oci_image( name = "java" + java_version + "_" + user + "_" + arch + "_" + distro, base = ":java_base_" + user + "_" + arch + "_" + distro, # We expect users to use: # cmd = ["/path/to/deploy.jar", "--option1", ...] entrypoint = [ "/usr/bin/java", "-jar", ], env = { "JAVA_VERSION": jre_ver(deb.version( arch, distro, "temurin-" + java_version + "-jre", "adoptium", )), }, tars = [ # we use system certs, but we might want to pull this out of the distro # like we did for the github released temurin ":temurin_" + java_version + "_jre_" + arch + "_" + distro, ], ) # debug image builds for user in USERS: oci_image( name = "java" + java_version + "_debug_" + user + "_" + arch + "_" + distro, base = ":java_base_debug_" + user + "_" + arch + "_" + distro, # We expect users to use: # cmd = ["/path/to/deploy.jar", "--option1", ...] entrypoint = [ "/usr/bin/java", "-jar", ], env = { "JAVA_VERSION": jre_ver(deb.version( arch, distro, "temurin-" + java_version + "-jdk", "adoptium", )), }, tars = [ # we use system certs, but we might want to pull this out of the distro # like we did for the github released temurin ":cacerts_java_" + arch + "_" + distro, ":temurin_" + java_version + "_jdk_" + arch + "_" + distro, ], ) java_tests(distro, java_version, arch) def java_tests(distro, java_version, arch): """Tests for java images. Args: distro: name of distribution java_version: version of java arch: the target arch """ for user in USERS: container_structure_test( name = "java" + java_version + "_" + user + "_" + arch + "_" + distro + "_test", configs = ["testdata/java" + java_version + "_" + distro + ".yaml"], image = ":java" + java_version + "_" + user + "_" + arch + "_" + distro, tags = [ arch, "manual", ], ) for user in USERS: container_structure_test( name = "java" + java_version + "_debug_" + user + "_" + arch + "_" + distro + "_test", configs = ["testdata/java" + java_version + "_debug" + "_" + distro + ".yaml"], image = ":java" + java_version + "_debug_" + user + "_" + arch + "_" + distro, tags = [ arch, "manual", ], ) if arch == "amd64": for user in USERS: oci_java_image( name = "check_certs_java" + java_version + "_" + user + "_" + distro, srcs = ["testdata/CheckCerts.java"], base = "//java:java" + java_version + "_" + user + "_amd64_" + distro, main_class = "testdata.CheckCerts", ) for user in USERS: container_structure_test( name = "check_certs_java" + java_version + "_" + user + "_" + distro + "_test", configs = ["testdata/java_certs.yaml"], image = ":check_certs_java" + java_version + "_" + user + "_" + distro, tags = [ "amd64", "manual", ], ) for user in USERS: oci_java_image( name = "check_encoding_java" + java_version + "_" + user + "_" + distro, srcs = ["testdata/CheckEncoding.java"], base = "//java:java" + java_version + "_" + user + "_amd64_" + distro, main_class = "testdata.CheckEncoding", ) for user in USERS: container_structure_test( name = "check_encoding_java" + java_version + "_" + user + "_" + distro + "_test", configs = ["testdata/java_encoding.yaml"], image = ":check_encoding_java" + java_version + "_" + user + "_" + distro, tags = [ "amd64", "manual", ], ) for user in USERS: oci_java_image( name = "check_libharfbuzz_java" + java_version + "_" + user + "_" + distro, srcs = ["testdata/CheckLibharfbuzz.java"], base = "//java:java" + java_version + "_" + user + "_amd64_" + distro, main_class = "testdata.CheckLibharfbuzz", ) for user in USERS: container_structure_test( name = "check_libharfbuzz_java" + java_version + "_" + user + "_" + distro + "_test", configs = ["testdata/java_libharfbuzz.yaml"], image = ":check_libharfbuzz_java" + java_version + "_" + user + "_" + distro, tags = [ "amd64", "manual", ], ) ================================================ FILE: java/jre_ver.bzl ================================================ def jre_ver(version): """Extract JRE version from a Debian openjdk downloaded filename. Debian packages versions are of the form: openjdk-11-jre*: 11.0.1+13-2~bpo9+1 """ if version.startswith("11.") or version.startswith("17.") or version.startswith("21.") or version.startswith("25."): v = version.split("+")[0].split(".") return v[0] + "." + v[1] + "." + v[2] fail("unrecognized openjdk package version: " + version) ================================================ FILE: java/testdata/CheckCerts.java ================================================ package testdata; import java.io.IOException; import java.net.URL; import javax.net.ssl.HttpsURLConnection; public class CheckCerts { public static void main(String[] args) throws IOException { URL url = new URL("https://www.google.com/"); HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(); conn.connect(); conn.getServerCertificates(); // succeeds if peer verified System.out.println("Successfully connected: " + conn.getResponseCode()); } } ================================================ FILE: java/testdata/CheckEncoding.java ================================================ package testdata; import java.nio.charset.Charset; import java.util.Locale; public class CheckEncoding { public static void main(String[] args) { System.out.println("LANG=" + System.getenv("LANG")); System.out.println("Locale.getDefault()=" + Locale.getDefault()); System.out.println("Charset.defaultCharset()=" + Charset.defaultCharset()); System.out.println("file.encoding=" + System.getProperty("file.encoding")); System.out.println("sun.jnu.encoding=" + System.getProperty("sun.jnu.encoding")); } } ================================================ FILE: java/testdata/CheckLibharfbuzz.java ================================================ package testdata; import java.awt.GraphicsEnvironment; import java.awt.Font; public class CheckLibharfbuzz { public static void main(String[] args) { GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment(); Font [] fonts = env.getAllFonts(); if ( fonts.length > 0 ) { System.out.println(fonts.length + " fonts available"); } } } ================================================ FILE: java/testdata/java17_debian13.yaml ================================================ schemaVersion: "2.0.0" commandTests: - name: java command: "/usr/lib/jvm/temurin-17-jre-amd64/bin/java" args: ["-version"] expectedError: ['openjdk version "17.0.18'] - name: java-symlink command: "/usr/bin/java" args: ["-version"] expectedError: ['openjdk version "17.0.18'] fileExistenceTests: - name: certs path: "/etc/ssl/certs/java/cacerts" shouldExist: true - name: certs path: "/etc/ssl/certs/adoptium/cacerts" permissions: 'Lrwxrwxrwx' shouldExist: true - name: certs path: "/usr/lib/jvm/temurin-17-jre-amd64/lib/security/cacerts" permissions: 'Lrwxrwxrwx' shouldExist: true - name: no-busybox path: "/busybox/sh" shouldExist: false - name: no-shell path: "/bin/sh" shouldExist: false - name: no-javac path: "/usr/lib/jvm/temurin-17-jre-amd64/bin/javac" shouldExist: false - name: jexec-executable path: "/usr/lib/jvm/temurin-17-jre-amd64/lib/jexec" shouldExist: true isExecutableBy: "any" - name: jspawnhelper-executable path: "/usr/lib/jvm/temurin-17-jre-amd64/lib/jspawnhelper" shouldExist: true isExecutableBy: "any" metadataTest: envVars: - key: 'JAVA_VERSION' value: '17.0.18' ================================================ FILE: java/testdata/java17_debug_debian13.yaml ================================================ schemaVersion: "2.0.0" commandTests: - name: java command: "/usr/lib/jvm/temurin-17-jdk-amd64/bin/java" args: ["-version"] expectedError: ['openjdk version "17.0.18"'] - name: java-symlink command: "/usr/bin/java" args: ["-version"] expectedError: ['openjdk version "17.0.18"'] - name: javac command: "/usr/lib/jvm/temurin-17-jdk-amd64/bin/javac" args: ["-version"] expectedOutput: ['javac 17.0.18'] fileExistenceTests: - name: certs path: "/etc/ssl/certs/java/cacerts" shouldExist: true - name: certs path: "/etc/ssl/certs/adoptium/cacerts" permissions: 'Lrwxrwxrwx' shouldExist: true - name: certs path: "/usr/lib/jvm/temurin-17-jdk-amd64/lib/security/cacerts" permissions: 'Lrwxrwxrwx' shouldExist: true - name: busybox path: "/busybox/sh" shouldExist: true - name: no-shell path: "/bin/sh" shouldExist: false metadataTest: envVars: - key: 'JAVA_VERSION' value: '17.0.18' ================================================ FILE: java/testdata/java21_debian13.yaml ================================================ schemaVersion: "2.0.0" commandTests: - name: java command: "/usr/lib/jvm/temurin-21-jre-amd64/bin/java" args: ["-version"] expectedError: ['openjdk version "21.0.10"'] - name: java-symlink command: "/usr/bin/java" args: ["-version"] expectedError: ['openjdk version "21.0.10"'] fileExistenceTests: - name: certs path: "/etc/ssl/certs/java/cacerts" shouldExist: true - name: certs path: "/etc/ssl/certs/adoptium/cacerts" permissions: 'Lrwxrwxrwx' shouldExist: true - name: certs path: "/usr/lib/jvm/temurin-21-jre-amd64/lib/security/cacerts" permissions: 'Lrwxrwxrwx' shouldExist: true - name: no-busybox path: "/busybox/sh" shouldExist: false - name: no-shell path: "/bin/sh" shouldExist: false - name: no-javac path: "/usr/lib/jvm/temurin-21-jre-amd64/bin/javac" shouldExist: false - name: jexec-executable path: "/usr/lib/jvm/temurin-21-jre-amd64/lib/jexec" shouldExist: true isExecutableBy: "any" - name: jspawnhelper-executable path: "/usr/lib/jvm/temurin-21-jre-amd64/lib/jspawnhelper" shouldExist: true isExecutableBy: "any" metadataTest: envVars: - key: 'JAVA_VERSION' value: '21.0.10' ================================================ FILE: java/testdata/java21_debug_debian13.yaml ================================================ schemaVersion: "2.0.0" commandTests: - name: java command: "/usr/lib/jvm/temurin-21-jdk-amd64/bin/java" args: ["-version"] expectedError: ['openjdk version "21.0.10"'] - name: java-symlink command: "/usr/bin/java" args: ["-version"] expectedError: ['openjdk version "21.0.10"'] - name: javac command: "/usr/lib/jvm/temurin-21-jdk-amd64/bin/javac" args: ["-version"] expectedOutput: ['javac 21.0.10'] fileExistenceTests: - name: certs path: "/etc/ssl/certs/java/cacerts" shouldExist: true - name: certs path: "/etc/ssl/certs/adoptium/cacerts" permissions: 'Lrwxrwxrwx' shouldExist: true - name: certs path: "/usr/lib/jvm/temurin-21-jdk-amd64/lib/security/cacerts" permissions: 'Lrwxrwxrwx' shouldExist: true - name: busybox path: "/busybox/sh" shouldExist: true - name: no-shell path: "/bin/sh" shouldExist: false metadataTest: envVars: - key: 'JAVA_VERSION' value: '21.0.10' ================================================ FILE: java/testdata/java25_debian13.yaml ================================================ schemaVersion: "2.0.0" commandTests: - name: java command: "/usr/lib/jvm/temurin-25-jre-amd64/bin/java" args: ["-version"] expectedError: ['openjdk version "25.0.2"'] - name: java-symlink command: "/usr/bin/java" args: ["-version"] expectedError: ['openjdk version "25.0.2"'] fileExistenceTests: - name: certs path: "/etc/ssl/certs/java/cacerts" shouldExist: true - name: certs path: "/etc/ssl/certs/adoptium/cacerts" permissions: 'Lrwxrwxrwx' shouldExist: true - name: certs path: "/usr/lib/jvm/temurin-25-jre-amd64/lib/security/cacerts" permissions: 'Lrwxrwxrwx' shouldExist: true - name: no-busybox path: "/busybox/sh" shouldExist: false - name: no-shell path: "/bin/sh" shouldExist: false - name: no-javac path: "/usr/lib/jvm/temurin-25-jre-amd64/bin/javac" shouldExist: false - name: jexec-executable path: "/usr/lib/jvm/temurin-25-jre-amd64/lib/jexec" shouldExist: true isExecutableBy: "any" - name: jspawnhelper-executable path: "/usr/lib/jvm/temurin-25-jre-amd64/lib/jspawnhelper" shouldExist: true isExecutableBy: "any" metadataTest: envVars: - key: 'JAVA_VERSION' value: '25.0.2' ================================================ FILE: java/testdata/java25_debug_debian13.yaml ================================================ schemaVersion: "2.0.0" commandTests: - name: java command: "/usr/lib/jvm/temurin-25-jdk-amd64/bin/java" args: ["-version"] expectedError: ['openjdk version "25.0.2"'] - name: java-symlink command: "/usr/bin/java" args: ["-version"] expectedError: ['openjdk version "25.0.2"'] - name: javac command: "/usr/lib/jvm/temurin-25-jdk-amd64/bin/javac" args: ["-version"] expectedOutput: ['javac 25.0.2'] fileExistenceTests: - name: certs path: "/etc/ssl/certs/java/cacerts" shouldExist: true - name: certs path: "/etc/ssl/certs/adoptium/cacerts" permissions: 'Lrwxrwxrwx' shouldExist: true - name: certs path: "/usr/lib/jvm/temurin-25-jdk-amd64/lib/security/cacerts" permissions: 'Lrwxrwxrwx' shouldExist: true - name: busybox path: "/busybox/sh" shouldExist: true - name: no-shell path: "/bin/sh" shouldExist: false metadataTest: envVars: - key: 'JAVA_VERSION' value: '25.0.2' ================================================ FILE: java/testdata/java_base.yaml ================================================ schemaVersion: "2.0.0" fileExistenceTests: - name: certs path: "/etc/ssl/certs/java/cacerts" shouldExist: true - name: no-busybox path: "/busybox/sh" shouldExist: false - name: no-shell path: "/bin/sh" shouldExist: false - name: no-jvm path: "/usr/lib/jvm" shouldExist: false ================================================ FILE: java/testdata/java_base_debug.yaml ================================================ schemaVersion: "2.0.0" fileExistenceTests: - name: certs path: "/etc/ssl/certs/java/cacerts" shouldExist: true - name: busybox path: "/busybox/sh" shouldExist: true - name: no-shell path: "/bin/sh" shouldExist: false - name: no-jvm path: "/usr/lib/jvm" shouldExist: false ================================================ FILE: java/testdata/java_certs.yaml ================================================ schemaVersion: "1.0.0" commandTests: - name: connect_to_https_google_com # This is a bit ugly because structure tests can't test the default entrypoint yet. command: ["/usr/bin/java", "-cp", "/*", "testdata.CheckCerts"] expectedOutput: ['Successfully connected: 200'] ================================================ FILE: java/testdata/java_encoding.yaml ================================================ schemaVersion: "1.0.0" commandTests: - name: check_encoding command: ["/usr/bin/java", "-cp", "/*", "testdata.CheckEncoding"] expectedOutput: ['LANG=C.UTF-8', 'Locale.getDefault\(\)=en', 'Charset.defaultCharset\(\)=UTF-8', 'file.encoding=UTF-8', 'sun.jnu.encoding=UTF-8'] ================================================ FILE: java/testdata/java_libharfbuzz.yaml ================================================ schemaVersion: "1.0.0" commandTests: - name: check_libharfbuzz command: ["/usr/bin/java", "-cp", "/*", "testdata.CheckLibharfbuzz"] expectedOutput: ['^\d+ fonts available'] ================================================ FILE: knife ================================================ #!/usr/bin/env bash set -o pipefail -o errexit -o nounset # Copyright 2024 Google Inc. All rights reserved. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. source knife.d/update_java_versions.sh if [ $(uname) == "Darwin" ]; then echo "WARNING: You are on a macos, you need to run 'brew install coreutils gnu-sed' to install required packages." echo "" export PATH="/opt/homebrew/opt/coreutils/libexec/gnubin:$PATH" export PATH="/opt/homebrew/opt/gnu-sed/libexec/gnubin:$PATH" fi function cmd_lock_all() { cmd_lock_snapshots cmd_lock_non_snapshots } function cmd_lock_snapshots() { echo "🚧 Querying for snapshot repos" echo "" local repos=$(grep -l snapshot.debian.org ./private/repos/deb/*.yaml | xargs -L 1 basename | cut -d. -f 1) _cmd_lock "$repos" } function cmd_lock_non_snapshots() { echo "🚧 Querying for non_snapshot repos" echo "" local repos=$(grep -lL snapshot.debian.org ./private/repos/deb/*.yaml | xargs -L 1 basename | cut -d. -f 1) _cmd_lock "$repos" update_java_versions_debian13 } function _cmd_lock() { local repos="$1" for repo in $repos; do for i in $(seq 10); do echo "🔑 Locking $repo (attempt ${i})" bazel run "@${repo}//:lock" && break || sleep 20; if [[ $i -eq 10 ]]; then echo "" echo "Failed to lock $repo after 10 attempts" >&2 exit 1 fi done done } function find_latest_snapshot() { local type="$1" # If it's the first of the month, look at the last month, otherwise this -1 day has no effect since searches # occur at the "month" level. This is an intentional buffer added to get the snapshots fully hydrated. We # intentionally don't include complicated logic for the case where it's after the 1st and no snapshots are # availalbe for the month (it's extremely unlikely for our updater to run into this situation unless the # snapshot serving infrastructure is acting up). local current="$(date -d '-1 day' +%Y-%m-%d)" local tmp=$(mktemp) local q=$(date -d "$current" +"year=%Y&month=%m") if curl -fs "https://snapshot.debian.org/archive/debian/?$q" | grep -ohE "([0-9]+T[0-9]+Z)" > $tmp; then # same logic as above, find the newest snapshot that isn't "today" today=$(date +"%Y%m%dT") cat $tmp | grep -v $today | tail -n1 fi } function cmd_update_snapshots() { echo "🧐 Looking for updates... " latest=$(find_latest_snapshot "debian") latest_security=$(find_latest_snapshot "debian-security") if [[ -z "$latest" || -z "$latest_security" ]]; then echo "" echo "could not find any snapshots for debian or debian-security" exit 1 fi echo "" echo "🎯 Found snapshots" echo " debian: $latest" echo " security: $latest_security" echo "" # if tty ask for approval if [ -t 1 ]; then read -p "Do you want to continue? (y/n) " -n 1 -r sleep 0.5 echo $'\n' if [[ ! "$REPLY" =~ ^[Yy]$ ]]; then echo "Aborting..." exit 0 fi fi for mpath in "./private/repos/deb/"*.yaml; do if ! grep -q "snapshot.debian.org" "$mpath"; then echo "ignoring non-snapshot repo $mpath" continue fi current=$(grep -oE "debian/([0-9]+T[0-9]+Z)" $mpath | cut -d/ -f2 | head -n1) current_security=$(grep -oE "debian-security/([0-9]+T[0-9]+Z)" $mpath | cut -d/ -f2 | head -n1) if [[ "$current" == "$latest" && "$current_security" == "$latest_security" ]]; then echo "🎖️ $mpath is up to date." continue fi echo "🗞️ $mpath" if [[ "$current" != "$latest" ]]; then sed -i -E "s/(debian\/)([0-9]+T[0-9]+Z)/\1$latest/" "$mpath" echo " debian: $current -> $latest" fi if [[ "$current_security" != "$latest_security" ]]; then sed -i -E "s/(debian-security\/)([0-9]+T[0-9]+Z)/\1$latest_security/" "$mpath" echo " debian-security: $current_security -> $latest_security" fi echo "" done echo "" echo "👌 Done..." } # write DISTROLESS_DIFF to GITHUB_ENV if changes are made function cmd_github_update_snapshots() { local tmp=$(mktemp -d) jq -nr 'inputs.packages[] | .key + " " + .sha256' ./private/repos/deb/*.lock.json | sort > "$tmp/old.hashes" cmd_update_snapshots cmd_lock_snapshots jq -nr 'inputs.packages[] | .key + " " + .sha256' ./private/repos/deb/*.lock.json | sort > "$tmp/new.hashes" diff "$tmp/old.hashes" "$tmp/new.hashes" | tee "$tmp/diff" || printf "DISTROLESS_DIFF<> "$GITHUB_ENV" } function cmd_lint () { local mode="fix" if [[ "${1:-}" == "--check" ]]; then mode="check" fi echo "🧹 Linting" echo "" if ! which buildifier > /dev/null; then echo "🧱 No buildifier executable was found." echo " Did you follow the ./CONTRIBUTING.md ?" exit 1 fi buildifier -mode=$mode $(find . -type f \( -name 'BUILD*' -o -name 'WORKSPACE*' -o -name '*.bzl' \)) } function cmd_update_node_archives () { if ! which jq > /dev/null; then echo "🧱 No jq executable was found" exit 1 fi if ! which curl > /dev/null; then echo "🧱 No curl executable was found" exit 1 fi if ! which node > /dev/null; then echo "🧱 No node executable was found" exit 1 fi versions=() for major in 20 22 24; do latest_version=$(curl -sSL https://nodejs.org/dist/index.json | jq -r --arg major "v$major" ' map(select(.version | startswith($major))) | sort_by(.date) | reverse | .[0].version ') latest_nov=$(echo "$latest_version" | sed 's/^v//') versions+=("$latest_nov") done joined_versions=$(IFS=, ; echo "${versions[*]}") node knife.d/update_node_archives.js "$joined_versions" } function cmd_test () { echo "🧪 Testing" echo "" local arch=$(uname -m) if [ ${arch} == "x86_64" ]; then arch="amd64" fi echo "💡 only including image tests for $arch" echo "" arch_specific_targets=$(bazel query "attr(\"tags\", "$arch", \"//...\")") # Run all tests tagged with "amd64" bazel test --test_timeout=900 //... $arch_specific_targets } function cmd_deb_versions () { echo "🔧 Printing .deb Versions (bookworm) from private/repos/deb/bookworm*.lock.json" echo "" jq -n '[inputs.packages[]] | group_by(.arch) | map({(.[0].arch): map({package: .name, version: .version})})' private/repos/deb/bookworm*.lock.json } case "${1:-"~~nocmd"}" in lock) cmd_lock_all ;; update-snapshots) cmd_update_snapshots ;; update-non-snapshots) cmd_lock_non_snapshots ;; lint) cmd_lint "${@:2}" ;; github-update-snapshots) cmd_github_update_snapshots ;; test) cmd_test ;; deb-versions) cmd_deb_versions ;; update-node-archives) cmd_update_node_archives ;; ~~nocmd) # no command provided echo "provide a command: lock, update-snapshots, github-update-snapshots, update-non-snapshots, test, deb-versions, update-node-archives" exit 1 ;; *) # unknown command echo "unknown command $1" exit 1 ;; esac ================================================ FILE: knife.d/update_java_versions.sh ================================================ set -o pipefail -o errexit -o nounset # Copyright 2024 Google Inc. All rights reserved. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # a collection of functions to use when updating java archives from the knife utility function update_java_versions_debian13() { local java_versions=("17" "21" "25") for java_version in "${java_versions[@]}"; do local version=$(jq -r --arg jv "temurin-${java_version}-jre" '.packages.[] | select((.arch=="amd64") and (.name==$jv)) | .version | split(".") | .[0:3] | join(".")' private/repos/deb/trixie_adoptium.lock.json) local major_version=$(echo "$version" | cut -d. -f 1) sed -i -r -e "s/${major_version}\\.[0-9]+\\.[0-9]+/${version}/g" java/testdata/java${major_version}*debian13.yaml done } ================================================ FILE: knife.d/update_node_archives.js ================================================ #!/usr/bin/env node const crypto = require("crypto"); const https = require("https"); const fs = require("fs"); if (process.argv.length < 3) { console.error("Usage: node nodeChecksum.js "); process.exit(1); } const versions = process.argv[2].split(","); const architectures = ["amd64", "arm64", "arm", "ppc64le", "s390x"]; const nodeVersions = {}; const calculateChecksum = (url) => { return new Promise((resolve, reject) => { https .get(url, (res) => { const hash = crypto.createHash("sha256"); res.on("data", (data) => { hash.update(data); }); res.on("end", () => { resolve(hash.digest("hex")); }); }) .on("error", (err) => { reject(`Error downloading file: ${err.message}`); }); }); }; const fetchChecksums = async () => { for (const nodeVersion of versions) { const major = parseInt(nodeVersion.split(".")[0]); nodeVersions[nodeVersion] = {}; await Promise.all( architectures.map(async (key) => { let arch = key; if (major > 22 && key === "arm") { return; } if (key === "amd64") { arch = "x64"; } else if (key === "arm") { arch = "armv7l"; } const url = `https://nodejs.org/dist/v${nodeVersion}/node-v${nodeVersion}-linux-${arch}.tar.gz`; try { const checksum = await calculateChecksum(url); nodeVersions[nodeVersion][key] = { checksum, suffix: arch, }; } catch (error) { console.error(error); } }) ); } }; fetchChecksums().then(() => { let nodeArchives = `"node" BUILD_TMPL = """\\ # GENERATED BY node_archive.bzl load("@distroless//private/pkg:debian_spdx.bzl", "debian_spdx") load("@distroless//private/util:merge_providers.bzl", "merge_providers") load("@distroless//private/util:tar.bzl", "tar") tar( name = "data", extension = "tar.gz", srcs = glob( [ "output/bin/node", "output/LICENSE", ], ), package_dir = "/nodejs", strip_prefix = "external/{canonical_name}/output" ) tar( name = "_control", extension = "tar.gz", srcs = ["control"] ) debian_spdx( name = "spdx", control = ":_control", data = ":data", package_name = "{package_name}", spdx_id = "{spdx_id}", sha256 = "{sha256}", urls = [{urls}] ) merge_providers( name = "{name}", srcs = [":data", ":spdx"], visibility = ["//visibility:public"], ) """ def _impl(rctx): rctx.report_progress("Fetching {}".format(rctx.attr.package_name)) rctx.download_and_extract( url = rctx.attr.urls, sha256 = rctx.attr.sha256, type = rctx.attr.type, stripPrefix = rctx.attr.strip_prefix, output = "output", ) rctx.template( "control", rctx.attr.control, substitutions = { "{{VERSION}}": rctx.attr.version, "{{ARCHITECTURE}}": rctx.attr.architecture, "{{SHA256}}": rctx.attr.sha256, }, ) rctx.file( "BUILD.bazel", content = BUILD_TMPL.format( canonical_name = rctx.attr.name, name = rctx.attr.name.split("~")[-1], package_name = rctx.attr.package_name, spdx_id = rctx.attr.name, urls = ",".join(['"%s"' % url for url in rctx.attr.urls]), sha256 = rctx.attr.sha256, ), ) node_archive = repository_rule( implementation = _impl, attrs = { "urls": attr.string_list(mandatory = True), "sha256": attr.string(mandatory = True), "type": attr.string(default = ".tar.gz"), "strip_prefix": attr.string(), "package_name": attr.string(default = "nodejs"), "version": attr.string(mandatory = True), "architecture": attr.string(mandatory = True), # control is only used to populate the sbom, see https://github.com/GoogleContainerTools/distroless/issues/1373 # for why writing debian control files to the image is incompatible with scanners. "control": attr.label(), }, ) def _node_impl(module_ctx): mod = module_ctx.modules[0] if len(module_ctx.modules) > 1: fail("node.archive should be called only once") if not mod.is_root: fail("node.archive should be called from root module only.") # Node (https://nodejs.org/en/about/releases/) # Follow Node's maintainence schedule and support all LTS versions that are not end of life`; for (const nodeVersion of versions) { const major = parseInt(nodeVersion.split(".")[0]); for (const key of architectures) { if (major > 22 && key === "arm") { continue; } const arch = nodeVersions[nodeVersion][key]; const url = `https://nodejs.org/dist/v${nodeVersion}/node-v${nodeVersion}-linux-${arch.suffix}.tar.gz`; nodeArchives += "\n"; nodeArchives += ` node_archive( name = "nodejs${major}_${key}", sha256 = "${arch.checksum}", strip_prefix = "node-v${nodeVersion}-linux-${arch.suffix}/", urls = ["${url}"], version = "${nodeVersion}", architecture = "${key}", control = "//nodejs:control", )`; } const testData = `schemaVersion: "2.0.0" commandTests: - name: nodejs command: "/nodejs/bin/node" args: ["--version"] expectedOutput: ["v${nodeVersion}"] `; fs.writeFile(`nodejs/testdata/nodejs${major}.yaml`, testData, (err) => { if (err) { console.error(err); } }); } nodeArchives += ` return module_ctx.extension_metadata( root_module_direct_deps = [`; for (const nodeVersion of versions) { const major = parseInt(nodeVersion.split(".")[0]); for (const arch of architectures) { if (major > 22 && arch === "arm") { continue; } nodeArchives += ` "nodejs${major}_${arch}",`; } } nodeArchives += ` ], root_module_direct_dev_deps = [], ) _archive = tag_class(attrs = {}) node = module_extension( implementation = _node_impl, tag_classes = { "archive": _archive, }, ) `; // Write output to node_archives.bzl file fs.writeFile("private/extensions/node.bzl", nodeArchives, (err) => { if (err) { console.error(err); } }); }); ================================================ FILE: nodejs/BUILD ================================================ load(":config.bzl", "NODEJS_ARCHITECTURES", "NODEJS_DISTROS", "NODEJS_MAJOR_VERSIONS") load(":nodejs.bzl", "nodejs_image", "nodejs_image_index") package(default_visibility = ["//visibility:public"]) [ nodejs_image( arch = arch, distro = distro, major_version = major_version, ) for distro in NODEJS_DISTROS for major_version in NODEJS_MAJOR_VERSIONS for arch in NODEJS_ARCHITECTURES[distro][major_version] ] [ nodejs_image_index( architectures = NODEJS_ARCHITECTURES[distro][major_version], distro = distro, major_version = major_version, ) for distro in NODEJS_DISTROS for major_version in NODEJS_MAJOR_VERSIONS ] ================================================ FILE: nodejs/README.md ================================================ # Documentation for `gcr.io/distroless/nodejs` ## Image Contents These images contain a minimal Linux, Node.js-based runtime. The supported versions match the [Node.js LTS releases](https://nodejs.org/en/about/previous-releases). Specifically, these images contain everything in the [cc image](../cc/README.md), plus one of: - Node.js v20 (`gcr.io/distroless/nodejs20-debian13`) and its dependencies. - Node.js v22 (`gcr.io/distroless/nodejs22-debian13`) and its dependencies. - Node.js v24 (`gcr.io/distroless/nodejs24-debian13`) and its dependencies. ## Usage The entrypoint of this image is set to "node", so this image expects users to supply a path to a .js file in the CMD. See the Node.js [Hello World](../examples/nodejs/) directory for an example. ================================================ FILE: nodejs/config.bzl ================================================ NODEJS_DISTROS = ["debian13"] NODEJS_ARCHITECTURES = { "debian13": { "20": ["amd64", "arm64", "arm", "s390x", "ppc64le"], "22": ["amd64", "arm64", "arm", "s390x", "ppc64le"], "24": ["amd64", "arm64", "s390x", "ppc64le"], }, } NODEJS_MAJOR_VERSIONS = ["20", "22", "24"] ================================================ FILE: nodejs/control ================================================ Package: nodejs Version: {{VERSION}} Architecture: {{ARCHITECTURE}} Maintainer: OpenJS Foundation Homepage: https://nodejs.org SHA256: {{SHA256}} Description: Node.js event-based server-side javascript engine Node.js is similar in design to and influenced by systems like Ruby's Event Machine or Python's Twisted. . It takes the event model a bit further - it presents the event loop as a language construct instead of as a library. . Node.js is bundled with several useful libraries to handle server tasks : System, Events, Standard I/O, Modules, Timers, Child Processes, POSIX, HTTP, Multipart Parsing, TCP, DNS, Assert, Path, URL, Query Strings. ================================================ FILE: nodejs/nodejs.bzl ================================================ "nodejs image definitions" load("@container_structure_test//:defs.bzl", "container_structure_test") load("@rules_oci//oci:defs.bzl", "oci_image", "oci_image_index") load("//common:variables.bzl", "DEBUG_MODE", "USERS") load("//private/util:tar.bzl", "tar") def nodejs_image_index(distro, major_version, architectures): """nodejs image index for a distro. Args: distro: name of distribution major_version: version of nodejs architectures: all architectures included in index """ for mode in DEBUG_MODE: for user in USERS: oci_image_index( name = "nodejs" + major_version + mode + "_" + user + "_" + distro, images = [ "nodejs" + major_version + mode + "_" + user + "_" + arch + "_" + distro for arch in architectures ], ) def _check_certificates_tar(): # only create once if native.existing_rule("check_certificate"): return tar( name = "check_certificate", extension = "tar.gz", srcs = ["testdata/check_certificate.js"], ) def nodejs_image(distro, major_version, arch): """nodejs and debug image with tests. Args: distro: name of distribution major_version: version of nodejs arch: the target arch """ for mode in DEBUG_MODE: for user in USERS: oci_image( name = "nodejs" + major_version + mode + "_" + user + "_" + arch + "_" + distro, base = "//cc:cc" + mode + "_" + user + "_" + arch + "_" + distro, entrypoint = ["/nodejs/bin/node"], tars = [ "@nodejs" + major_version + "_" + arch, ], ) _check_certificates_tar() for mode in DEBUG_MODE: for user in USERS: container_structure_test( name = "nodejs" + major_version + mode + "_" + user + "_" + arch + "_" + distro + "_test", configs = [ "testdata/nodejs" + major_version + ".yaml", "testdata/check_headers.yaml", "testdata/check_npm.yaml", ], image = "nodejs" + major_version + mode + "_" + user + "_" + arch + "_" + distro, tags = [ arch, "manual", ], ) for mode in DEBUG_MODE: for user in USERS: oci_image( name = "check_certificate_nodejs" + major_version + mode + "_" + user + "_" + arch + "_" + distro, base = "nodejs" + major_version + mode + "_" + user + "_" + arch + "_" + distro, tars = [ ":check_certificate", ], ) for mode in DEBUG_MODE: for user in USERS: container_structure_test( name = "check_certificate_nodejs" + major_version + mode + "_" + user + "_" + arch + "_" + distro + "_test", configs = ["testdata/check_certificate.yaml"], image = "check_certificate_nodejs" + major_version + mode + "_" + user + "_" + arch + "_" + distro, tags = [ arch, "manual", ], ) ================================================ FILE: nodejs/testdata/check_certificate.js ================================================ const https = require('https') const options = { hostname: 'www.google.com', port: 443, path: '/', method: 'GET' } const req = https.request(options, res => { console.log(`statusCode: ${res.statusCode}`) res.resume() }) req.end() ================================================ FILE: nodejs/testdata/check_certificate.yaml ================================================ schemaVersion: "2.0.0" commandTests: - name: nodejs command: "/nodejs/bin/node" args: ["/check_certificate.js"] expectedOutput: ['statusCode: 200'] ================================================ FILE: nodejs/testdata/check_headers.yaml ================================================ schemaVersion: "2.0.0" fileExistenceTests: - name: npm path: '/nodejs/include/node/node.h' shouldExist: false ================================================ FILE: nodejs/testdata/check_npm.yaml ================================================ schemaVersion: "2.0.0" fileExistenceTests: - name: npm path: '/nodejs/lib/node_modules/npm' shouldExist: false - name: corepack path: '/nodejs/lib/node_modules/corepack' shouldExist: false - name: npm path: '/nodejs/bin/npm' shouldExist: false - name: corepack path: '/nodejs/bin/corepack' shouldExist: false - name: npx path: '/nodejs/bin/npx' shouldExist: false ================================================ FILE: nodejs/testdata/nodejs20.yaml ================================================ schemaVersion: "2.0.0" commandTests: - name: nodejs command: "/nodejs/bin/node" args: ["--version"] expectedOutput: ["v20.20.1"] ================================================ FILE: nodejs/testdata/nodejs22.yaml ================================================ schemaVersion: "2.0.0" commandTests: - name: nodejs command: "/nodejs/bin/node" args: ["--version"] expectedOutput: ["v22.22.1"] ================================================ FILE: nodejs/testdata/nodejs24.yaml ================================================ schemaVersion: "2.0.0" commandTests: - name: nodejs command: "/nodejs/bin/node" args: ["--version"] expectedOutput: ["v24.14.0"] ================================================ FILE: private/extensions/BUILD.bazel ================================================ ================================================ FILE: private/extensions/busybox.bzl ================================================ "busybox" load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive", "http_file") load("//experimental/busybox:commands.bzl", "BUSYBOX_ARCHIVE_BUILD") def _busybox_impl(module_ctx): mod = module_ctx.modules[0] if len(module_ctx.modules) > 1: fail("busybox.archive should be called only once") if not mod.is_root: fail("busybox.archive should be called from root module only.") # To update amd64 busybox binary (#1014) # Get the latest commit hash from dist-amd64 branch of docker-library repo. You can also view it # at https://github.com/docker-library/official-images/blob/master/library/busybox # Substitute it in the link: https://github.com/docker-library/busybox/raw//latest/musl/busybox.tar.gz # Update the sha256 value. Since github api doesn't give sha256 value, it can be obtained using sha256sum command. http_archive( name = "busybox_amd64", sha256 = "8e7bef4a92afca21c56c9f85e4e63885b320f1da8f8f82a1cf87af359faf57d3", urls = ["https://raw.githubusercontent.com/docker-library/busybox/e5b5178110ca0332364a77d5eb4fff87b0e2ba3f/latest/musl/amd64/rootfs.tar.gz"], build_file_content = BUSYBOX_ARCHIVE_BUILD, ) # To update arm busybox binary # Get the latest commit hash from dist-arm32v7 branch of docker-library repo. You can also view it # at https://github.com/docker-library/official-images/blob/master/library/busybox # Substitute it in the link: https://github.com/docker-library/busybox/raw//latest/musl/arm32v7/rootfs.tar.gz # Update the sha256 value. Since github api doesn't give sha256 value, it can be obtained using sha256sum command. http_archive( name = "busybox_arm", sha256 = "3c873527f998bba56151b7c7d19c133390a44ef894242e7ad5536de1ac0c347e", urls = ["https://raw.githubusercontent.com/docker-library/busybox/a4fac83861d137e9dcfce70b31d0b8fafea9346e/latest/musl/arm32v7/rootfs.tar.gz"], build_file_content = BUSYBOX_ARCHIVE_BUILD, ) # To update arm64 busybox binary (#657) # Get the latest commit hash from dist-arm64v8 branch of docker-library repo. You can also view it # at https://github.com/docker-library/official-images/blob/master/library/busybox # Substitute it in the link: https://github.com/docker-library/busybox/raw//latest/musl/busybox.tar.gz # Update the sha256 value. Since github api doesn't give sha256 value, it can be obtained using sha256sum command. http_archive( name = "busybox_arm64", sha256 = "07b73337cea2a5d87c21278f251e1e742e253232ebd035d6a4a6d2cb4612e462", urls = ["https://raw.githubusercontent.com/docker-library/busybox/f30de561de9bf38da10058620e9c4c383ec8a905/latest/musl/arm64v8/rootfs.tar.gz"], build_file_content = BUSYBOX_ARCHIVE_BUILD, ) # To update s390x busybox binary # Get the latest commit hash from dist-s390x branch of docker-library repo. You can also view it # at https://github.com/docker-library/official-images/blob/master/library/busybox # Substitute it in the link: https://github.com/docker-library/busybox/raw//latest/musl/s390x/rootfs.tar.gz # Update the sha256 value. Since github api doesn't give sha256 value, it can be obtained using sha256sum command. http_archive( name = "busybox_s390x", sha256 = "3bd977f75e22a5e164e2e6ac3556cee55053022e9ad8bba89614e7a8680791d1", urls = ["https://raw.githubusercontent.com/docker-library/busybox/87c948a4fac6f84195e795486a8d650b0c9cc10d/latest/musl/s390x/rootfs.tar.gz"], build_file_content = BUSYBOX_ARCHIVE_BUILD, ) # To update ppc64le busybox binary (#723) # Get the latest commit hash from dist-ppc64le branch of docker-library repo. You can also view it # at https://github.com/docker-library/official-images/blob/master/library/busybox # Substitute it in the link: https://github.com/docker-library/busybox/raw//latest/musl/busybox.tar.gz # Update the sha256 value. Since github api doesn't give sha256 value, it can be obtained using sha256sum command. http_archive( name = "busybox_ppc64le", sha256 = "f3f5d636887b8d56aabe29047a58ef074511f5252c722b1e476b7f79fd35fb7f", urls = ["https://raw.githubusercontent.com/docker-library/busybox/149c39d6036d77a55679c6b9e0c946ba2ad38555/latest/musl/ppc64le/rootfs.tar.gz"], build_file_content = BUSYBOX_ARCHIVE_BUILD, ) # To update riscv64 busybox binary # Get the latest commit hash from dist-riscv64 branch of docker-library repo. You can also view it # at https://github.com/docker-library/official-images/blob/master/library/busybox # Substitute it in the link: https://github.com/docker-library/busybox/raw//latest/musl/busybox.tar.gz # Update the sha256 value. Since github api doesn't give sha256 value, it can be obtained using sha256sum command. http_archive( name = "busybox_riscv64", sha256 = "17737180c892fb9eac75524ae789040f0b01415e6e05e063bc2b8f982b340d97", urls = ["https://raw.githubusercontent.com/docker-library/busybox/eabe7cf678f2abbc0477a8603428519771ede877/latest/musl/riscv64/rootfs.tar.gz"], build_file_content = BUSYBOX_ARCHIVE_BUILD, ) return module_ctx.extension_metadata( root_module_direct_deps = [ "busybox_amd64", "busybox_arm", "busybox_arm64", "busybox_s390x", "busybox_ppc64le", "busybox_riscv64", ], root_module_direct_dev_deps = [], ) _archive = tag_class(attrs = {}) busybox = module_extension( implementation = _busybox_impl, tag_classes = { "archive": _archive, }, ) ================================================ FILE: private/extensions/node.bzl ================================================ "node" BUILD_TMPL = """\ # GENERATED BY node_archive.bzl load("@distroless//private/pkg:debian_spdx.bzl", "debian_spdx") load("@distroless//private/util:merge_providers.bzl", "merge_providers") load("@distroless//private/util:tar.bzl", "tar") tar( name = "data", extension = "tar.gz", srcs = glob( [ "output/bin/node", "output/LICENSE", ], ), package_dir = "/nodejs", strip_prefix = "external/{canonical_name}/output" ) tar( name = "_control", extension = "tar.gz", srcs = ["control"] ) debian_spdx( name = "spdx", control = ":_control", data = ":data", package_name = "{package_name}", spdx_id = "{spdx_id}", sha256 = "{sha256}", urls = [{urls}] ) merge_providers( name = "{name}", srcs = [":data", ":spdx"], visibility = ["//visibility:public"], ) """ def _impl(rctx): rctx.report_progress("Fetching {}".format(rctx.attr.package_name)) rctx.download_and_extract( url = rctx.attr.urls, sha256 = rctx.attr.sha256, type = rctx.attr.type, stripPrefix = rctx.attr.strip_prefix, output = "output", ) rctx.template( "control", rctx.attr.control, substitutions = { "{{VERSION}}": rctx.attr.version, "{{ARCHITECTURE}}": rctx.attr.architecture, "{{SHA256}}": rctx.attr.sha256, }, ) rctx.file( "BUILD.bazel", content = BUILD_TMPL.format( canonical_name = rctx.attr.name, name = rctx.attr.name.split("~")[-1], package_name = rctx.attr.package_name, spdx_id = rctx.attr.name, urls = ",".join(['"%s"' % url for url in rctx.attr.urls]), sha256 = rctx.attr.sha256, ), ) node_archive = repository_rule( implementation = _impl, attrs = { "urls": attr.string_list(mandatory = True), "sha256": attr.string(mandatory = True), "type": attr.string(default = ".tar.gz"), "strip_prefix": attr.string(), "package_name": attr.string(default = "nodejs"), "version": attr.string(mandatory = True), "architecture": attr.string(mandatory = True), # control is only used to populate the sbom, see https://github.com/GoogleContainerTools/distroless/issues/1373 # for why writing debian control files to the image is incompatible with scanners. "control": attr.label(), }, ) def _node_impl(module_ctx): mod = module_ctx.modules[0] if len(module_ctx.modules) > 1: fail("node.archive should be called only once") if not mod.is_root: fail("node.archive should be called from root module only.") # Node (https://nodejs.org/en/about/releases/) # Follow Node's maintainence schedule and support all LTS versions that are not end of life node_archive( name = "nodejs20_amd64", sha256 = "6362e50804cdcc110592201f67beda93bcd702fdcbe1c42840a50d590e3af0ce", strip_prefix = "node-v20.20.1-linux-x64/", urls = ["https://nodejs.org/dist/v20.20.1/node-v20.20.1-linux-x64.tar.gz"], version = "20.20.1", architecture = "amd64", control = "//nodejs:control", ) node_archive( name = "nodejs20_arm64", sha256 = "d6947e10ddc124284aee92981cc739cd4581a6b4bf89520792f2b582600195fa", strip_prefix = "node-v20.20.1-linux-arm64/", urls = ["https://nodejs.org/dist/v20.20.1/node-v20.20.1-linux-arm64.tar.gz"], version = "20.20.1", architecture = "arm64", control = "//nodejs:control", ) node_archive( name = "nodejs20_arm", sha256 = "6d7b0f1f3a88004b251fd4d2ee2f5c4faca15587a3cdaaefae11e655b9e01cde", strip_prefix = "node-v20.20.1-linux-armv7l/", urls = ["https://nodejs.org/dist/v20.20.1/node-v20.20.1-linux-armv7l.tar.gz"], version = "20.20.1", architecture = "arm", control = "//nodejs:control", ) node_archive( name = "nodejs20_ppc64le", sha256 = "d885a22c1a08bd2d2f91c290770f3a9762075c4ec222fcd9d9fc921b0c8294b9", strip_prefix = "node-v20.20.1-linux-ppc64le/", urls = ["https://nodejs.org/dist/v20.20.1/node-v20.20.1-linux-ppc64le.tar.gz"], version = "20.20.1", architecture = "ppc64le", control = "//nodejs:control", ) node_archive( name = "nodejs20_s390x", sha256 = "7f0688d98fce89a9d7c623a3b0d2eab8374333f31461c8cb8b9d34712c45a1ba", strip_prefix = "node-v20.20.1-linux-s390x/", urls = ["https://nodejs.org/dist/v20.20.1/node-v20.20.1-linux-s390x.tar.gz"], version = "20.20.1", architecture = "s390x", control = "//nodejs:control", ) node_archive( name = "nodejs22_amd64", sha256 = "07c8aafa60644fb81adefa1ee7da860eb1920851ffdc9a37020ab0be47fbc10e", strip_prefix = "node-v22.22.1-linux-x64/", urls = ["https://nodejs.org/dist/v22.22.1/node-v22.22.1-linux-x64.tar.gz"], version = "22.22.1", architecture = "amd64", control = "//nodejs:control", ) node_archive( name = "nodejs22_arm64", sha256 = "1d1690e9aba47e887a275abc6d8f7317e571a0700deaef493f768377e99155f5", strip_prefix = "node-v22.22.1-linux-arm64/", urls = ["https://nodejs.org/dist/v22.22.1/node-v22.22.1-linux-arm64.tar.gz"], version = "22.22.1", architecture = "arm64", control = "//nodejs:control", ) node_archive( name = "nodejs22_arm", sha256 = "2b592d21609ef299d1e3918bb806ed62ba715d4109b0f8ec11b132af9fa42d70", strip_prefix = "node-v22.22.1-linux-armv7l/", urls = ["https://nodejs.org/dist/v22.22.1/node-v22.22.1-linux-armv7l.tar.gz"], version = "22.22.1", architecture = "arm", control = "//nodejs:control", ) node_archive( name = "nodejs22_ppc64le", sha256 = "18f9ab7da4f3a04ec213590b14e5d78b60bfb5c6b8bf53541e7eaf1adf9d270a", strip_prefix = "node-v22.22.1-linux-ppc64le/", urls = ["https://nodejs.org/dist/v22.22.1/node-v22.22.1-linux-ppc64le.tar.gz"], version = "22.22.1", architecture = "ppc64le", control = "//nodejs:control", ) node_archive( name = "nodejs22_s390x", sha256 = "6128f9d54a1b43258144d7ac074a82d3b6c96d8e9cb3a8e14e4722a66990adbe", strip_prefix = "node-v22.22.1-linux-s390x/", urls = ["https://nodejs.org/dist/v22.22.1/node-v22.22.1-linux-s390x.tar.gz"], version = "22.22.1", architecture = "s390x", control = "//nodejs:control", ) node_archive( name = "nodejs24_amd64", sha256 = "dbf5b8665dec15e59e6359a517fefb47b23fdb9152d8def975b9bca3dfc6d355", strip_prefix = "node-v24.14.0-linux-x64/", urls = ["https://nodejs.org/dist/v24.14.0/node-v24.14.0-linux-x64.tar.gz"], version = "24.14.0", architecture = "amd64", control = "//nodejs:control", ) node_archive( name = "nodejs24_arm64", sha256 = "f44740cd218de8127f1c44c41510a3a740fa5c9c8d1cdce1c3bedada79f3cde7", strip_prefix = "node-v24.14.0-linux-arm64/", urls = ["https://nodejs.org/dist/v24.14.0/node-v24.14.0-linux-arm64.tar.gz"], version = "24.14.0", architecture = "arm64", control = "//nodejs:control", ) node_archive( name = "nodejs24_ppc64le", sha256 = "83b263f9c2ea946c0c4a15c3caea6470dc49fe0beb6f33dfd29aa9128250637a", strip_prefix = "node-v24.14.0-linux-ppc64le/", urls = ["https://nodejs.org/dist/v24.14.0/node-v24.14.0-linux-ppc64le.tar.gz"], version = "24.14.0", architecture = "ppc64le", control = "//nodejs:control", ) node_archive( name = "nodejs24_s390x", sha256 = "8fa220a1f7b7769605c2e929fdbf736822997bf4cf88a3db05188eabd7712328", strip_prefix = "node-v24.14.0-linux-s390x/", urls = ["https://nodejs.org/dist/v24.14.0/node-v24.14.0-linux-s390x.tar.gz"], version = "24.14.0", architecture = "s390x", control = "//nodejs:control", ) return module_ctx.extension_metadata( root_module_direct_deps = [ "nodejs20_amd64", "nodejs20_arm64", "nodejs20_arm", "nodejs20_ppc64le", "nodejs20_s390x", "nodejs22_amd64", "nodejs22_arm64", "nodejs22_arm", "nodejs22_ppc64le", "nodejs22_s390x", "nodejs24_amd64", "nodejs24_arm64", "nodejs24_ppc64le", "nodejs24_s390x", ], root_module_direct_dev_deps = [], ) _archive = tag_class(attrs = {}) node = module_extension( implementation = _node_impl, tag_classes = { "archive": _archive, }, ) ================================================ FILE: private/extensions/version.bzl ================================================ "generates version information from lockfiles" # buildifier: disable=bzl-visibility load("@rules_distroless//apt/private:version.bzl", _version = "version") _VERSIONS_TMPL = """\ "versions repo" # AUTO GENERATED. DO NOT EDIT. _versions = {} # buildifier: disable=function-docstring def version(dist, arch, name): if dist not in _versions: fail("unknown dist {{}}".format(dist)) if name not in _versions[dist]: fail("unknown package {{}}".format(name)) if arch not in _versions[dist][name]: fail("unknown arch {{}}".format(arch)) return struct(**_versions[dist][name][arch]) """ def _parse_version(raw): (epoch, upstream, revision) = _version.parse(raw) return struct(raw = raw, epoch = epoch, upstream = upstream, revision = revision) def _version_repo_impl(rctx): rctx.file("versions.bzl", _VERSIONS_TMPL.format(json.decode(rctx.attr.versions))) rctx.file("BUILD.bazel", "exports_files(['versions.bzl'])") version_repo = repository_rule( implementation = _version_repo_impl, attrs = { "versions": attr.string(), }, ) def _version_impl(module_ctx): versions = dict() for mod in module_ctx.modules: for from_lock in mod.tags.from_lock: lock = json.decode(module_ctx.read(from_lock.lock)) repo = from_lock.repo_name if lock["version"] != 1: fail("unknown lock version") if repo not in versions: versions[repo] = dict() for pkg in lock["packages"]: if pkg["name"] not in versions[repo]: versions[repo][pkg["name"]] = dict() versions[repo][pkg["name"]][pkg["arch"]] = _parse_version(pkg["version"]) version_repo( name = "versions", versions = json.encode(versions), ) return module_ctx.extension_metadata( root_module_direct_deps = ["versions"], root_module_direct_dev_deps = [], ) _from_lock = tag_class(attrs = { "repo_name": attr.string(mandatory = True), "lock": attr.label(mandatory = True), }) version = module_extension( implementation = _version_impl, tag_classes = { "from_lock": _from_lock, }, ) ================================================ FILE: private/oci/BUILD.bazel ================================================ exports_files(["sign_and_push.sh.tpl"]) ================================================ FILE: private/oci/cc_image.bzl ================================================ "cc_image rule for creating C++ container images" load("@rules_cc//cc:cc_binary.bzl", "cc_binary") load("@rules_oci//oci:defs.bzl", "oci_image") load("//private/util:tar.bzl", "tar") def cc_image(name, srcs, base): cc_binary( name = "%s_binary" % name, srcs = srcs, ) tar( name = "%s_layer" % name, extension = "tar.gz", srcs = [ ":%s_binary" % name, ], ) oci_image( name = name, base = base, entrypoint = [ "/%s_binary" % name, ], tars = [ ":%s_layer" % name, ], ) ================================================ FILE: private/oci/defs.bzl ================================================ load(":cc_image.bzl", _cc_image = "cc_image") load(":go_image.bzl", _go_image = "go_image") load(":java_image.bzl", _java_image = "java_image") load(":rust_image.bzl", _rust_image = "rust_image") load(":sign_and_push.bzl", _sign_and_push_all = "sign_and_push_all") java_image = _java_image cc_image = _cc_image rust_image = _rust_image go_image = _go_image sign_and_push_all = _sign_and_push_all ================================================ FILE: private/oci/digest.bzl ================================================ "generate digest for oci_image and oci_image_index" load("@aspect_bazel_lib//lib:copy_file.bzl", "copy_file") load("@aspect_bazel_lib//lib:directory_path.bzl", "directory_path") load("@aspect_bazel_lib//lib:jq.bzl", "jq") # Normally we'd use the `.digest` target that rules_oci creates for every oci_image but # we also use oci_image_index which does not have a digest target. This was fixed in # https://github.com/bazel-contrib/rules_oci/pull/742 but it on the 2.x releases of rules_oci # TODO: Remove this once we upgrade to rules_oci 2.x def digest(name, image, **kwargs): # `oci_image_rule` and `oci_image_index_rule` produce a directory as default output. # Label for the [name]/index.json file directory_path( name = "_{}_index_json".format(name), directory = image, path = "index.json", **kwargs ) copy_file( name = "_{}_index_json_cp".format(name), src = "_{}_index_json".format(name), out = "_{}_index.json".format(name), **kwargs ) # Matches the [name].digest target produced by rules_docker container_image jq( name = name, args = ["--raw-output"], srcs = ["_{}_index.json".format(name)], filter = """.manifests[0].digest""", out = name + ".json.sha256", # path chosen to match rules_docker for easy migration **kwargs ) ================================================ FILE: private/oci/go_image.bzl ================================================ "go_image rule for creating Go container images" load("@rules_go//go:def.bzl", "go_binary") load("@rules_oci//oci:defs.bzl", "oci_image") load("//private/util:tar.bzl", "tar") def go_image(name, srcs, base, arch = "amd64", os = "linux"): go_binary( name = "{}_binary".format(name), srcs = srcs, goarch = arch, goos = os, pure = "on", ) tar( name = "{}_layer".format(name), extension = "tar.gz", srcs = ["{}_binary".format(name)], ) oci_image( name = name, base = base, entrypoint = ["/{}_binary".format(name)], tars = [ "{}_layer".format(name), ], ) ================================================ FILE: private/oci/java_image.bzl ================================================ "java_image rule for creating Java container images" load("@rules_oci//oci:defs.bzl", "oci_image") load("//private/util:tar.bzl", "tar") def java_image(name, srcs, main_class, base): native.java_binary( name = "%s_binary" % name, srcs = srcs, main_class = main_class, ) tar( name = "%s_layer" % name, extension = "tar.gz", srcs = [ ":%s_binary" % name, ], ) oci_image( name = name, base = base, cmd = [ "/%s_binary.jar" % name, ], tars = [ ":%s_layer" % name, ], ) ================================================ FILE: private/oci/rust_image.bzl ================================================ "rust_image rule for creating Rust container images" load("@rules_oci//oci:defs.bzl", "oci_image") load("@rules_rust//rust:defs.bzl", "rust_binary") load("//private/util:tar.bzl", "tar") def rust_image(name, srcs, base, tags): rust_binary( name = "%s_binary" % name, srcs = srcs, tags = tags, ) tar( name = "%s_layer" % name, extension = "tar.gz", srcs = [ ":%s_binary" % name, ], tags = tags, ) oci_image( name = name, base = base, entrypoint = [ "/%s_binary" % name, ], tars = [ ":%s_layer" % name, ], tags = tags, ) ================================================ FILE: private/oci/sign_and_push.bzl ================================================ "rules for signing, attesting and pushing images" load("@bazel_skylib//rules:write_file.bzl", "write_file") load("//private/pkg:oci_image_spdx.bzl", "oci_image_spdx") load(":digest.bzl", "digest") PUSH_AND_SIGN_CMD = """\ # Push {IMAGE} repository="$(stamp "{REPOSITORY}")" tag="$(stamp "{TAG}")" digest="$(cat {DIGEST})" echo "Pushing $repository@$digest" {CRANE} push {IMAGE} "$repository@$digest" # Check for signature and skip signing/sbom if present if ! {COSIGN} verify "$repository@$digest" --certificate-oidc-issuer https://accounts.google.com --certificate-identity "${{KEYLESS}}" > /dev/null; then {COSIGN} attest "$repository@$digest" --predicate "{SBOM}" --type "spdx" --yes {COSIGN} sign "$repository@$digest" --yes fi {CRANE} tag "$repository@$digest" "$tag" """ TAG_CMD = """\ # Tag {IMAGE} from="$(stamp "{FROM}")" tag="$(stamp "{TAG}")" {CRANE} tag "$from" "$tag" """ def _sign_and_push_impl(ctx): cmds = [] runfiles = ctx.runfiles(files = ctx.files.targets + [ctx.version_file, ctx.file._crane, ctx.file._cosign]) for (image, target) in ctx.attr.targets.items(): files = target[DefaultInfo].files.to_list() all_refs = ctx.attr.refs[image] for ref in all_refs: repository_and_tag = ref.split(":") cmds.append( PUSH_AND_SIGN_CMD.format( IMAGE = files[0].short_path, SBOM = files[1].short_path, DIGEST = files[2].short_path, CRANE = ctx.file._crane.short_path, COSIGN = ctx.file._cosign.short_path, REPOSITORY = repository_and_tag[0], TAG = repository_and_tag[1], ), ) for tag in ctx.attr.more_tags[ref]: cmds.append( TAG_CMD.format( IMAGE = image, FROM = ref, TAG = tag, CRANE = ctx.file._crane.short_path, ), ) executable = ctx.actions.declare_file("{}_sign_and_push.sh".format(ctx.label.name)) ctx.actions.expand_template( template = ctx.file._push_tpl, output = executable, substitutions = { "{{VERSION_FILE}}": ctx.version_file.short_path, "{{CMDS}}": "\n".join(cmds), }, is_executable = True, ) return DefaultInfo(executable = executable, runfiles = runfiles) sign_and_push = rule( implementation = _sign_and_push_impl, attrs = { "refs": attr.string_list_dict(mandatory = True), "targets": attr.string_keyed_label_dict(mandatory = True, cfg = "exec"), "more_tags": attr.string_list_dict(mandatory = True), "_push_tpl": attr.label(default = "sign_and_push.sh.tpl", allow_single_file = True), "_crane": attr.label(allow_single_file = True, cfg = "exec", default = "@oci_crane_toolchains//:current_toolchain"), "_cosign": attr.label(allow_single_file = True, cfg = "exec", default = "@oci_cosign_toolchains//:current_toolchain"), }, executable = True, ) def sign_and_push_all(name, images): """simple macro singing and pushing images Args: name: name of the target images: a dict where keys are fully qualified image reference and values are image label """ # since bazel doesn't allow dicts of dicts of lists as attrs, we have to write this nutty # deduplication code dedup_image_dict = dict() dedup_more_tags = dict() dedup_push_dict = dict() for (idx, (ref, image)) in enumerate(images.items()): repository_and_tag = ref.split(":") repository = repository_and_tag[0] tag = repository_and_tag[1] if image in dedup_image_dict: foundPrefix = False for oRef in dedup_image_dict[image]: if oRef.split(":")[0] == repository: dedup_more_tags[oRef].append(tag) foundPrefix = True break if not foundPrefix: dedup_image_dict[image].append(ref) dedup_more_tags[ref] = [] else: dedup_image_dict[image] = [ref] dedup_more_tags[ref] = [] for (idx, (image, _)) in enumerate(dedup_image_dict.items()): oci_image_spdx( name = "{}_{}_sbom".format(name, idx), image = image, ) digest( name = "{}_{}_digest".format(name, idx), image = image, ) native.filegroup( name = "{}_{}".format(name, idx), srcs = [ image, ":{}_{}_sbom".format(name, idx), ":{}_{}_digest".format(name, idx), ], ) dedup_push_dict[image] = "{}_{}".format(name, idx) write_file( name = name + ".query", content = [ "{repo} {image}".format( repo = repo, image = image, ) for (image, refs) in dedup_image_dict.items() for repo in refs ], out = name + "_query", ) sign_and_push( name = name, targets = dedup_push_dict, more_tags = dedup_more_tags, refs = dedup_image_dict, ) ================================================ FILE: private/oci/sign_and_push.sh.tpl ================================================ #!/usr/bin/env bash set -o pipefail -o errexit -o nounset KEYLESS="${KEYLESS:-}" while (( $# > 0 )); do case $1 in (--keyless) KEYLESS="$2" shift shift;; (*) echo "unknown arg $1" exit 1 esac done if [ -z $KEYLESS ]; then echo "--keyless flag or KEYLESS environment variable must be provided" exit 1 fi echo "## Signing and pushing images..." echo "" readonly version_file="$(cat "{{VERSION_FILE}}")" function stamp() { local str=$1 while read -r line; do IFS=" " read -r key value <<< "$line" str="${str/\{$key\}/$value}" done <<< "$version_file" echo "$str" } export GOOGLE_SERVICE_ACCOUNT_NAME="${KEYLESS}" {{CMDS}} echo "" echo "👌 Finished pushing & signing" echo "" ================================================ FILE: private/pkg/BUILD.bazel ================================================ load("@rules_go//go:def.bzl", "go_binary") package(default_visibility = ["//visibility:public"]) go_binary( name = "oci_image_spdx", srcs = ["oci_image_spdx.go"], deps = [ "@com_github_spdx_tools_golang//json", "@com_github_spdx_tools_golang//spdx/common", "@com_github_spdx_tools_golang//spdx/v2_3", ], ) go_binary( name = "debian_spdx", srcs = ["debian_spdx.go"], deps = [ "@com_github_spdx_tools_golang//json", "@com_github_spdx_tools_golang//spdx/common", "@com_github_spdx_tools_golang//spdx/v2_3", ], ) ================================================ FILE: private/pkg/debian_spdx.bzl ================================================ SPDX_CMD = """\ tmp="$(mktemp -d)" tar -xf "$1" -C "$tmp" "./control" || tar -xf "$1" -C "$tmp" "control" if tar -xf "$2" -C "$tmp" "usr/share/doc/$3/copyright" >/dev/null 2>&1; then COPYRIGHT="$tmp/usr/share/doc/$3/copyright" fi if tar -xf "$2" -C "$tmp" "./usr/share/doc/$3/copyright" >/dev/null 2>&1; then COPYRIGHT="$tmp/usr/share/doc/$3/copyright" fi shift shift shift {generator} --control="$tmp/control" --copyright=$COPYRIGHT $@ """ def _impl(ctx): output = ctx.actions.declare_file("%s.spdx.json" % ctx.label.name) args = ctx.actions.args() args.add(ctx.file.control.path) args.add(ctx.file.data.path) args.add(ctx.attr.package_name) args.add(ctx.attr.spdx_id, format = "--id=%s") args.add(output.path, format = "--output=%s") args.add(ctx.label, format = "--generates=%s") # TODO: multiple urls. it is not required at the moment since .deb are fetched without a fallback mirror. args.add(ctx.attr.urls[0], format = "--url=%s") args.add(ctx.attr.sha256, format = "--sha256=%s") ctx.actions.run_shell( inputs = [ctx.file.control, ctx.file.data], outputs = [output], command = SPDX_CMD.format(generator = ctx.file._generator.path), tools = [ctx.executable._generator], arguments = [args], ) return OutputGroupInfo( spdx = depset([output]), ) debian_spdx = rule( implementation = _impl, attrs = { "control": attr.label(mandatory = True, allow_single_file = [".tar", ".tar.xz", "tar.gz", "tar.zst"]), "data": attr.label(mandatory = True, allow_single_file = [".tar", ".tar.xz", "tar.gz", "tar.zst"]), "package_name": attr.string(mandatory = True), "spdx_id": attr.string(mandatory = True), "urls": attr.string_list(mandatory = True), "sha256": attr.string(mandatory = True), "_generator": attr.label(default = ":debian_spdx", executable = True, allow_single_file = True, cfg = "exec"), }, ) ================================================ FILE: private/pkg/debian_spdx.go ================================================ package main import ( "bufio" "flag" "fmt" "io" "log" "os" "regexp" "strings" spdx_json "github.com/spdx/tools-golang/json" "github.com/spdx/tools-golang/spdx/common" "github.com/spdx/tools-golang/spdx/v2_3" ) func pkgId(id string) string { id = strings.ReplaceAll(id, "/", "-slash-") id = strings.ReplaceAll(id, "_", "-underscore-") id = strings.ReplaceAll(id, "_", "-underscore-") id = strings.ReplaceAll(id, ":", "-colon-") id = strings.ReplaceAll(id, "@", "-at-") return id } // TODO: make part of debian_package_manager func parseDebControl(r io.Reader) (map[string]string, error) { const ( separator = ":" ) var currentKey string var currentEntry = map[string]string{} continuation := regexp.MustCompile(`^\s`) s := bufio.NewScanner(r) // some Packages.xz lines are super big maxCap := 1024 * 1024 megaBuffer := make([]byte, maxCap) s.Buffer(megaBuffer, maxCap) ln := 0 for s.Scan() { line := s.Text() ln++ if continuation.MatchString(line) { if currentKey == "" || len(currentEntry) == 0 { return nil, fmt.Errorf("bad indentation on line %d: %q", ln, line) } currentEntry[currentKey] += "\n" + strings.TrimSpace(line) } else if strings.Contains(line, separator) { sp := strings.SplitN(line, separator, 2) currentKey = strings.TrimSpace(sp[0]) if _, ok := currentEntry[currentKey]; ok { return nil, fmt.Errorf("duplicate key %q on line %d: %q", currentKey, ln, line) } currentEntry[currentKey] = strings.TrimSpace(sp[1]) } else { return nil, fmt.Errorf("no indentation or delimiter on line %d: %q", ln, line) } } if s.Err() != nil { return nil, s.Err() } return currentEntry, nil } func main() { var control, output, sha256, url, id, copyright, generates string flag.StringVar(&control, "control", "", "") flag.StringVar(&output, "output", "", "") flag.StringVar(&sha256, "sha256", "", "") flag.StringVar(&id, "id", "", "") flag.StringVar(©right, "copyright", "", "") flag.StringVar(&generates, "generates", "", "") // TODO: multiple urls. it is not required at the moment since .deb are fetched without a fallback mirror. flag.StringVar(&url, "url", "", "") flag.Parse() read, err := os.Open(control) if err != nil { log.Fatalln(err) } mp, err := parseDebControl(read) if err != nil { log.Fatalln(err) } copyrightText := "NOASSERTION" if copyright != "" { copyrightBytes, err := os.ReadFile(copyright) if err != nil { log.Fatalln(err) } copyrightText = string(copyrightBytes) } supplier := &common.Supplier{} if mp["Maintainer"] != "" { supplier.Supplier = mp["Maintainer"] supplier.SupplierType = "Person" } deb := &v2_3.Package{ PackageSPDXIdentifier: common.ElementID(pkgId(id)), PackageName: mp["Package"], PackageDescription: mp["Description"], PackageSummary: strings.Split(mp["Description"], "\n")[0], PackageVersion: mp["Version"], PackageSourceInfo: mp["Source"], PackageHomePage: mp["Homepage"], BuiltDate: mp["Date"], ReleaseDate: mp["Date"], PackageDownloadLocation: url, PackageSupplier: supplier, PackageCopyrightText: copyrightText, PackageChecksums: []common.Checksum{ { Algorithm: common.SHA256, Value: sha256, }, }, PackageExternalReferences: []*v2_3.PackageExternalReference{ { Category: "PACKAGE-MANAGER", Locator: fmt.Sprintf("pkg:deb/debian/%s@%s?arch=%s", mp["Package"], mp["Version"], mp["Architecture"]), RefType: common.TypePackageManagerPURL, }, }, } gen := &v2_3.Package{ PackageSPDXIdentifier: common.ElementID(pkgId(generates)), PackageName: generates, PackageDescription: fmt.Sprintf("Generated from %s@%s", deb.PackageName, deb.PackageVersion), PackageDownloadLocation: "NOASSERTION", PackageCopyrightText: "NOASSERTION", } doc := &v2_3.Document{ SPDXIdentifier: gen.PackageSPDXIdentifier, Packages: []*v2_3.Package{ deb, gen, }, Relationships: []*v2_3.Relationship{ &v2_3.Relationship{ RefA: common.DocElementID{ElementRefID: gen.PackageSPDXIdentifier}, RefB: common.DocElementID{ElementRefID: deb.PackageSPDXIdentifier}, Relationship: common.TypeRelationshipGeneratedFrom, }, }, } outputFile, err := os.Create(output) if err != nil { log.Fatalln(err) } if err := spdx_json.Save2_3(doc, outputFile); err != nil { log.Fatalln(err) } } ================================================ FILE: private/pkg/oci_image_spdx.bzl ================================================ "an aspect rule that generates spdx by collecting spdx output group" def _image_aspect_impl(target, ctx): output = ctx.actions.declare_file("%s.spdx.json" % target.label.name) args = ctx.actions.args() args.add(output.path, format = "--output=%s") args.add(target.label, format = "--label=%s") input_depsets = [] if ctx.rule.kind == "oci_image": if ctx.rule.attr.base != None: output_group_info = ctx.rule.attr.base[OutputGroupInfo] if output_group_info and "spdx" in output_group_info: input_depsets.append(output_group_info.spdx) args.add_all(output_group_info.spdx, format_each = "--contains=%s") for src in ctx.rule.attr.tars: if OutputGroupInfo in src and "spdx" in src[OutputGroupInfo]: input_depsets.append(src[OutputGroupInfo].spdx) args.add_all(src[OutputGroupInfo].spdx) elif ctx.rule.kind == "oci_image_index": for image in ctx.rule.attr.images: if OutputGroupInfo in image and "spdx" in image[OutputGroupInfo]: input_depsets.append(image[OutputGroupInfo].spdx) args.add_all(image[OutputGroupInfo].spdx, format_each = "--contains=%s") ctx.actions.run( inputs = depset(transitive = input_depsets), outputs = [output], executable = ctx.executable._generator, arguments = [args], ) return [ OutputGroupInfo( spdx = depset([output]), ), ] image_aspect = aspect( implementation = _image_aspect_impl, attr_aspects = ["base", "images"], attrs = {"_generator": attr.label(default = ":oci_image_spdx", executable = True, allow_single_file = True, cfg = "exec")}, ) def _oci_image_spdx_impl(ctx): return DefaultInfo(files = ctx.attr.image[OutputGroupInfo].spdx) oci_image_spdx = rule( implementation = _oci_image_spdx_impl, attrs = { "image": attr.label(aspects = [image_aspect]), }, ) ================================================ FILE: private/pkg/oci_image_spdx.go ================================================ package main import ( "flag" "fmt" "log" "os" "strings" spdx_json "github.com/spdx/tools-golang/json" "github.com/spdx/tools-golang/spdx/common" "github.com/spdx/tools-golang/spdx/v2_3" ) func pkgId(id string) string { id = strings.ReplaceAll(id, "/", "-slash-") id = strings.ReplaceAll(id, "_", "-underscore-") id = strings.ReplaceAll(id, "_", "-underscore-") id = strings.ReplaceAll(id, ":", "-colon-") id = strings.ReplaceAll(id, "@", "-at-") return id } type ArrayFlags []string func (i *ArrayFlags) String() string { return "my string representation" } func (i *ArrayFlags) Set(value string) error { *i = append(*i, value) return nil } func main() { var label, output string var contains ArrayFlags flag.StringVar(&output, "output", "", "") flag.StringVar(&label, "label", "", "") flag.Var(&contains, "contains", "") flag.Parse() id := pkgId(label) doc := v2_3.Document{ SPDXIdentifier: "SPDXRef-DOCUMENT", SPDXVersion: "SPDX-2.3", DocumentName: label, DataLicense: "CC0-1.0", DocumentNamespace: "http://spdx.org/spdxdocs/distroless/" + id, CreationInfo: &v2_3.CreationInfo{ Created: "1970-01-01T00:00:00Z", Creators: []common.Creator{ common.Creator{ Creator: "distroless", CreatorType: "Organization", }, }, LicenseListVersion: "NOASSERTION", }, Packages: []*v2_3.Package{ { PackageSPDXIdentifier: common.ElementID(id), PackageName: label, PackageDownloadLocation: "NOASSERTION", PackageCopyrightText: "NOASSERTION", }, }, Relationships: []*v2_3.Relationship{ { RefA: common.MakeDocElementID("", "DOCUMENT"), RefB: common.MakeDocElementID("", id), Relationship: "DESCRIBES", }, }, } spdxs := flag.Args() for _, p := range spdxs { bytes, err := os.Open(p) if err != nil { log.Fatalln(err) } subdoc, err := spdx_json.Load2_3(bytes) if err != nil { log.Fatalln(err) } doc.Packages = append(doc.Packages, subdoc.Packages...) for _, rel := range subdoc.Relationships { if rel.Relationship == "DESCRIBES" && rel.RefA.ElementRefID == "DOCUMENT" { continue } doc.Relationships = append(doc.Relationships, rel) } doc.Relationships = append(doc.Relationships, &v2_3.Relationship{ RefA: common.MakeDocElementID("", id), RefB: common.DocElementID{ElementRefID: subdoc.SPDXIdentifier}, Relationship: "DEPENDS_ON", }) } for _, contain := range contains { bytes, err := os.Open(contain) if err != nil { log.Fatalln(err) } subdoc, err := spdx_json.Load2_3(bytes) if err != nil { log.Fatalln(err) } doc.Packages = append(doc.Packages, subdoc.Packages...) var describedBy *common.DocElementID = nil for _, rel := range subdoc.Relationships { if rel.Relationship == "DESCRIBES" && rel.RefA.ElementRefID == "DOCUMENT" { if rel.RefA.ElementRefID == subdoc.SPDXIdentifier { describedBy = &rel.RefB } continue } doc.Relationships = append(doc.Relationships, rel) } if describedBy == nil { log.Fatalln(fmt.Errorf("%s: can not determine which package describes %s", contain, subdoc.SPDXIdentifier)) } doc.Relationships = append(doc.Relationships, &v2_3.Relationship{ RefA: common.MakeDocElementID("", id), RefB: *describedBy, Relationship: "CONTAINS", }) } outputFile, err := os.Create(output) if err != nil { log.Fatalln(err) } if err := spdx_json.Save2_3(&doc, outputFile); err != nil { log.Fatalln(err) } } ================================================ FILE: private/pkg/test/oci_image/BUILD.bazel ================================================ load("@aspect_bazel_lib//lib:write_source_files.bzl", "write_source_files") load("@rules_oci//oci:defs.bzl", "oci_image", "oci_image_index") load("//private/pkg:oci_image_spdx.bzl", "oci_image_spdx") load("//private/util:deb.bzl", "deb") oci_image( name = "image_arm64", architecture = "arm64", os = "linux", tars = [ deb.package("arm64", "debian12", "base-files"), ], ) oci_image_spdx( name = "image_arm64_sbom", image = ":image_arm64", ) oci_image( name = "image_amd64", architecture = "amd64", os = "linux", tars = [ deb.package("amd64", "debian12", "netbase"), ], ) oci_image_spdx( name = "image_amd64_sbom", image = ":image_amd64", ) oci_image_index( name = "fat_image", images = [ ":image_arm64", ":image_amd64", ], ) oci_image_spdx( name = "fat_image_sbom", image = ":fat_image", ) write_source_files( name = "test_sboms", files = { "fat_image_sbom.spdx.json": ":fat_image_sbom", "image_arm64.spdx.json": ":image_arm64_sbom", "image_amd64.spdx.json": ":image_amd64_sbom", }, ) ================================================ FILE: private/pkg/test/oci_image/fat_image_sbom.spdx.json ================================================ {"spdxVersion":"SPDX-2.3","dataLicense":"CC0-1.0","SPDXID":"SPDXRef-DOCUMENT","name":"//private/pkg/test/oci_image:fat_image","documentNamespace":"http://spdx.org/spdxdocs/distroless/-slash--slash-private-slash-pkg-slash-test-slash-oci-underscore-image-colon-fat-underscore-image","creationInfo":{"licenseListVersion":"NOASSERTION","creators":["Organization: distroless"],"created":"1970-01-01T00:00:00Z"},"packages":[{"name":"//private/pkg/test/oci_image:fat_image","SPDXID":"SPDXRef--slash--slash-private-slash-pkg-slash-test-slash-oci-underscore-image-colon-fat-underscore-image","downloadLocation":"NOASSERTION","copyrightText":"NOASSERTION"},{"name":"//private/pkg/test/oci_image:image_arm64","SPDXID":"SPDXRef--slash--slash-private-slash-pkg-slash-test-slash-oci-underscore-image-colon-image-underscore-arm64","downloadLocation":"NOASSERTION","copyrightText":"NOASSERTION"},{"name":"base-files","SPDXID":"SPDXRef--at-rules-underscore-distroless~~apt~bookworm-underscore-base-files-underscore-12.4-p-deb12u13-underscore-arm64","versionInfo":"12.4+deb12u13","supplier":"Person: Santiago Vila \\\\u003csanvila@debian.org\\\\u003e","downloadLocation":"https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/b/base-files/base-files_12.4+deb12u13_arm64.deb","checksums":[{"algorithm":"SHA256","checksumValue":"4eed22415ebf001438f17064ded8ae9bb5d1bc4ad1200a3f05345055af540e1f"}],"copyrightText":"This is the Debian prepackaged version of the Debian Base System\nMiscellaneous files. These files were written by Ian Murdock\n\u003cimurdock@debian.org\u003e and Bruce Perens \u003cbruce@pixar.com\u003e.\n\nThis package was first put together by Bruce Perens \u003cBruce@Pixar.com\u003e,\nfrom his own sources.\n\nThe GNU Public Licenses in /usr/share/common-licenses were taken from\nftp.gnu.org and are copyrighted by the Free Software Foundation, Inc.\n\nThe Artistic License in /usr/share/common-licenses is the one coming\nfrom Perl and its SPDX name is \"Artistic License 1.0 (Perl)\".\n\n\nCopyright (C) 1995-2011 Software in the Public Interest.\n\nThis program is free software; you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation; either version 2 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\nGNU General Public License for more details.\n\nOn Debian systems, the complete text of the GNU General\nPublic License can be found in `/usr/share/common-licenses/GPL'.\n","summary":"Debian base system miscellaneous files","description":"Debian base system miscellaneous files\nThis package contains the basic filesystem hierarchy of a Debian system, and\nseveral important miscellaneous files, such as /etc/debian_version,\n/etc/host.conf, /etc/issue, /etc/motd, /etc/profile, and others,\nand the text of several common licenses in use on Debian systems.","externalRefs":[{"referenceCategory":"PACKAGE-MANAGER","referenceType":"purl","referenceLocator":"pkg:deb/debian/base-files@12.4+deb12u13?arch=arm64"}]},{"name":"@bookworm//base-files/arm64:spdx","SPDXID":"SPDXRef--at-bookworm-slash--slash-base-files-slash-arm64-colon-spdx","downloadLocation":"NOASSERTION","copyrightText":"NOASSERTION","description":"Generated from base-files@12.4+deb12u13"},{"name":"//private/pkg/test/oci_image:image_amd64","SPDXID":"SPDXRef--slash--slash-private-slash-pkg-slash-test-slash-oci-underscore-image-colon-image-underscore-amd64","downloadLocation":"NOASSERTION","copyrightText":"NOASSERTION"},{"name":"netbase","SPDXID":"SPDXRef--at-rules-underscore-distroless~~apt~bookworm-underscore-netbase-underscore-6.4-underscore-amd64","versionInfo":"6.4","supplier":"Person: Marco d'Itri \\\\u003cmd@linux.it\\\\u003e","downloadLocation":"https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/n/netbase/netbase_6.4_all.deb","checksums":[{"algorithm":"SHA256","checksumValue":"29b23c48c0fe6f878e56c5ddc9f65d1c05d729360f3690a593a8c795031cd867"}],"copyrightText":"Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/\nComment:\n This package was created by Peter Tobias tobias@et-inf.fho-emden.de on\n Wed, 24 Aug 1994 21:33:28 +0200 and maintained by Anthony Towns\n \u003cajt@debian.org\u003e until 2001.\n It is currently maintained by Marco d'Itri \u003cmd@linux.it\u003e.\n\nFiles: *\nCopyright:\n Copyright (c) 1994-1998 Peter Tobias\n Copyright (c) 1998-2001 Anthony Towns\n Copyright (c) 2002-2022 Marco d'Itri\nLicense: GPL-2\n This program is free software; you can redistribute it and/or modify\n it under the terms of the GNU General Public License, version 2, as\n published by the Free Software Foundation.\n .\n This program is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU General Public License for more details.\n .\n You should have received a copy of the GNU General Public License along\n with this program; if not, write to the Free Software Foundation,\n Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n .\n On Debian systems, the complete text of the GNU General Public License\n version 2 can be found in '/usr/share/common-licenses/GPL-2'.\n","summary":"Basic TCP/IP networking system","description":"Basic TCP/IP networking system\nThis package provides the necessary infrastructure for basic TCP/IP based\nnetworking.\n.\nIn particular, it supplies common name-to-number mappings in /etc/services,\n/etc/rpc, /etc/protocols and /etc/ethertypes.","externalRefs":[{"referenceCategory":"PACKAGE-MANAGER","referenceType":"purl","referenceLocator":"pkg:deb/debian/netbase@6.4?arch=all"}]},{"name":"@bookworm//netbase/amd64:spdx","SPDXID":"SPDXRef--at-bookworm-slash--slash-netbase-slash-amd64-colon-spdx","downloadLocation":"NOASSERTION","copyrightText":"NOASSERTION","description":"Generated from netbase@6.4"}],"relationships":[{"spdxElementId":"SPDXRef-DOCUMENT","relatedSpdxElement":"SPDXRef--slash--slash-private-slash-pkg-slash-test-slash-oci-underscore-image-colon-fat-underscore-image","relationshipType":"DESCRIBES"},{"spdxElementId":"SPDXRef--at-bookworm-slash--slash-base-files-slash-arm64-colon-spdx","relatedSpdxElement":"SPDXRef--at-rules-underscore-distroless~~apt~bookworm-underscore-base-files-underscore-12.4-p-deb12u13-underscore-arm64","relationshipType":"GENERATED_FROM"},{"spdxElementId":"SPDXRef--slash--slash-private-slash-pkg-slash-test-slash-oci-underscore-image-colon-image-underscore-arm64","relatedSpdxElement":"SPDXRef--at-bookworm-slash--slash-base-files-slash-arm64-colon-spdx","relationshipType":"DEPENDS_ON"},{"spdxElementId":"SPDXRef--slash--slash-private-slash-pkg-slash-test-slash-oci-underscore-image-colon-fat-underscore-image","relatedSpdxElement":"SPDXRef--slash--slash-private-slash-pkg-slash-test-slash-oci-underscore-image-colon-image-underscore-arm64","relationshipType":"CONTAINS"},{"spdxElementId":"SPDXRef--at-bookworm-slash--slash-netbase-slash-amd64-colon-spdx","relatedSpdxElement":"SPDXRef--at-rules-underscore-distroless~~apt~bookworm-underscore-netbase-underscore-6.4-underscore-amd64","relationshipType":"GENERATED_FROM"},{"spdxElementId":"SPDXRef--slash--slash-private-slash-pkg-slash-test-slash-oci-underscore-image-colon-image-underscore-amd64","relatedSpdxElement":"SPDXRef--at-bookworm-slash--slash-netbase-slash-amd64-colon-spdx","relationshipType":"DEPENDS_ON"},{"spdxElementId":"SPDXRef--slash--slash-private-slash-pkg-slash-test-slash-oci-underscore-image-colon-fat-underscore-image","relatedSpdxElement":"SPDXRef--slash--slash-private-slash-pkg-slash-test-slash-oci-underscore-image-colon-image-underscore-amd64","relationshipType":"CONTAINS"}]} ================================================ FILE: private/pkg/test/oci_image/image_amd64.spdx.json ================================================ {"spdxVersion":"SPDX-2.3","dataLicense":"CC0-1.0","SPDXID":"SPDXRef-DOCUMENT","name":"//private/pkg/test/oci_image:image_amd64","documentNamespace":"http://spdx.org/spdxdocs/distroless/-slash--slash-private-slash-pkg-slash-test-slash-oci-underscore-image-colon-image-underscore-amd64","creationInfo":{"licenseListVersion":"NOASSERTION","creators":["Organization: distroless"],"created":"1970-01-01T00:00:00Z"},"packages":[{"name":"//private/pkg/test/oci_image:image_amd64","SPDXID":"SPDXRef--slash--slash-private-slash-pkg-slash-test-slash-oci-underscore-image-colon-image-underscore-amd64","downloadLocation":"NOASSERTION","copyrightText":"NOASSERTION"},{"name":"netbase","SPDXID":"SPDXRef--at-rules-underscore-distroless~~apt~bookworm-underscore-netbase-underscore-6.4-underscore-amd64","versionInfo":"6.4","supplier":"Person: Marco d'Itri \\u003cmd@linux.it\\u003e","downloadLocation":"https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/n/netbase/netbase_6.4_all.deb","checksums":[{"algorithm":"SHA256","checksumValue":"29b23c48c0fe6f878e56c5ddc9f65d1c05d729360f3690a593a8c795031cd867"}],"copyrightText":"Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/\nComment:\n This package was created by Peter Tobias tobias@et-inf.fho-emden.de on\n Wed, 24 Aug 1994 21:33:28 +0200 and maintained by Anthony Towns\n \u003cajt@debian.org\u003e until 2001.\n It is currently maintained by Marco d'Itri \u003cmd@linux.it\u003e.\n\nFiles: *\nCopyright:\n Copyright (c) 1994-1998 Peter Tobias\n Copyright (c) 1998-2001 Anthony Towns\n Copyright (c) 2002-2022 Marco d'Itri\nLicense: GPL-2\n This program is free software; you can redistribute it and/or modify\n it under the terms of the GNU General Public License, version 2, as\n published by the Free Software Foundation.\n .\n This program is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU General Public License for more details.\n .\n You should have received a copy of the GNU General Public License along\n with this program; if not, write to the Free Software Foundation,\n Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n .\n On Debian systems, the complete text of the GNU General Public License\n version 2 can be found in '/usr/share/common-licenses/GPL-2'.\n","summary":"Basic TCP/IP networking system","description":"Basic TCP/IP networking system\nThis package provides the necessary infrastructure for basic TCP/IP based\nnetworking.\n.\nIn particular, it supplies common name-to-number mappings in /etc/services,\n/etc/rpc, /etc/protocols and /etc/ethertypes.","externalRefs":[{"referenceCategory":"PACKAGE-MANAGER","referenceType":"purl","referenceLocator":"pkg:deb/debian/netbase@6.4?arch=all"}]},{"name":"@bookworm//netbase/amd64:spdx","SPDXID":"SPDXRef--at-bookworm-slash--slash-netbase-slash-amd64-colon-spdx","downloadLocation":"NOASSERTION","copyrightText":"NOASSERTION","description":"Generated from netbase@6.4"}],"relationships":[{"spdxElementId":"SPDXRef-DOCUMENT","relatedSpdxElement":"SPDXRef--slash--slash-private-slash-pkg-slash-test-slash-oci-underscore-image-colon-image-underscore-amd64","relationshipType":"DESCRIBES"},{"spdxElementId":"SPDXRef--at-bookworm-slash--slash-netbase-slash-amd64-colon-spdx","relatedSpdxElement":"SPDXRef--at-rules-underscore-distroless~~apt~bookworm-underscore-netbase-underscore-6.4-underscore-amd64","relationshipType":"GENERATED_FROM"},{"spdxElementId":"SPDXRef--slash--slash-private-slash-pkg-slash-test-slash-oci-underscore-image-colon-image-underscore-amd64","relatedSpdxElement":"SPDXRef--at-bookworm-slash--slash-netbase-slash-amd64-colon-spdx","relationshipType":"DEPENDS_ON"}]} ================================================ FILE: private/pkg/test/oci_image/image_arm64.spdx.json ================================================ {"spdxVersion":"SPDX-2.3","dataLicense":"CC0-1.0","SPDXID":"SPDXRef-DOCUMENT","name":"//private/pkg/test/oci_image:image_arm64","documentNamespace":"http://spdx.org/spdxdocs/distroless/-slash--slash-private-slash-pkg-slash-test-slash-oci-underscore-image-colon-image-underscore-arm64","creationInfo":{"licenseListVersion":"NOASSERTION","creators":["Organization: distroless"],"created":"1970-01-01T00:00:00Z"},"packages":[{"name":"//private/pkg/test/oci_image:image_arm64","SPDXID":"SPDXRef--slash--slash-private-slash-pkg-slash-test-slash-oci-underscore-image-colon-image-underscore-arm64","downloadLocation":"NOASSERTION","copyrightText":"NOASSERTION"},{"name":"base-files","SPDXID":"SPDXRef--at-rules-underscore-distroless~~apt~bookworm-underscore-base-files-underscore-12.4-p-deb12u13-underscore-arm64","versionInfo":"12.4+deb12u13","supplier":"Person: Santiago Vila \\u003csanvila@debian.org\\u003e","downloadLocation":"https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/b/base-files/base-files_12.4+deb12u13_arm64.deb","checksums":[{"algorithm":"SHA256","checksumValue":"4eed22415ebf001438f17064ded8ae9bb5d1bc4ad1200a3f05345055af540e1f"}],"copyrightText":"This is the Debian prepackaged version of the Debian Base System\nMiscellaneous files. These files were written by Ian Murdock\n\u003cimurdock@debian.org\u003e and Bruce Perens \u003cbruce@pixar.com\u003e.\n\nThis package was first put together by Bruce Perens \u003cBruce@Pixar.com\u003e,\nfrom his own sources.\n\nThe GNU Public Licenses in /usr/share/common-licenses were taken from\nftp.gnu.org and are copyrighted by the Free Software Foundation, Inc.\n\nThe Artistic License in /usr/share/common-licenses is the one coming\nfrom Perl and its SPDX name is \"Artistic License 1.0 (Perl)\".\n\n\nCopyright (C) 1995-2011 Software in the Public Interest.\n\nThis program is free software; you can redistribute it and/or modify\nit under the terms of the GNU General Public License as published by\nthe Free Software Foundation; either version 2 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\nGNU General Public License for more details.\n\nOn Debian systems, the complete text of the GNU General\nPublic License can be found in `/usr/share/common-licenses/GPL'.\n","summary":"Debian base system miscellaneous files","description":"Debian base system miscellaneous files\nThis package contains the basic filesystem hierarchy of a Debian system, and\nseveral important miscellaneous files, such as /etc/debian_version,\n/etc/host.conf, /etc/issue, /etc/motd, /etc/profile, and others,\nand the text of several common licenses in use on Debian systems.","externalRefs":[{"referenceCategory":"PACKAGE-MANAGER","referenceType":"purl","referenceLocator":"pkg:deb/debian/base-files@12.4+deb12u13?arch=arm64"}]},{"name":"@bookworm//base-files/arm64:spdx","SPDXID":"SPDXRef--at-bookworm-slash--slash-base-files-slash-arm64-colon-spdx","downloadLocation":"NOASSERTION","copyrightText":"NOASSERTION","description":"Generated from base-files@12.4+deb12u13"}],"relationships":[{"spdxElementId":"SPDXRef-DOCUMENT","relatedSpdxElement":"SPDXRef--slash--slash-private-slash-pkg-slash-test-slash-oci-underscore-image-colon-image-underscore-arm64","relationshipType":"DESCRIBES"},{"spdxElementId":"SPDXRef--at-bookworm-slash--slash-base-files-slash-arm64-colon-spdx","relatedSpdxElement":"SPDXRef--at-rules-underscore-distroless~~apt~bookworm-underscore-base-files-underscore-12.4-p-deb12u13-underscore-arm64","relationshipType":"GENERATED_FROM"},{"spdxElementId":"SPDXRef--slash--slash-private-slash-pkg-slash-test-slash-oci-underscore-image-colon-image-underscore-arm64","relatedSpdxElement":"SPDXRef--at-bookworm-slash--slash-base-files-slash-arm64-colon-spdx","relationshipType":"DEPENDS_ON"}]} ================================================ FILE: private/repos/deb/BUILD.bazel ================================================ ================================================ FILE: private/repos/deb/bookworm.lock.json ================================================ { "packages": [ { "arch": "amd64", "dependencies": [], "key": "base-files_12.4-p-deb12u13_amd64", "name": "base-files", "sha256": "d0aee30a91b1283e0c724e9ad0ae7394d8e56f07d20cacfcb79b8f444daa94cd", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/b/base-files/base-files_12.4+deb12u13_amd64.deb" ], "version": "12.4+deb12u13" }, { "arch": "amd64", "dependencies": [], "key": "ca-certificates_20230311-p-deb12u1_amd64", "name": "ca-certificates", "sha256": "0d5f444f594e48c1e16a41d8fc628a09b24c658916a1274025c2330f2a802bed", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/c/ca-certificates/ca-certificates_20230311+deb12u1_all.deb" ], "version": "20230311+deb12u1" }, { "arch": "amd64", "dependencies": [], "key": "libc6_2.36-9-p-deb12u13_amd64", "name": "libc6", "sha256": "3d8072c73b017e907bbf44b7db870687888a991961d74f1ecbba6b9458f32a2c", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/glibc/libc6_2.36-9+deb12u13_amd64.deb" ], "version": "2.36-9+deb12u13" }, { "arch": "amd64", "dependencies": [], "key": "libc-bin_2.36-9-p-deb12u13_amd64", "name": "libc-bin", "sha256": "3f7a7caf9a34875fb076f08d168430ad8c338c71b0b7e6c02d19e914d7bc4277", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/glibc/libc-bin_2.36-9+deb12u13_amd64.deb" ], "version": "2.36-9+deb12u13" }, { "arch": "amd64", "dependencies": [], "key": "libssl3_3.0.18-1_deb12u2_amd64", "name": "libssl3", "sha256": "ed44f11b74763cded2ad406f4de4d585ea27b0ce6377e7c8d98c2ddf2ed35cb3", "urls": [ "https://snapshot.debian.org/archive/debian-security/20260314T202839Z/pool/updates/main/o/openssl/libssl3_3.0.18-1~deb12u2_amd64.deb" ], "version": "3.0.18-1~deb12u2" }, { "arch": "amd64", "dependencies": [], "key": "netbase_6.4_amd64", "name": "netbase", "sha256": "29b23c48c0fe6f878e56c5ddc9f65d1c05d729360f3690a593a8c795031cd867", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/n/netbase/netbase_6.4_all.deb" ], "version": "6.4" }, { "arch": "amd64", "dependencies": [], "key": "openssl_3.0.18-1_deb12u2_amd64", "name": "openssl", "sha256": "9107c374e0f760d5d7c9c7372788d4e618e1433db4fdef9a3a25788dfd5588bb", "urls": [ "https://snapshot.debian.org/archive/debian-security/20260314T202839Z/pool/updates/main/o/openssl/openssl_3.0.18-1~deb12u2_amd64.deb" ], "version": "3.0.18-1~deb12u2" }, { "arch": "amd64", "dependencies": [], "key": "tzdata_2025b-0-p-deb12u2_amd64", "name": "tzdata", "sha256": "719b61acbc9974a86b92c1d043b9f3b7883dbfe9f5824f9a43c575445fa55d2a", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/t/tzdata/tzdata_2025b-0+deb12u2_all.deb" ], "version": "2025b-0+deb12u2" }, { "arch": "amd64", "dependencies": [], "key": "media-types_10.0.0_amd64", "name": "media-types", "sha256": "aaa46dcb3b39948ae2e0fdb72cfcb2f48c0b59f19785a3da8045c05eb19955dd", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/m/media-types/media-types_10.0.0_all.deb" ], "version": "10.0.0" }, { "arch": "amd64", "dependencies": [], "key": "gcc-12-base_12.2.0-14-p-deb12u1_amd64", "name": "gcc-12-base", "sha256": "1896a2aacf4ad681ff5eacc24a5b0ca4d5d9c9b9c9e4b6de5197bc1e116ea619", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-12/gcc-12-base_12.2.0-14+deb12u1_amd64.deb" ], "version": "12.2.0-14+deb12u1" }, { "arch": "amd64", "dependencies": [], "key": "libgcc-s1_12.2.0-14-p-deb12u1_amd64", "name": "libgcc-s1", "sha256": "3016e62cb4b7cd8038822870601f5ed131befe942774d0f745622cc77d8a88f7", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-12/libgcc-s1_12.2.0-14+deb12u1_amd64.deb" ], "version": "12.2.0-14+deb12u1" }, { "arch": "amd64", "dependencies": [], "key": "libgomp1_12.2.0-14-p-deb12u1_amd64", "name": "libgomp1", "sha256": "48fec46bda7f5b1638b9e959889bfbc20491247d402d120bb152687eb48143d7", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-12/libgomp1_12.2.0-14+deb12u1_amd64.deb" ], "version": "12.2.0-14+deb12u1" }, { "arch": "amd64", "dependencies": [], "key": "libstdc-p--p-6_12.2.0-14-p-deb12u1_amd64", "name": "libstdc++6", "sha256": "5cd3171216d4ab0fc911cfe9c35509bf2dd8f47761c43b7f6a4296701551a24d", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-12/libstdc++6_12.2.0-14+deb12u1_amd64.deb" ], "version": "12.2.0-14+deb12u1" }, { "arch": "arm64", "dependencies": [], "key": "base-files_12.4-p-deb12u13_arm64", "name": "base-files", "sha256": "4eed22415ebf001438f17064ded8ae9bb5d1bc4ad1200a3f05345055af540e1f", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/b/base-files/base-files_12.4+deb12u13_arm64.deb" ], "version": "12.4+deb12u13" }, { "arch": "arm64", "dependencies": [], "key": "ca-certificates_20230311-p-deb12u1_arm64", "name": "ca-certificates", "sha256": "0d5f444f594e48c1e16a41d8fc628a09b24c658916a1274025c2330f2a802bed", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/c/ca-certificates/ca-certificates_20230311+deb12u1_all.deb" ], "version": "20230311+deb12u1" }, { "arch": "arm64", "dependencies": [], "key": "libc6_2.36-9-p-deb12u13_arm64", "name": "libc6", "sha256": "03c3909c47a6df9f6f05357474efefca9bc30212069135a7c354fa78a1ec2415", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/glibc/libc6_2.36-9+deb12u13_arm64.deb" ], "version": "2.36-9+deb12u13" }, { "arch": "arm64", "dependencies": [], "key": "libc-bin_2.36-9-p-deb12u13_arm64", "name": "libc-bin", "sha256": "1199da233e4c893e0a44e81b2024667241c19f93eb12f4ec1e29585117270a85", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/glibc/libc-bin_2.36-9+deb12u13_arm64.deb" ], "version": "2.36-9+deb12u13" }, { "arch": "arm64", "dependencies": [], "key": "libssl3_3.0.18-1_deb12u2_arm64", "name": "libssl3", "sha256": "30b2d6c27fd4a2f5ef554ac3b86c96e8a3abbbfb454c6dbe7e308ce9df36f8c5", "urls": [ "https://snapshot.debian.org/archive/debian-security/20260314T202839Z/pool/updates/main/o/openssl/libssl3_3.0.18-1~deb12u2_arm64.deb" ], "version": "3.0.18-1~deb12u2" }, { "arch": "arm64", "dependencies": [], "key": "netbase_6.4_arm64", "name": "netbase", "sha256": "29b23c48c0fe6f878e56c5ddc9f65d1c05d729360f3690a593a8c795031cd867", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/n/netbase/netbase_6.4_all.deb" ], "version": "6.4" }, { "arch": "arm64", "dependencies": [], "key": "openssl_3.0.18-1_deb12u2_arm64", "name": "openssl", "sha256": "ed4671eb9fcc282b69c9768863f2df0386664d686bb3103d5397802f9c0b1297", "urls": [ "https://snapshot.debian.org/archive/debian-security/20260314T202839Z/pool/updates/main/o/openssl/openssl_3.0.18-1~deb12u2_arm64.deb" ], "version": "3.0.18-1~deb12u2" }, { "arch": "arm64", "dependencies": [], "key": "tzdata_2025b-0-p-deb12u2_arm64", "name": "tzdata", "sha256": "719b61acbc9974a86b92c1d043b9f3b7883dbfe9f5824f9a43c575445fa55d2a", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/t/tzdata/tzdata_2025b-0+deb12u2_all.deb" ], "version": "2025b-0+deb12u2" }, { "arch": "arm64", "dependencies": [], "key": "media-types_10.0.0_arm64", "name": "media-types", "sha256": "aaa46dcb3b39948ae2e0fdb72cfcb2f48c0b59f19785a3da8045c05eb19955dd", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/m/media-types/media-types_10.0.0_all.deb" ], "version": "10.0.0" }, { "arch": "arm64", "dependencies": [], "key": "gcc-12-base_12.2.0-14-p-deb12u1_arm64", "name": "gcc-12-base", "sha256": "674cf6cba6d432bd200c45fe866c1652c7a53523cc2e7a613e05bc4abf7b5440", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-12/gcc-12-base_12.2.0-14+deb12u1_arm64.deb" ], "version": "12.2.0-14+deb12u1" }, { "arch": "arm64", "dependencies": [], "key": "libgcc-s1_12.2.0-14-p-deb12u1_arm64", "name": "libgcc-s1", "sha256": "576926b283613db80168ddf76380a3bd877602778cf0d226caa7bfbfa71eacf3", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-12/libgcc-s1_12.2.0-14+deb12u1_arm64.deb" ], "version": "12.2.0-14+deb12u1" }, { "arch": "arm64", "dependencies": [], "key": "libgomp1_12.2.0-14-p-deb12u1_arm64", "name": "libgomp1", "sha256": "a48b70dd1a95585466b40bd94564bce56ebcb2566e49ccdb6441e996aaab2098", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-12/libgomp1_12.2.0-14+deb12u1_arm64.deb" ], "version": "12.2.0-14+deb12u1" }, { "arch": "arm64", "dependencies": [], "key": "libstdc-p--p-6_12.2.0-14-p-deb12u1_arm64", "name": "libstdc++6", "sha256": "26e138c677a985775331373828a6c286c551ff397cb735d00e2383cb273d1cb2", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-12/libstdc++6_12.2.0-14+deb12u1_arm64.deb" ], "version": "12.2.0-14+deb12u1" }, { "arch": "armhf", "dependencies": [], "key": "base-files_12.4-p-deb12u13_armhf", "name": "base-files", "sha256": "75e4530fc4f301449c94b953d4568ad22ce6b57209fbcf9d1f0d0091ec03de69", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/b/base-files/base-files_12.4+deb12u13_armhf.deb" ], "version": "12.4+deb12u13" }, { "arch": "armhf", "dependencies": [], "key": "ca-certificates_20230311-p-deb12u1_armhf", "name": "ca-certificates", "sha256": "0d5f444f594e48c1e16a41d8fc628a09b24c658916a1274025c2330f2a802bed", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/c/ca-certificates/ca-certificates_20230311+deb12u1_all.deb" ], "version": "20230311+deb12u1" }, { "arch": "armhf", "dependencies": [], "key": "libc6_2.36-9-p-deb12u13_armhf", "name": "libc6", "sha256": "f62e6fb5ec766e80ef811d11e8453e44a389900076899f7c9d4cb244955883d0", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/glibc/libc6_2.36-9+deb12u13_armhf.deb" ], "version": "2.36-9+deb12u13" }, { "arch": "armhf", "dependencies": [], "key": "libc-bin_2.36-9-p-deb12u13_armhf", "name": "libc-bin", "sha256": "a4f59c85e0dca4a66f21e26eb4c7d440f581a806edeab2ce7b749a0cf5b8cb3d", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/glibc/libc-bin_2.36-9+deb12u13_armhf.deb" ], "version": "2.36-9+deb12u13" }, { "arch": "armhf", "dependencies": [], "key": "libssl3_3.0.18-1_deb12u2_armhf", "name": "libssl3", "sha256": "954b6ba96d28e9659e4049de09ff56aee9d7b16e9f2c94577e22907a4c3b4085", "urls": [ "https://snapshot.debian.org/archive/debian-security/20260314T202839Z/pool/updates/main/o/openssl/libssl3_3.0.18-1~deb12u2_armhf.deb" ], "version": "3.0.18-1~deb12u2" }, { "arch": "armhf", "dependencies": [], "key": "netbase_6.4_armhf", "name": "netbase", "sha256": "29b23c48c0fe6f878e56c5ddc9f65d1c05d729360f3690a593a8c795031cd867", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/n/netbase/netbase_6.4_all.deb" ], "version": "6.4" }, { "arch": "armhf", "dependencies": [], "key": "openssl_3.0.18-1_deb12u2_armhf", "name": "openssl", "sha256": "f7e9348d0edc740f1b1dee053414b24f99f40d6db76b93b4db0b2af45a5d8a06", "urls": [ "https://snapshot.debian.org/archive/debian-security/20260314T202839Z/pool/updates/main/o/openssl/openssl_3.0.18-1~deb12u2_armhf.deb" ], "version": "3.0.18-1~deb12u2" }, { "arch": "armhf", "dependencies": [], "key": "tzdata_2025b-0-p-deb12u2_armhf", "name": "tzdata", "sha256": "719b61acbc9974a86b92c1d043b9f3b7883dbfe9f5824f9a43c575445fa55d2a", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/t/tzdata/tzdata_2025b-0+deb12u2_all.deb" ], "version": "2025b-0+deb12u2" }, { "arch": "armhf", "dependencies": [], "key": "media-types_10.0.0_armhf", "name": "media-types", "sha256": "aaa46dcb3b39948ae2e0fdb72cfcb2f48c0b59f19785a3da8045c05eb19955dd", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/m/media-types/media-types_10.0.0_all.deb" ], "version": "10.0.0" }, { "arch": "armhf", "dependencies": [], "key": "gcc-12-base_12.2.0-14-p-deb12u1_armhf", "name": "gcc-12-base", "sha256": "aa50f90c440377b9219830ed3e658aedcb0a1c1bb47733eb05cf65545012f563", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-12/gcc-12-base_12.2.0-14+deb12u1_armhf.deb" ], "version": "12.2.0-14+deb12u1" }, { "arch": "armhf", "dependencies": [], "key": "libgcc-s1_12.2.0-14-p-deb12u1_armhf", "name": "libgcc-s1", "sha256": "f58562bf01efd6112b914182147ee149e0d4c90869046e31844da8803669eeb3", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-12/libgcc-s1_12.2.0-14+deb12u1_armhf.deb" ], "version": "12.2.0-14+deb12u1" }, { "arch": "armhf", "dependencies": [], "key": "libgomp1_12.2.0-14-p-deb12u1_armhf", "name": "libgomp1", "sha256": "31a758a139de68333485e03679cc4721d4a5a2652b64a9402b0b1f401f38ce85", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-12/libgomp1_12.2.0-14+deb12u1_armhf.deb" ], "version": "12.2.0-14+deb12u1" }, { "arch": "armhf", "dependencies": [], "key": "libstdc-p--p-6_12.2.0-14-p-deb12u1_armhf", "name": "libstdc++6", "sha256": "66d53ddeb10a37f22e455611c2c515f9d444e523b55d873ff48bde47267963db", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-12/libstdc++6_12.2.0-14+deb12u1_armhf.deb" ], "version": "12.2.0-14+deb12u1" }, { "arch": "s390x", "dependencies": [], "key": "base-files_12.4-p-deb12u13_s390x", "name": "base-files", "sha256": "26836d12260f8ebff7d7cc4c635af23b413e4d46a96c2707d0310a99f5a07e94", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/b/base-files/base-files_12.4+deb12u13_s390x.deb" ], "version": "12.4+deb12u13" }, { "arch": "s390x", "dependencies": [], "key": "ca-certificates_20230311-p-deb12u1_s390x", "name": "ca-certificates", "sha256": "0d5f444f594e48c1e16a41d8fc628a09b24c658916a1274025c2330f2a802bed", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/c/ca-certificates/ca-certificates_20230311+deb12u1_all.deb" ], "version": "20230311+deb12u1" }, { "arch": "s390x", "dependencies": [], "key": "libc6_2.36-9-p-deb12u13_s390x", "name": "libc6", "sha256": "a3445bb815ef415ca1c419b5c84dab873cac4d1210ace620b95600d8e0344137", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/glibc/libc6_2.36-9+deb12u13_s390x.deb" ], "version": "2.36-9+deb12u13" }, { "arch": "s390x", "dependencies": [], "key": "libc-bin_2.36-9-p-deb12u13_s390x", "name": "libc-bin", "sha256": "6a459d71f550505335fcbb81a7f67866a3c3ffc08e77c1d82e4a39dbcb9090a3", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/glibc/libc-bin_2.36-9+deb12u13_s390x.deb" ], "version": "2.36-9+deb12u13" }, { "arch": "s390x", "dependencies": [], "key": "libssl3_3.0.18-1_deb12u2_s390x", "name": "libssl3", "sha256": "4880e9829cf618d54ed5c2662a6f9a0a3eaf021e2db4767e76eab5a95da6d023", "urls": [ "https://snapshot.debian.org/archive/debian-security/20260314T202839Z/pool/updates/main/o/openssl/libssl3_3.0.18-1~deb12u2_s390x.deb" ], "version": "3.0.18-1~deb12u2" }, { "arch": "s390x", "dependencies": [], "key": "netbase_6.4_s390x", "name": "netbase", "sha256": "29b23c48c0fe6f878e56c5ddc9f65d1c05d729360f3690a593a8c795031cd867", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/n/netbase/netbase_6.4_all.deb" ], "version": "6.4" }, { "arch": "s390x", "dependencies": [], "key": "openssl_3.0.18-1_deb12u2_s390x", "name": "openssl", "sha256": "1f393115696962b061d47e82abcce6501d69e86a0e9cb81068b4a7454cd0f0ae", "urls": [ "https://snapshot.debian.org/archive/debian-security/20260314T202839Z/pool/updates/main/o/openssl/openssl_3.0.18-1~deb12u2_s390x.deb" ], "version": "3.0.18-1~deb12u2" }, { "arch": "s390x", "dependencies": [], "key": "tzdata_2025b-0-p-deb12u2_s390x", "name": "tzdata", "sha256": "719b61acbc9974a86b92c1d043b9f3b7883dbfe9f5824f9a43c575445fa55d2a", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/t/tzdata/tzdata_2025b-0+deb12u2_all.deb" ], "version": "2025b-0+deb12u2" }, { "arch": "s390x", "dependencies": [], "key": "media-types_10.0.0_s390x", "name": "media-types", "sha256": "aaa46dcb3b39948ae2e0fdb72cfcb2f48c0b59f19785a3da8045c05eb19955dd", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/m/media-types/media-types_10.0.0_all.deb" ], "version": "10.0.0" }, { "arch": "s390x", "dependencies": [], "key": "gcc-12-base_12.2.0-14-p-deb12u1_s390x", "name": "gcc-12-base", "sha256": "95394971de33e2d3c04c8e77c5cab1ddcba3924692749513be19d8c65b4a3001", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-12/gcc-12-base_12.2.0-14+deb12u1_s390x.deb" ], "version": "12.2.0-14+deb12u1" }, { "arch": "s390x", "dependencies": [], "key": "libgcc-s1_12.2.0-14-p-deb12u1_s390x", "name": "libgcc-s1", "sha256": "58f31fb42eecc42510d5b5022f03aa7e302350637a5643b1773361c0da97f905", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-12/libgcc-s1_12.2.0-14+deb12u1_s390x.deb" ], "version": "12.2.0-14+deb12u1" }, { "arch": "s390x", "dependencies": [], "key": "libgomp1_12.2.0-14-p-deb12u1_s390x", "name": "libgomp1", "sha256": "57527a0d71f4ba47e384d69c3bb2d5647dcddc4b49cd098a2fd46d59492eaefc", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-12/libgomp1_12.2.0-14+deb12u1_s390x.deb" ], "version": "12.2.0-14+deb12u1" }, { "arch": "s390x", "dependencies": [], "key": "libstdc-p--p-6_12.2.0-14-p-deb12u1_s390x", "name": "libstdc++6", "sha256": "b0521cbe2cd1de442a468373bdfe323ed83e04aa729d5a3f554beefba4049e68", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-12/libstdc++6_12.2.0-14+deb12u1_s390x.deb" ], "version": "12.2.0-14+deb12u1" }, { "arch": "ppc64el", "dependencies": [], "key": "base-files_12.4-p-deb12u13_ppc64el", "name": "base-files", "sha256": "ae229b34dd67ed8245554d40d7dc3579fe43da7ffb5a22b40c7d94cf7d2a0a8e", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/b/base-files/base-files_12.4+deb12u13_ppc64el.deb" ], "version": "12.4+deb12u13" }, { "arch": "ppc64el", "dependencies": [], "key": "ca-certificates_20230311-p-deb12u1_ppc64el", "name": "ca-certificates", "sha256": "0d5f444f594e48c1e16a41d8fc628a09b24c658916a1274025c2330f2a802bed", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/c/ca-certificates/ca-certificates_20230311+deb12u1_all.deb" ], "version": "20230311+deb12u1" }, { "arch": "ppc64el", "dependencies": [], "key": "libc6_2.36-9-p-deb12u13_ppc64el", "name": "libc6", "sha256": "17280b91201b45e75469dc3fb6a307de8d6551bee16bc6cb98335601a4dc5311", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/glibc/libc6_2.36-9+deb12u13_ppc64el.deb" ], "version": "2.36-9+deb12u13" }, { "arch": "ppc64el", "dependencies": [], "key": "libc-bin_2.36-9-p-deb12u13_ppc64el", "name": "libc-bin", "sha256": "babb33ae6ad54d257cd8f999894dc9cf4a0a7f03654f5c860c1131eef1c6d9ba", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/glibc/libc-bin_2.36-9+deb12u13_ppc64el.deb" ], "version": "2.36-9+deb12u13" }, { "arch": "ppc64el", "dependencies": [], "key": "libssl3_3.0.18-1_deb12u2_ppc64el", "name": "libssl3", "sha256": "b5f48b447b296ed45f857a34fdc42f42134ad26ababbe6b5b0e7ed56c8bedc54", "urls": [ "https://snapshot.debian.org/archive/debian-security/20260314T202839Z/pool/updates/main/o/openssl/libssl3_3.0.18-1~deb12u2_ppc64el.deb" ], "version": "3.0.18-1~deb12u2" }, { "arch": "ppc64el", "dependencies": [], "key": "netbase_6.4_ppc64el", "name": "netbase", "sha256": "29b23c48c0fe6f878e56c5ddc9f65d1c05d729360f3690a593a8c795031cd867", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/n/netbase/netbase_6.4_all.deb" ], "version": "6.4" }, { "arch": "ppc64el", "dependencies": [], "key": "openssl_3.0.18-1_deb12u2_ppc64el", "name": "openssl", "sha256": "269f301321dfd24a68a48c30d2e468176561681b0acdd50787e311b0232dd785", "urls": [ "https://snapshot.debian.org/archive/debian-security/20260314T202839Z/pool/updates/main/o/openssl/openssl_3.0.18-1~deb12u2_ppc64el.deb" ], "version": "3.0.18-1~deb12u2" }, { "arch": "ppc64el", "dependencies": [], "key": "tzdata_2025b-0-p-deb12u2_ppc64el", "name": "tzdata", "sha256": "719b61acbc9974a86b92c1d043b9f3b7883dbfe9f5824f9a43c575445fa55d2a", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/t/tzdata/tzdata_2025b-0+deb12u2_all.deb" ], "version": "2025b-0+deb12u2" }, { "arch": "ppc64el", "dependencies": [], "key": "media-types_10.0.0_ppc64el", "name": "media-types", "sha256": "aaa46dcb3b39948ae2e0fdb72cfcb2f48c0b59f19785a3da8045c05eb19955dd", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/m/media-types/media-types_10.0.0_all.deb" ], "version": "10.0.0" }, { "arch": "ppc64el", "dependencies": [], "key": "gcc-12-base_12.2.0-14-p-deb12u1_ppc64el", "name": "gcc-12-base", "sha256": "2703f8a9087f18cc73b2d6c3c0adcd568e9302451335dad627392517019200b5", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-12/gcc-12-base_12.2.0-14+deb12u1_ppc64el.deb" ], "version": "12.2.0-14+deb12u1" }, { "arch": "ppc64el", "dependencies": [], "key": "libgcc-s1_12.2.0-14-p-deb12u1_ppc64el", "name": "libgcc-s1", "sha256": "ced4a668899fc6b13e87b2ffa44b0e819797f9b36fcff5c1709094d653cd9b2f", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-12/libgcc-s1_12.2.0-14+deb12u1_ppc64el.deb" ], "version": "12.2.0-14+deb12u1" }, { "arch": "ppc64el", "dependencies": [], "key": "libgomp1_12.2.0-14-p-deb12u1_ppc64el", "name": "libgomp1", "sha256": "e7ae3f0f0d26334fca637989ac691b7c91046c3a878b64227efd29ee00a369e4", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-12/libgomp1_12.2.0-14+deb12u1_ppc64el.deb" ], "version": "12.2.0-14+deb12u1" }, { "arch": "ppc64el", "dependencies": [], "key": "libstdc-p--p-6_12.2.0-14-p-deb12u1_ppc64el", "name": "libstdc++6", "sha256": "290e4a488a2911b230df0b03c19591a5663a7136f8cc5ceba946880ff7dbf047", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-12/libstdc++6_12.2.0-14+deb12u1_ppc64el.deb" ], "version": "12.2.0-14+deb12u1" } ], "version": 1 } ================================================ FILE: private/repos/deb/bookworm.yaml ================================================ # debian 12 version: 1 sources: - channel: bookworm main url: https://snapshot.debian.org/archive/debian/20260314T202839Z - channel: bookworm-updates main url: https://snapshot.debian.org/archive/debian/20260314T202839Z - channel: bookworm-security main url: https://snapshot.debian.org/archive/debian-security/20260314T202839Z archs: - amd64 - arm64 - armhf - s390x - ppc64el packages: - base-files - ca-certificates - libc6 - libc-bin - libssl3 - netbase - openssl - tzdata - media-types # c++ - gcc-12-base - libgcc-s1 - libgomp1 - libstdc++6 ================================================ FILE: private/repos/deb/bookworm_python.lock.json ================================================ { "packages": [ { "arch": "amd64", "dependencies": [], "key": "libbz2-1.0_1.0.8-5-p-b1_amd64", "name": "libbz2-1.0", "sha256": "54149da3f44b22d523b26b692033b84503d822cc5122fed606ea69cc83ca5aeb", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/b/bzip2/libbz2-1.0_1.0.8-5+b1_amd64.deb" ], "version": "1.0.8-5+b1" }, { "arch": "amd64", "dependencies": [], "key": "libcom-err2_1.47.0-2-p-b2_amd64", "name": "libcom-err2", "sha256": "a2bac7015e78fbc0c504df3e441f3a22292f1d2d77f9ccda760057f3690e22f2", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/e/e2fsprogs/libcom-err2_1.47.0-2+b2_amd64.deb" ], "version": "1.47.0-2+b2" }, { "arch": "amd64", "dependencies": [], "key": "libcrypt1_1-4.4.33-2_amd64", "name": "libcrypt1", "sha256": "f5f60a5cdfd4e4eaa9438ade5078a57741a7a78d659fcb0c701204f523e8bd29", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/libx/libxcrypt/libcrypt1_4.4.33-2_amd64.deb" ], "version": "1:4.4.33-2" }, { "arch": "amd64", "dependencies": [], "key": "libdb5.3_5.3.28-p-dfsg2-1_amd64", "name": "libdb5.3", "sha256": "7dc5127b8dd0da80e992ba594954c005ae4359d839a24eb65d0d8129b5235c84", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/d/db5.3/libdb5.3_5.3.28+dfsg2-1_amd64.deb" ], "version": "5.3.28+dfsg2-1" }, { "arch": "amd64", "dependencies": [], "key": "libexpat1_2.5.0-1-p-deb12u2_amd64", "name": "libexpat1", "sha256": "2255e62fc22a86d2c544b8a3f516da9aee19383ad5742722ab4ce7f66a30dbc8", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/e/expat/libexpat1_2.5.0-1+deb12u2_amd64.deb" ], "version": "2.5.0-1+deb12u2" }, { "arch": "amd64", "dependencies": [], "key": "libffi8_3.4.4-1_amd64", "name": "libffi8", "sha256": "6d9f6c25c30efccce6d4bceaa48ea86c329a3432abb360a141f76ac223a4c34a", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/libf/libffi/libffi8_3.4.4-1_amd64.deb" ], "version": "3.4.4-1" }, { "arch": "amd64", "dependencies": [], "key": "libgssapi-krb5-2_1.20.1-2-p-deb12u4_amd64", "name": "libgssapi-krb5-2", "sha256": "ae20a9d90d0998ccb062a42739c8c5c725579e2d3f44fbd16b026e336b4543bb", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/k/krb5/libgssapi-krb5-2_1.20.1-2+deb12u4_amd64.deb" ], "version": "1.20.1-2+deb12u4" }, { "arch": "amd64", "dependencies": [], "key": "libk5crypto3_1.20.1-2-p-deb12u4_amd64", "name": "libk5crypto3", "sha256": "b921355ee030582117aadd95a9f08de341867921a277803ae7e520be2ac9786d", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/k/krb5/libk5crypto3_1.20.1-2+deb12u4_amd64.deb" ], "version": "1.20.1-2+deb12u4" }, { "arch": "amd64", "dependencies": [], "key": "libkeyutils1_1.6.3-2_amd64", "name": "libkeyutils1", "sha256": "cfac89e6a7a54ff3c6a4f843310e25efeddaa771baeae470bd98bd588c373563", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/k/keyutils/libkeyutils1_1.6.3-2_amd64.deb" ], "version": "1.6.3-2" }, { "arch": "amd64", "dependencies": [], "key": "libkrb5-3_1.20.1-2-p-deb12u4_amd64", "name": "libkrb5-3", "sha256": "af14ab652a7e8579c67c846dd95b987a4332c05165c8eec9790028f5aea6c2b0", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/k/krb5/libkrb5-3_1.20.1-2+deb12u4_amd64.deb" ], "version": "1.20.1-2+deb12u4" }, { "arch": "amd64", "dependencies": [], "key": "libkrb5support0_1.20.1-2-p-deb12u4_amd64", "name": "libkrb5support0", "sha256": "5e7fac690530a3e16c0a6707d8262d869c23248eac72daee3eb7c40982c3ddfe", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/k/krb5/libkrb5support0_1.20.1-2+deb12u4_amd64.deb" ], "version": "1.20.1-2+deb12u4" }, { "arch": "amd64", "dependencies": [], "key": "liblzma5_5.4.1-1_amd64", "name": "liblzma5", "sha256": "d321b9502b16aac534e1c691afbe3dc5e125e5091aa35bea026c59b25ebe82e7", "urls": [ "https://snapshot.debian.org/archive/debian-security/20260314T202839Z/pool/updates/main/x/xz-utils/liblzma5_5.4.1-1_amd64.deb" ], "version": "5.4.1-1" }, { "arch": "amd64", "dependencies": [], "key": "libncursesw6_6.4-4_amd64", "name": "libncursesw6", "sha256": "98fa7a53dc565a38b65fb70422ad08001bf5361d8fbc74255280c329996a6bec", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/n/ncurses/libncursesw6_6.4-4_amd64.deb" ], "version": "6.4-4" }, { "arch": "amd64", "dependencies": [], "key": "libnsl2_1.3.0-2_amd64", "name": "libnsl2", "sha256": "c0d83437fdb016cb289436f49f28a36be44b3e8f1f2498c7e3a095f709c0d6f8", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/libn/libnsl/libnsl2_1.3.0-2_amd64.deb" ], "version": "1.3.0-2" }, { "arch": "amd64", "dependencies": [], "key": "libpython3.11-minimal_3.11.2-6-p-deb12u6_amd64", "name": "libpython3.11-minimal", "sha256": "b21639516f96bde030d9548220952ad17ed5dd602b6339ce183658c5aa4c1fb4", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/p/python3.11/libpython3.11-minimal_3.11.2-6+deb12u6_amd64.deb" ], "version": "3.11.2-6+deb12u6" }, { "arch": "amd64", "dependencies": [], "key": "libpython3.11-stdlib_3.11.2-6-p-deb12u6_amd64", "name": "libpython3.11-stdlib", "sha256": "409f354d3d5d5b605a5d2d359936e6c2262b6c8f2bb120ec530bc69cb318fac4", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/p/python3.11/libpython3.11-stdlib_3.11.2-6+deb12u6_amd64.deb" ], "version": "3.11.2-6+deb12u6" }, { "arch": "amd64", "dependencies": [], "key": "libreadline8_8.2-1.3_amd64", "name": "libreadline8", "sha256": "e02ebbd3701cf468dbf98d6d917fbe0325e881f07fe8b316150c8d2a64486e66", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/r/readline/libreadline8_8.2-1.3_amd64.deb" ], "version": "8.2-1.3" }, { "arch": "amd64", "dependencies": [], "key": "libsqlite3-0_3.40.1-2-p-deb12u2_amd64", "name": "libsqlite3-0", "sha256": "a8d78b40e9b4e422224aeebfe0e4dfc243f6acf3532490b0c05480d4283d41e2", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/s/sqlite3/libsqlite3-0_3.40.1-2+deb12u2_amd64.deb" ], "version": "3.40.1-2+deb12u2" }, { "arch": "amd64", "dependencies": [], "key": "libtinfo6_6.4-4_amd64", "name": "libtinfo6", "sha256": "072d908f38f51090ca28ca5afa3b46b2957dc61fe35094c0b851426859a49a51", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/n/ncurses/libtinfo6_6.4-4_amd64.deb" ], "version": "6.4-4" }, { "arch": "amd64", "dependencies": [], "key": "libtirpc3_1.3.3-p-ds-1_amd64", "name": "libtirpc3", "sha256": "2a46d5a5e9486da11ffeff5740931740d6deae4f92cd6098df060dc5dff1e1c7", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/libt/libtirpc/libtirpc3_1.3.3+ds-1_amd64.deb" ], "version": "1.3.3+ds-1" }, { "arch": "amd64", "dependencies": [], "key": "libuuid1_2.38.1-5-p-deb12u3_amd64", "name": "libuuid1", "sha256": "5fff398321da62d28a842bcbabd193d72ae21724962c029dc32b1dc6b2deaeaf", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/u/util-linux/libuuid1_2.38.1-5+deb12u3_amd64.deb" ], "version": "2.38.1-5+deb12u3" }, { "arch": "amd64", "dependencies": [], "key": "python3-distutils_3.11.2-3_amd64", "name": "python3-distutils", "sha256": "a620b555f301860a08e30534c7e6f7d79818e5e1977bfec39a612e7003074318", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/p/python3-stdlib-extensions/python3-distutils_3.11.2-3_all.deb" ], "version": "3.11.2-3" }, { "arch": "amd64", "dependencies": [], "key": "python3.11-minimal_3.11.2-6-p-deb12u6_amd64", "name": "python3.11-minimal", "sha256": "4742c49d9bc418eac8c60216af4b9280440f86d5ecf0816931fcc6774a6d90d4", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/p/python3.11/python3.11-minimal_3.11.2-6+deb12u6_amd64.deb" ], "version": "3.11.2-6+deb12u6" }, { "arch": "amd64", "dependencies": [], "key": "zlib1g_1-1.2.13.dfsg-1_amd64", "name": "zlib1g", "sha256": "d7dd1d1411fedf27f5e27650a6eff20ef294077b568f4c8c5e51466dc7c08ce4", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/z/zlib/zlib1g_1.2.13.dfsg-1_amd64.deb" ], "version": "1:1.2.13.dfsg-1" }, { "arch": "arm64", "dependencies": [], "key": "libbz2-1.0_1.0.8-5-p-b1_arm64", "name": "libbz2-1.0", "sha256": "d3a96ece03326498b39ff093a76800dfcbcb1d4049d6ae6e9f6fa1aa7a590ad6", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/b/bzip2/libbz2-1.0_1.0.8-5+b1_arm64.deb" ], "version": "1.0.8-5+b1" }, { "arch": "arm64", "dependencies": [], "key": "libcom-err2_1.47.0-2-p-b2_arm64", "name": "libcom-err2", "sha256": "36c15f933a965b50f4c9558d792d9556934c84e532703935d8ae7e69dd3fa863", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/e/e2fsprogs/libcom-err2_1.47.0-2+b2_arm64.deb" ], "version": "1.47.0-2+b2" }, { "arch": "arm64", "dependencies": [], "key": "libcrypt1_1-4.4.33-2_arm64", "name": "libcrypt1", "sha256": "eea0ad76ea5eb507127fea0c291622ea4ecdbb71c4b9a8ed9c76ae33fc1a0127", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/libx/libxcrypt/libcrypt1_4.4.33-2_arm64.deb" ], "version": "1:4.4.33-2" }, { "arch": "arm64", "dependencies": [], "key": "libdb5.3_5.3.28-p-dfsg2-1_arm64", "name": "libdb5.3", "sha256": "344367608d622298a3d916f4cee3dc3173286f3b21f8f497ab21e7178ba930f9", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/d/db5.3/libdb5.3_5.3.28+dfsg2-1_arm64.deb" ], "version": "5.3.28+dfsg2-1" }, { "arch": "arm64", "dependencies": [], "key": "libexpat1_2.5.0-1-p-deb12u2_arm64", "name": "libexpat1", "sha256": "8dc1976735acf825e3a922d82f171e20feec7394da2b8c616091983e38706275", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/e/expat/libexpat1_2.5.0-1+deb12u2_arm64.deb" ], "version": "2.5.0-1+deb12u2" }, { "arch": "arm64", "dependencies": [], "key": "libffi8_3.4.4-1_arm64", "name": "libffi8", "sha256": "80b5c36177dc0e29d531c7eddbed3cc7355cb490e49f8cfa5959572d161f27b3", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/libf/libffi/libffi8_3.4.4-1_arm64.deb" ], "version": "3.4.4-1" }, { "arch": "arm64", "dependencies": [], "key": "libgssapi-krb5-2_1.20.1-2-p-deb12u4_arm64", "name": "libgssapi-krb5-2", "sha256": "5dd7242e08da4b8e190b8c4bbad2a0f7b26d718bf98c332233362aface6fd44d", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/k/krb5/libgssapi-krb5-2_1.20.1-2+deb12u4_arm64.deb" ], "version": "1.20.1-2+deb12u4" }, { "arch": "arm64", "dependencies": [], "key": "libk5crypto3_1.20.1-2-p-deb12u4_arm64", "name": "libk5crypto3", "sha256": "e72fc6077826bcc070e56c11491f6032010269f1af0135ccb918bf90471add6b", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/k/krb5/libk5crypto3_1.20.1-2+deb12u4_arm64.deb" ], "version": "1.20.1-2+deb12u4" }, { "arch": "arm64", "dependencies": [], "key": "libkeyutils1_1.6.3-2_arm64", "name": "libkeyutils1", "sha256": "aac46cb6faec4e737502b3c2290b7b02f8ba04e8accd5af7fd07934df0c867b1", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/k/keyutils/libkeyutils1_1.6.3-2_arm64.deb" ], "version": "1.6.3-2" }, { "arch": "arm64", "dependencies": [], "key": "libkrb5-3_1.20.1-2-p-deb12u4_arm64", "name": "libkrb5-3", "sha256": "70599ea93ff9dacf0621f776faa4ae142b6cc0420f50dad7cf6bd2c1bcdad71b", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/k/krb5/libkrb5-3_1.20.1-2+deb12u4_arm64.deb" ], "version": "1.20.1-2+deb12u4" }, { "arch": "arm64", "dependencies": [], "key": "libkrb5support0_1.20.1-2-p-deb12u4_arm64", "name": "libkrb5support0", "sha256": "e201269c7fa36cc22a4edb680bc093a155a32fbef23ef2d65fef20907cee4ff7", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/k/krb5/libkrb5support0_1.20.1-2+deb12u4_arm64.deb" ], "version": "1.20.1-2+deb12u4" }, { "arch": "arm64", "dependencies": [], "key": "liblzma5_5.4.1-1_arm64", "name": "liblzma5", "sha256": "3d9b12d3f93d08205335624c2238518911f7b1ce3355c630b433561b3ca25cd4", "urls": [ "https://snapshot.debian.org/archive/debian-security/20260314T202839Z/pool/updates/main/x/xz-utils/liblzma5_5.4.1-1_arm64.deb" ], "version": "5.4.1-1" }, { "arch": "arm64", "dependencies": [], "key": "libncursesw6_6.4-4_arm64", "name": "libncursesw6", "sha256": "cf32cb6751718872c6def448b82211eec494f688e2f1a3e6c71bfdaf6b0722c5", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/n/ncurses/libncursesw6_6.4-4_arm64.deb" ], "version": "6.4-4" }, { "arch": "arm64", "dependencies": [], "key": "libnsl2_1.3.0-2_arm64", "name": "libnsl2", "sha256": "8f9ba58b219779b43c4ccc78c79b0a23f721fc96323c202abb31e02f942104b3", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/libn/libnsl/libnsl2_1.3.0-2_arm64.deb" ], "version": "1.3.0-2" }, { "arch": "arm64", "dependencies": [], "key": "libpython3.11-minimal_3.11.2-6-p-deb12u6_arm64", "name": "libpython3.11-minimal", "sha256": "c75c613fd294230221b05c4a65daecb9ccdb4da0076682b6a1ce67bdee9ad0fd", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/p/python3.11/libpython3.11-minimal_3.11.2-6+deb12u6_arm64.deb" ], "version": "3.11.2-6+deb12u6" }, { "arch": "arm64", "dependencies": [], "key": "libpython3.11-stdlib_3.11.2-6-p-deb12u6_arm64", "name": "libpython3.11-stdlib", "sha256": "d9043f4957804cd4c7bc0af4784c80c4a5d08002a0e9b67407da20b3b47e3676", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/p/python3.11/libpython3.11-stdlib_3.11.2-6+deb12u6_arm64.deb" ], "version": "3.11.2-6+deb12u6" }, { "arch": "arm64", "dependencies": [], "key": "libreadline8_8.2-1.3_arm64", "name": "libreadline8", "sha256": "f3b162b7c1e05430607e792ebdbfc417cbd1f1d32cf83664133ae63d811a72d2", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/r/readline/libreadline8_8.2-1.3_arm64.deb" ], "version": "8.2-1.3" }, { "arch": "arm64", "dependencies": [], "key": "libsqlite3-0_3.40.1-2-p-deb12u2_arm64", "name": "libsqlite3-0", "sha256": "a690f7f2aa6435bd1fd7cbbd2216acb9acbb8c48c9721f2c195766375439eb13", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/s/sqlite3/libsqlite3-0_3.40.1-2+deb12u2_arm64.deb" ], "version": "3.40.1-2+deb12u2" }, { "arch": "arm64", "dependencies": [], "key": "libtinfo6_6.4-4_arm64", "name": "libtinfo6", "sha256": "baef0f6776f84c7eed4f1146d6e5774689567dad43216894d41da02e6608e4b3", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/n/ncurses/libtinfo6_6.4-4_arm64.deb" ], "version": "6.4-4" }, { "arch": "arm64", "dependencies": [], "key": "libtirpc3_1.3.3-p-ds-1_arm64", "name": "libtirpc3", "sha256": "deaf9ea54f74cab6690b4bc0b427f05cbe62cc073580d84f5f18a8d9e2ece401", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/libt/libtirpc/libtirpc3_1.3.3+ds-1_arm64.deb" ], "version": "1.3.3+ds-1" }, { "arch": "arm64", "dependencies": [], "key": "libuuid1_2.38.1-5-p-deb12u3_arm64", "name": "libuuid1", "sha256": "3b2d19df0f3190108cf54228c4cfc822226c06d8f3615a5ab16a7dffb1f58aed", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/u/util-linux/libuuid1_2.38.1-5+deb12u3_arm64.deb" ], "version": "2.38.1-5+deb12u3" }, { "arch": "arm64", "dependencies": [], "key": "python3-distutils_3.11.2-3_arm64", "name": "python3-distutils", "sha256": "a620b555f301860a08e30534c7e6f7d79818e5e1977bfec39a612e7003074318", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/p/python3-stdlib-extensions/python3-distutils_3.11.2-3_all.deb" ], "version": "3.11.2-3" }, { "arch": "arm64", "dependencies": [], "key": "python3.11-minimal_3.11.2-6-p-deb12u6_arm64", "name": "python3.11-minimal", "sha256": "44196e58ef8c3ccae9d9f03055273d8cc647d27f93548ea76a1f96b0e531b8a1", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/p/python3.11/python3.11-minimal_3.11.2-6+deb12u6_arm64.deb" ], "version": "3.11.2-6+deb12u6" }, { "arch": "arm64", "dependencies": [], "key": "zlib1g_1-1.2.13.dfsg-1_arm64", "name": "zlib1g", "sha256": "52b8b8a145bbe1956bba82034f77022cbef0c3d0885c9e32d9817a7932fe1913", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/z/zlib/zlib1g_1.2.13.dfsg-1_arm64.deb" ], "version": "1:1.2.13.dfsg-1" } ], "version": 1 } ================================================ FILE: private/repos/deb/bookworm_python.yaml ================================================ # debian 12, limited architectures, python only version: 1 sources: - channel: bookworm main url: https://snapshot.debian.org/archive/debian/20260314T202839Z - channel: bookworm-updates main url: https://snapshot.debian.org/archive/debian/20260314T202839Z - channel: bookworm-security main url: https://snapshot.debian.org/archive/debian-security/20260314T202839Z archs: - amd64 - arm64 packages: - libbz2-1.0 - libcom-err2 - libcrypt1 # TODO: glibc library for -lcrypt; maybe should be in cc? - libdb5.3 - libexpat1 - libffi8 - libgssapi-krb5-2 - libk5crypto3 - libkeyutils1 - libkrb5-3 - libkrb5support0 - liblzma5 - libncursesw6 - libnsl2 - libpython3.11-minimal - libpython3.11-stdlib - libreadline8 - libsqlite3-0 - libtinfo6 - libtirpc3 - libuuid1 - python3-distutils - python3.11-minimal - zlib1g ================================================ FILE: private/repos/deb/deb.MODULE.bazel ================================================ "debian dependencies" REPOS = [ "trixie", "trixie_java", "trixie_adoptium", "trixie_python", "bookworm", "bookworm_python", ] apt = use_extension("@rules_distroless//apt:extensions.bzl", "apt") [ apt.install( name = repo, lock = "//private/repos/deb:{}.lock.json".format(repo), manifest = "//private/repos/deb:{}.yaml".format(repo), ## merged usr fs is only enabled on debian13+, remove this line once we remove debian12 builds mergedusr = repo.startswith("trixie"), package_template = "//private/repos/deb:package.BUILD.tmpl", resolve_transitive = False, ) for repo in REPOS ] use_repo(apt, "bookworm", "bookworm_python", "trixie", "trixie_adoptium", "trixie_java", "trixie_python") ### VERSIONS HUB REPO ### version = use_extension("//private/extensions:version.bzl", "version") [ version.from_lock( lock = "//private/repos/deb:{}.lock.json".format(repo), repo_name = repo, ) for repo in REPOS ] use_repo(version, "versions") ================================================ FILE: private/repos/deb/package.BUILD.tmpl ================================================ """Generated by distroless. DO NOT EDIT!""" load("@@//private/pkg:debian_spdx.bzl", "debian_spdx") load("@@//private/util:merge_providers.bzl", "merge_providers") load("@@rules_distroless~//apt:defs.bzl", "dpkg_statusd") load("@@//private/util:tar.bzl", "tar") alias( name = "control", actual = "@{repo_name}//:control", visibility = ["//visibility:public"] ) alias( name = "data", actual = "@{repo_name}//:data", visibility = ["//visibility:public"] ) dpkg_statusd( name = "statusd", control = ":control", package_name = "{name}" ) tar( name = "data_statusd", extension = "tar.gz", package_dir = "./", deps = [ ":data", ":statusd" ] ) debian_spdx( name = "spdx", control = ":control", data = ":data", package_name = "{name}", spdx_id = "{repo_name}", sha256 = "{sha256}", urls = {urls} ) merge_providers( name = "{target_name}", srcs = [":data_statusd", ":spdx"], visibility = ["//visibility:public"], ) ================================================ FILE: private/repos/deb/trixie.lock.json ================================================ { "packages": [ { "arch": "amd64", "dependencies": [], "key": "base-files_13.8-p-deb13u4_amd64", "name": "base-files", "sha256": "819e70a077c6b94d72c1385cc18a512446ded629499f7bb7d84d727977b67ad4", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/b/base-files/base-files_13.8+deb13u4_amd64.deb" ], "version": "13.8+deb13u4" }, { "arch": "amd64", "dependencies": [], "key": "ca-certificates_20250419_amd64", "name": "ca-certificates", "sha256": "ef590f89563aa4b46c8260d49d1cea0fc1b181d19e8df3782694706adf05c184", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/c/ca-certificates/ca-certificates_20250419_all.deb" ], "version": "20250419" }, { "arch": "amd64", "dependencies": [], "key": "libc6_2.41-12-p-deb13u2_amd64", "name": "libc6", "sha256": "8f9ddeb958cec3a05c4c303d4c85fddf30cb994747b16b1eb715ac49049f6d4a", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/glibc/libc6_2.41-12+deb13u2_amd64.deb" ], "version": "2.41-12+deb13u2" }, { "arch": "amd64", "dependencies": [], "key": "libc-bin_2.41-12-p-deb13u2_amd64", "name": "libc-bin", "sha256": "e30df1bcd947889cd96b5a094e0bf6be6acb4d6d7d2b6def0507f36b432916be", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/glibc/libc-bin_2.41-12+deb13u2_amd64.deb" ], "version": "2.41-12+deb13u2" }, { "arch": "amd64", "dependencies": [], "key": "libssl3t64_3.5.5-1_deb13u1_amd64", "name": "libssl3t64", "sha256": "9a5d0bc0c5fcdd11e8d70bf01ab444a10aebae7d90ea6e25f93ddc797b134dbc", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/o/openssl/libssl3t64_3.5.5-1~deb13u1_amd64.deb" ], "version": "3.5.5-1~deb13u1" }, { "arch": "amd64", "dependencies": [], "key": "netbase_6.5_amd64", "name": "netbase", "sha256": "76bafa92947ebd37b0a6f9ec6570412041f56edebc1c66d323731216d318471e", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/n/netbase/netbase_6.5_all.deb" ], "version": "6.5" }, { "arch": "amd64", "dependencies": [], "key": "openssl_3.5.5-1_deb13u1_amd64", "name": "openssl", "sha256": "233d6d1f6ff00509cba554365e7cfb3be36db1dea57291eeb248f2c04d62719d", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/o/openssl/openssl_3.5.5-1~deb13u1_amd64.deb" ], "version": "3.5.5-1~deb13u1" }, { "arch": "amd64", "dependencies": [], "key": "tzdata_2026a-0-p-deb13u1_amd64", "name": "tzdata", "sha256": "9fb91a8d4f4f852918d14b1379f788c1c4971cf640c4bda7f568e7601620a874", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/t/tzdata/tzdata_2026a-0+deb13u1_all.deb" ], "version": "2026a-0+deb13u1" }, { "arch": "amd64", "dependencies": [], "key": "tzdata-legacy_2026a-0-p-deb13u1_amd64", "name": "tzdata-legacy", "sha256": "f402289df6fd7f698e0f073da0e260e3365be368243a66bf2a2b940f37554b1c", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/t/tzdata/tzdata-legacy_2026a-0+deb13u1_all.deb" ], "version": "2026a-0+deb13u1" }, { "arch": "amd64", "dependencies": [], "key": "media-types_13.0.0_amd64", "name": "media-types", "sha256": "0788e4b0b72db1bcf74a19cb24c3511e7770ad0b341f0f30e361701c3072f53e", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/m/media-types/media-types_13.0.0_all.deb" ], "version": "13.0.0" }, { "arch": "amd64", "dependencies": [], "key": "zlib1g_1-1.3.dfsg-p-really1.3.1-1-p-b1_amd64", "name": "zlib1g", "sha256": "015be740d6236ad114582dea500c1d907f29e16d6db00566ca32fb68d71ac90d", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/z/zlib/zlib1g_1.3.dfsg+really1.3.1-1+b1_amd64.deb" ], "version": "1:1.3.dfsg+really1.3.1-1+b1" }, { "arch": "amd64", "dependencies": [], "key": "libzstd1_1.5.7-p-dfsg-1_amd64", "name": "libzstd1", "sha256": "2f6a2aeacfc925eba8b00ac9139bc4bfccf8cacb09eb93de067074b26948eef9", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/libz/libzstd/libzstd1_1.5.7+dfsg-1_amd64.deb" ], "version": "1.5.7+dfsg-1" }, { "arch": "amd64", "dependencies": [], "key": "gcc-14-base_14.2.0-19_amd64", "name": "gcc-14-base", "sha256": "5b6825de4263824b78c4c51f6476414f3b4e89c2ab63e81dc8b9b5501e867cf6", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-14/gcc-14-base_14.2.0-19_amd64.deb" ], "version": "14.2.0-19" }, { "arch": "amd64", "dependencies": [], "key": "libgcc-s1_14.2.0-19_amd64", "name": "libgcc-s1", "sha256": "3c71917b490d1a17aed43196a2787a256ecf060526cdb20216a74bedc061b150", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-14/libgcc-s1_14.2.0-19_amd64.deb" ], "version": "14.2.0-19" }, { "arch": "amd64", "dependencies": [], "key": "libgomp1_14.2.0-19_amd64", "name": "libgomp1", "sha256": "72b7a1a33c48f3195efeb044111b34ae684b1e640bb6495c832443b798601cd5", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-14/libgomp1_14.2.0-19_amd64.deb" ], "version": "14.2.0-19" }, { "arch": "amd64", "dependencies": [], "key": "libstdc-p--p-6_14.2.0-19_amd64", "name": "libstdc++6", "sha256": "ab1fa05837aa7a92aae748fd07a18a35f7d18bb4a71c4724fe2bbf0e32089de0", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-14/libstdc++6_14.2.0-19_amd64.deb" ], "version": "14.2.0-19" }, { "arch": "arm64", "dependencies": [], "key": "base-files_13.8-p-deb13u4_arm64", "name": "base-files", "sha256": "d4493ac8b04311c4e393ccf87b8413155912aabe551f67877f9487c1f16cee69", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/b/base-files/base-files_13.8+deb13u4_arm64.deb" ], "version": "13.8+deb13u4" }, { "arch": "arm64", "dependencies": [], "key": "ca-certificates_20250419_arm64", "name": "ca-certificates", "sha256": "ef590f89563aa4b46c8260d49d1cea0fc1b181d19e8df3782694706adf05c184", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/c/ca-certificates/ca-certificates_20250419_all.deb" ], "version": "20250419" }, { "arch": "arm64", "dependencies": [], "key": "libc6_2.41-12-p-deb13u2_arm64", "name": "libc6", "sha256": "f4679f22ee71be9f79bb36c62bb0b6fed97c19f245d2afaf8a9c1d000a1d312a", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/glibc/libc6_2.41-12+deb13u2_arm64.deb" ], "version": "2.41-12+deb13u2" }, { "arch": "arm64", "dependencies": [], "key": "libc-bin_2.41-12-p-deb13u2_arm64", "name": "libc-bin", "sha256": "c533ba20b97e8cec1ad816936043e7c2cfa24e724e13e99eaa66cad74fbff0c8", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/glibc/libc-bin_2.41-12+deb13u2_arm64.deb" ], "version": "2.41-12+deb13u2" }, { "arch": "arm64", "dependencies": [], "key": "libssl3t64_3.5.5-1_deb13u1_arm64", "name": "libssl3t64", "sha256": "7273dabe9471b474bcbceffd1caf7207e37fa7d7e4974cfb033c1ea2f6f3ef51", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/o/openssl/libssl3t64_3.5.5-1~deb13u1_arm64.deb" ], "version": "3.5.5-1~deb13u1" }, { "arch": "arm64", "dependencies": [], "key": "netbase_6.5_arm64", "name": "netbase", "sha256": "76bafa92947ebd37b0a6f9ec6570412041f56edebc1c66d323731216d318471e", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/n/netbase/netbase_6.5_all.deb" ], "version": "6.5" }, { "arch": "arm64", "dependencies": [], "key": "openssl_3.5.5-1_deb13u1_arm64", "name": "openssl", "sha256": "92dfcdc213cd7a5e6aa34a1ac9660a59e56838d12876f4b34599f8fea39cb432", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/o/openssl/openssl_3.5.5-1~deb13u1_arm64.deb" ], "version": "3.5.5-1~deb13u1" }, { "arch": "arm64", "dependencies": [], "key": "tzdata_2026a-0-p-deb13u1_arm64", "name": "tzdata", "sha256": "9fb91a8d4f4f852918d14b1379f788c1c4971cf640c4bda7f568e7601620a874", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/t/tzdata/tzdata_2026a-0+deb13u1_all.deb" ], "version": "2026a-0+deb13u1" }, { "arch": "arm64", "dependencies": [], "key": "tzdata-legacy_2026a-0-p-deb13u1_arm64", "name": "tzdata-legacy", "sha256": "f402289df6fd7f698e0f073da0e260e3365be368243a66bf2a2b940f37554b1c", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/t/tzdata/tzdata-legacy_2026a-0+deb13u1_all.deb" ], "version": "2026a-0+deb13u1" }, { "arch": "arm64", "dependencies": [], "key": "media-types_13.0.0_arm64", "name": "media-types", "sha256": "0788e4b0b72db1bcf74a19cb24c3511e7770ad0b341f0f30e361701c3072f53e", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/m/media-types/media-types_13.0.0_all.deb" ], "version": "13.0.0" }, { "arch": "arm64", "dependencies": [], "key": "zlib1g_1-1.3.dfsg-p-really1.3.1-1-p-b1_arm64", "name": "zlib1g", "sha256": "209aa5cf671e97b9eb0410844fa6df4cae2e75b0c72e7802ab6c8ece13e6ddef", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/z/zlib/zlib1g_1.3.dfsg+really1.3.1-1+b1_arm64.deb" ], "version": "1:1.3.dfsg+really1.3.1-1+b1" }, { "arch": "arm64", "dependencies": [], "key": "libzstd1_1.5.7-p-dfsg-1_arm64", "name": "libzstd1", "sha256": "924540bd59fdbfa77a0604360efdaca54411a43daf11c7e002a3c64791b67448", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/libz/libzstd/libzstd1_1.5.7+dfsg-1_arm64.deb" ], "version": "1.5.7+dfsg-1" }, { "arch": "arm64", "dependencies": [], "key": "gcc-14-base_14.2.0-19_arm64", "name": "gcc-14-base", "sha256": "34ee90679b018c0e64234747a4c4c0ae6b7f63541115037465a8627c2dfbc594", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-14/gcc-14-base_14.2.0-19_arm64.deb" ], "version": "14.2.0-19" }, { "arch": "arm64", "dependencies": [], "key": "libgcc-s1_14.2.0-19_arm64", "name": "libgcc-s1", "sha256": "1108bc87879833d6d9a145f22a4a15cddb34e065b4b5f4b97bee586adbac2851", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-14/libgcc-s1_14.2.0-19_arm64.deb" ], "version": "14.2.0-19" }, { "arch": "arm64", "dependencies": [], "key": "libgomp1_14.2.0-19_arm64", "name": "libgomp1", "sha256": "43e84cb7971d8a4d8870cab6204e998ea4f23ee1339bb0ff556dd881bac82d25", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-14/libgomp1_14.2.0-19_arm64.deb" ], "version": "14.2.0-19" }, { "arch": "arm64", "dependencies": [], "key": "libstdc-p--p-6_14.2.0-19_arm64", "name": "libstdc++6", "sha256": "6669b0c52a2e7c6af9adfdabce3ff6e286065cdfbc7b85280862b5f799daebee", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-14/libstdc++6_14.2.0-19_arm64.deb" ], "version": "14.2.0-19" }, { "arch": "armhf", "dependencies": [], "key": "base-files_13.8-p-deb13u4_armhf", "name": "base-files", "sha256": "c18f87e0b0bfc9832c805adffb9dfc1f2642ead53e447b105098334241d3b40f", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/b/base-files/base-files_13.8+deb13u4_armhf.deb" ], "version": "13.8+deb13u4" }, { "arch": "armhf", "dependencies": [], "key": "ca-certificates_20250419_armhf", "name": "ca-certificates", "sha256": "ef590f89563aa4b46c8260d49d1cea0fc1b181d19e8df3782694706adf05c184", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/c/ca-certificates/ca-certificates_20250419_all.deb" ], "version": "20250419" }, { "arch": "armhf", "dependencies": [], "key": "libc6_2.41-12-p-deb13u2_armhf", "name": "libc6", "sha256": "5111f0399bdcd0e7cc517cf5d0a7796649c364c11f1e2cd52cce89fe30d230f8", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/glibc/libc6_2.41-12+deb13u2_armhf.deb" ], "version": "2.41-12+deb13u2" }, { "arch": "armhf", "dependencies": [], "key": "libc-bin_2.41-12-p-deb13u2_armhf", "name": "libc-bin", "sha256": "81e7d78ef525e9bf4052e720adb85682827c37e23bfaa3083b898953211bceb0", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/glibc/libc-bin_2.41-12+deb13u2_armhf.deb" ], "version": "2.41-12+deb13u2" }, { "arch": "armhf", "dependencies": [], "key": "libssl3t64_3.5.5-1_deb13u1_armhf", "name": "libssl3t64", "sha256": "6a46fcc84c641c72df3fd1fe2a1e919aed9ca05176c4b444963b8cdf38e8bf78", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/o/openssl/libssl3t64_3.5.5-1~deb13u1_armhf.deb" ], "version": "3.5.5-1~deb13u1" }, { "arch": "armhf", "dependencies": [], "key": "netbase_6.5_armhf", "name": "netbase", "sha256": "76bafa92947ebd37b0a6f9ec6570412041f56edebc1c66d323731216d318471e", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/n/netbase/netbase_6.5_all.deb" ], "version": "6.5" }, { "arch": "armhf", "dependencies": [], "key": "openssl_3.5.5-1_deb13u1_armhf", "name": "openssl", "sha256": "79fc2bdd6a2dd5682110a4e6d6d6349e16e3d691831ec0cb299699b0821ea157", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/o/openssl/openssl_3.5.5-1~deb13u1_armhf.deb" ], "version": "3.5.5-1~deb13u1" }, { "arch": "armhf", "dependencies": [], "key": "tzdata_2026a-0-p-deb13u1_armhf", "name": "tzdata", "sha256": "9fb91a8d4f4f852918d14b1379f788c1c4971cf640c4bda7f568e7601620a874", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/t/tzdata/tzdata_2026a-0+deb13u1_all.deb" ], "version": "2026a-0+deb13u1" }, { "arch": "armhf", "dependencies": [], "key": "tzdata-legacy_2026a-0-p-deb13u1_armhf", "name": "tzdata-legacy", "sha256": "f402289df6fd7f698e0f073da0e260e3365be368243a66bf2a2b940f37554b1c", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/t/tzdata/tzdata-legacy_2026a-0+deb13u1_all.deb" ], "version": "2026a-0+deb13u1" }, { "arch": "armhf", "dependencies": [], "key": "media-types_13.0.0_armhf", "name": "media-types", "sha256": "0788e4b0b72db1bcf74a19cb24c3511e7770ad0b341f0f30e361701c3072f53e", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/m/media-types/media-types_13.0.0_all.deb" ], "version": "13.0.0" }, { "arch": "armhf", "dependencies": [], "key": "zlib1g_1-1.3.dfsg-p-really1.3.1-1-p-b1_armhf", "name": "zlib1g", "sha256": "81c55a59e1570477ecef6a449bf6dce44dad67ba4ce9e04760451d4cfe200534", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/z/zlib/zlib1g_1.3.dfsg+really1.3.1-1+b1_armhf.deb" ], "version": "1:1.3.dfsg+really1.3.1-1+b1" }, { "arch": "armhf", "dependencies": [], "key": "libzstd1_1.5.7-p-dfsg-1_armhf", "name": "libzstd1", "sha256": "da5238dd84fc51f782f39d435821bff556409b3dbc82d232e4e81f427fb1ca65", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/libz/libzstd/libzstd1_1.5.7+dfsg-1_armhf.deb" ], "version": "1.5.7+dfsg-1" }, { "arch": "armhf", "dependencies": [], "key": "gcc-14-base_14.2.0-19_armhf", "name": "gcc-14-base", "sha256": "0f702fdd5e5471efda9fece892e09ce73e3447968083e1f8c341f8b66b1fb340", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-14/gcc-14-base_14.2.0-19_armhf.deb" ], "version": "14.2.0-19" }, { "arch": "armhf", "dependencies": [], "key": "libgcc-s1_14.2.0-19_armhf", "name": "libgcc-s1", "sha256": "25910c3a0bce3985e388de445244578b7922dc670c9bba1c8673779b89447873", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-14/libgcc-s1_14.2.0-19_armhf.deb" ], "version": "14.2.0-19" }, { "arch": "armhf", "dependencies": [], "key": "libgomp1_14.2.0-19_armhf", "name": "libgomp1", "sha256": "00e56cbc41157ce7139b758b422133ab2a75bdfc71ee5c8c2ab8dbdc98cb2dbf", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-14/libgomp1_14.2.0-19_armhf.deb" ], "version": "14.2.0-19" }, { "arch": "armhf", "dependencies": [], "key": "libstdc-p--p-6_14.2.0-19_armhf", "name": "libstdc++6", "sha256": "9c82eecc30961a3da3e062c0dba8ce076736059f4b8e7794c803985e75aea48b", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-14/libstdc++6_14.2.0-19_armhf.deb" ], "version": "14.2.0-19" }, { "arch": "s390x", "dependencies": [], "key": "base-files_13.8-p-deb13u4_s390x", "name": "base-files", "sha256": "1d8657244ce4944696cfc7b9cbb3464133dc913ef20abea8e481afc906b24b2c", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/b/base-files/base-files_13.8+deb13u4_s390x.deb" ], "version": "13.8+deb13u4" }, { "arch": "s390x", "dependencies": [], "key": "ca-certificates_20250419_s390x", "name": "ca-certificates", "sha256": "ef590f89563aa4b46c8260d49d1cea0fc1b181d19e8df3782694706adf05c184", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/c/ca-certificates/ca-certificates_20250419_all.deb" ], "version": "20250419" }, { "arch": "s390x", "dependencies": [], "key": "libc6_2.41-12-p-deb13u2_s390x", "name": "libc6", "sha256": "d896feb7b84aae53707ad7d2f842232a9ed1df4f29cecf2ec3a761fda91ea43b", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/glibc/libc6_2.41-12+deb13u2_s390x.deb" ], "version": "2.41-12+deb13u2" }, { "arch": "s390x", "dependencies": [], "key": "libc-bin_2.41-12-p-deb13u2_s390x", "name": "libc-bin", "sha256": "dd6b635d449b0f9238028ea8ce17b2a2e2f71f915444e8c4fbb8ad9386d37fcd", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/glibc/libc-bin_2.41-12+deb13u2_s390x.deb" ], "version": "2.41-12+deb13u2" }, { "arch": "s390x", "dependencies": [], "key": "libssl3t64_3.5.5-1_deb13u1_s390x", "name": "libssl3t64", "sha256": "3aec6fa7c116f3f59f65816c3244194cfa1b4bc6bb9fd1b1a8d0c7b5ea9a1c83", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/o/openssl/libssl3t64_3.5.5-1~deb13u1_s390x.deb" ], "version": "3.5.5-1~deb13u1" }, { "arch": "s390x", "dependencies": [], "key": "netbase_6.5_s390x", "name": "netbase", "sha256": "76bafa92947ebd37b0a6f9ec6570412041f56edebc1c66d323731216d318471e", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/n/netbase/netbase_6.5_all.deb" ], "version": "6.5" }, { "arch": "s390x", "dependencies": [], "key": "openssl_3.5.5-1_deb13u1_s390x", "name": "openssl", "sha256": "8eda97cd22dc15e525e6fea05fc49433ece3298d2183302a74ee7bffebbe3274", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/o/openssl/openssl_3.5.5-1~deb13u1_s390x.deb" ], "version": "3.5.5-1~deb13u1" }, { "arch": "s390x", "dependencies": [], "key": "tzdata_2026a-0-p-deb13u1_s390x", "name": "tzdata", "sha256": "9fb91a8d4f4f852918d14b1379f788c1c4971cf640c4bda7f568e7601620a874", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/t/tzdata/tzdata_2026a-0+deb13u1_all.deb" ], "version": "2026a-0+deb13u1" }, { "arch": "s390x", "dependencies": [], "key": "tzdata-legacy_2026a-0-p-deb13u1_s390x", "name": "tzdata-legacy", "sha256": "f402289df6fd7f698e0f073da0e260e3365be368243a66bf2a2b940f37554b1c", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/t/tzdata/tzdata-legacy_2026a-0+deb13u1_all.deb" ], "version": "2026a-0+deb13u1" }, { "arch": "s390x", "dependencies": [], "key": "media-types_13.0.0_s390x", "name": "media-types", "sha256": "0788e4b0b72db1bcf74a19cb24c3511e7770ad0b341f0f30e361701c3072f53e", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/m/media-types/media-types_13.0.0_all.deb" ], "version": "13.0.0" }, { "arch": "s390x", "dependencies": [], "key": "zlib1g_1-1.3.dfsg-p-really1.3.1-1-p-b1_s390x", "name": "zlib1g", "sha256": "e38a94c60e944dfcf1937a12b02785afbbb2bedf356da18984c4dac0acc47ed9", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/z/zlib/zlib1g_1.3.dfsg+really1.3.1-1+b1_s390x.deb" ], "version": "1:1.3.dfsg+really1.3.1-1+b1" }, { "arch": "s390x", "dependencies": [], "key": "libzstd1_1.5.7-p-dfsg-1_s390x", "name": "libzstd1", "sha256": "ed6bd13718360720b0a03d62e2440bd926b1db3b7443f46314fe3deb7e69989e", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/libz/libzstd/libzstd1_1.5.7+dfsg-1_s390x.deb" ], "version": "1.5.7+dfsg-1" }, { "arch": "s390x", "dependencies": [], "key": "gcc-14-base_14.2.0-19_s390x", "name": "gcc-14-base", "sha256": "7db20fd710eadefff128e82b4d4de68b466ce2aa1c53255004eb1d3d1d168495", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-14/gcc-14-base_14.2.0-19_s390x.deb" ], "version": "14.2.0-19" }, { "arch": "s390x", "dependencies": [], "key": "libgcc-s1_14.2.0-19_s390x", "name": "libgcc-s1", "sha256": "b5e87f11a8ac0537d500bf2dba37165bf8d25b5b44add1035a32deddbd4bfdda", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-14/libgcc-s1_14.2.0-19_s390x.deb" ], "version": "14.2.0-19" }, { "arch": "s390x", "dependencies": [], "key": "libgomp1_14.2.0-19_s390x", "name": "libgomp1", "sha256": "7297625ed2bd024f2fbb013a3a2c291cd4b0d5fb02afccaeba85c4cb8c386a2d", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-14/libgomp1_14.2.0-19_s390x.deb" ], "version": "14.2.0-19" }, { "arch": "s390x", "dependencies": [], "key": "libstdc-p--p-6_14.2.0-19_s390x", "name": "libstdc++6", "sha256": "6a91f4a1c8c30dc6d0a23ad7ead8a56271b9f6966d6d74734f4b423cdfe5c21b", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-14/libstdc++6_14.2.0-19_s390x.deb" ], "version": "14.2.0-19" }, { "arch": "ppc64el", "dependencies": [], "key": "base-files_13.8-p-deb13u4_ppc64el", "name": "base-files", "sha256": "ce2583fae881bb3abbf78cf81937877ce79a1527deaa9245c5b1ee4fd70533bc", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/b/base-files/base-files_13.8+deb13u4_ppc64el.deb" ], "version": "13.8+deb13u4" }, { "arch": "ppc64el", "dependencies": [], "key": "ca-certificates_20250419_ppc64el", "name": "ca-certificates", "sha256": "ef590f89563aa4b46c8260d49d1cea0fc1b181d19e8df3782694706adf05c184", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/c/ca-certificates/ca-certificates_20250419_all.deb" ], "version": "20250419" }, { "arch": "ppc64el", "dependencies": [], "key": "libc6_2.41-12-p-deb13u2_ppc64el", "name": "libc6", "sha256": "eb4ae10394bec4d04449bc029b953f1fc8d8a7958b8f881addce25e65f56ecce", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/glibc/libc6_2.41-12+deb13u2_ppc64el.deb" ], "version": "2.41-12+deb13u2" }, { "arch": "ppc64el", "dependencies": [], "key": "libc-bin_2.41-12-p-deb13u2_ppc64el", "name": "libc-bin", "sha256": "fce65b28edb8e02457e65aea16a63d3d5b4ec69cc7616b1c7620124aac4b39ed", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/glibc/libc-bin_2.41-12+deb13u2_ppc64el.deb" ], "version": "2.41-12+deb13u2" }, { "arch": "ppc64el", "dependencies": [], "key": "libssl3t64_3.5.5-1_deb13u1_ppc64el", "name": "libssl3t64", "sha256": "498840dfa4bb1e5abd3f01c867a0f8e7dcbb5433c0c529d4d57e5031a511e5ac", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/o/openssl/libssl3t64_3.5.5-1~deb13u1_ppc64el.deb" ], "version": "3.5.5-1~deb13u1" }, { "arch": "ppc64el", "dependencies": [], "key": "netbase_6.5_ppc64el", "name": "netbase", "sha256": "76bafa92947ebd37b0a6f9ec6570412041f56edebc1c66d323731216d318471e", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/n/netbase/netbase_6.5_all.deb" ], "version": "6.5" }, { "arch": "ppc64el", "dependencies": [], "key": "openssl_3.5.5-1_deb13u1_ppc64el", "name": "openssl", "sha256": "4a02e74427acdd82f7dc11b0442a46ba50db2fe8a1e0bbf36afcd85b574a3e1d", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/o/openssl/openssl_3.5.5-1~deb13u1_ppc64el.deb" ], "version": "3.5.5-1~deb13u1" }, { "arch": "ppc64el", "dependencies": [], "key": "tzdata_2026a-0-p-deb13u1_ppc64el", "name": "tzdata", "sha256": "9fb91a8d4f4f852918d14b1379f788c1c4971cf640c4bda7f568e7601620a874", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/t/tzdata/tzdata_2026a-0+deb13u1_all.deb" ], "version": "2026a-0+deb13u1" }, { "arch": "ppc64el", "dependencies": [], "key": "tzdata-legacy_2026a-0-p-deb13u1_ppc64el", "name": "tzdata-legacy", "sha256": "f402289df6fd7f698e0f073da0e260e3365be368243a66bf2a2b940f37554b1c", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/t/tzdata/tzdata-legacy_2026a-0+deb13u1_all.deb" ], "version": "2026a-0+deb13u1" }, { "arch": "ppc64el", "dependencies": [], "key": "media-types_13.0.0_ppc64el", "name": "media-types", "sha256": "0788e4b0b72db1bcf74a19cb24c3511e7770ad0b341f0f30e361701c3072f53e", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/m/media-types/media-types_13.0.0_all.deb" ], "version": "13.0.0" }, { "arch": "ppc64el", "dependencies": [], "key": "zlib1g_1-1.3.dfsg-p-really1.3.1-1-p-b1_ppc64el", "name": "zlib1g", "sha256": "f526e830310db11983cf51cfde95a74bc449a7bdc44b6ce68827d78802f1b4ae", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/z/zlib/zlib1g_1.3.dfsg+really1.3.1-1+b1_ppc64el.deb" ], "version": "1:1.3.dfsg+really1.3.1-1+b1" }, { "arch": "ppc64el", "dependencies": [], "key": "libzstd1_1.5.7-p-dfsg-1_ppc64el", "name": "libzstd1", "sha256": "1cdefa11a7d31bb36b610d4e44551870a44dfc6cac8359ebe9f9061a4f830773", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/libz/libzstd/libzstd1_1.5.7+dfsg-1_ppc64el.deb" ], "version": "1.5.7+dfsg-1" }, { "arch": "ppc64el", "dependencies": [], "key": "gcc-14-base_14.2.0-19_ppc64el", "name": "gcc-14-base", "sha256": "ebb80291fedd8db88488eef76573df0b4a1a11648a16406d9a0c0d4aaf229593", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-14/gcc-14-base_14.2.0-19_ppc64el.deb" ], "version": "14.2.0-19" }, { "arch": "ppc64el", "dependencies": [], "key": "libgcc-s1_14.2.0-19_ppc64el", "name": "libgcc-s1", "sha256": "9fef01c88bc508ff05ff9ce5d0cc05de36798591e060b07749c3835616ed5696", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-14/libgcc-s1_14.2.0-19_ppc64el.deb" ], "version": "14.2.0-19" }, { "arch": "ppc64el", "dependencies": [], "key": "libgomp1_14.2.0-19_ppc64el", "name": "libgomp1", "sha256": "cca95ab0ba3537a573c1d2796b8c1a00ef2839766fbb01b7b8882f47b2d504bb", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-14/libgomp1_14.2.0-19_ppc64el.deb" ], "version": "14.2.0-19" }, { "arch": "ppc64el", "dependencies": [], "key": "libstdc-p--p-6_14.2.0-19_ppc64el", "name": "libstdc++6", "sha256": "ee601ab87b7c7ac01f3d7be0fe2423f0ddc3a51b46d3331b4e9dff4110e6a8b9", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-14/libstdc++6_14.2.0-19_ppc64el.deb" ], "version": "14.2.0-19" }, { "arch": "riscv64", "dependencies": [], "key": "base-files_13.8-p-deb13u4_riscv64", "name": "base-files", "sha256": "80ed884c8808860b4aa0a1e8e27b5ffe9ae6f4f3f1ff1f609ec6bab88c7ab437", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/b/base-files/base-files_13.8+deb13u4_riscv64.deb" ], "version": "13.8+deb13u4" }, { "arch": "riscv64", "dependencies": [], "key": "ca-certificates_20250419_riscv64", "name": "ca-certificates", "sha256": "ef590f89563aa4b46c8260d49d1cea0fc1b181d19e8df3782694706adf05c184", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/c/ca-certificates/ca-certificates_20250419_all.deb" ], "version": "20250419" }, { "arch": "riscv64", "dependencies": [], "key": "libc6_2.41-12-p-deb13u2_riscv64", "name": "libc6", "sha256": "3c80d1019eb1d15c5d941bda85bab8358621d46408099ba2bc08ac4512c2fe0c", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/glibc/libc6_2.41-12+deb13u2_riscv64.deb" ], "version": "2.41-12+deb13u2" }, { "arch": "riscv64", "dependencies": [], "key": "libc-bin_2.41-12-p-deb13u2_riscv64", "name": "libc-bin", "sha256": "4b03a077476ed203f0edd56339a8d2b91a6b12ae1cc801db2ac917ad07b05617", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/glibc/libc-bin_2.41-12+deb13u2_riscv64.deb" ], "version": "2.41-12+deb13u2" }, { "arch": "riscv64", "dependencies": [], "key": "libssl3t64_3.5.5-1_deb13u1_riscv64", "name": "libssl3t64", "sha256": "3f07bbe787738e37733b094195cd073451ca722bad41462630b6a1146664673c", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/o/openssl/libssl3t64_3.5.5-1~deb13u1_riscv64.deb" ], "version": "3.5.5-1~deb13u1" }, { "arch": "riscv64", "dependencies": [], "key": "netbase_6.5_riscv64", "name": "netbase", "sha256": "76bafa92947ebd37b0a6f9ec6570412041f56edebc1c66d323731216d318471e", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/n/netbase/netbase_6.5_all.deb" ], "version": "6.5" }, { "arch": "riscv64", "dependencies": [], "key": "openssl_3.5.5-1_deb13u1_riscv64", "name": "openssl", "sha256": "d035fac9cd37b94a8a2cd571816ff4ce1630ddcc7ca8f81d5b351affed71671e", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/o/openssl/openssl_3.5.5-1~deb13u1_riscv64.deb" ], "version": "3.5.5-1~deb13u1" }, { "arch": "riscv64", "dependencies": [], "key": "tzdata_2026a-0-p-deb13u1_riscv64", "name": "tzdata", "sha256": "9fb91a8d4f4f852918d14b1379f788c1c4971cf640c4bda7f568e7601620a874", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/t/tzdata/tzdata_2026a-0+deb13u1_all.deb" ], "version": "2026a-0+deb13u1" }, { "arch": "riscv64", "dependencies": [], "key": "tzdata-legacy_2026a-0-p-deb13u1_riscv64", "name": "tzdata-legacy", "sha256": "f402289df6fd7f698e0f073da0e260e3365be368243a66bf2a2b940f37554b1c", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/t/tzdata/tzdata-legacy_2026a-0+deb13u1_all.deb" ], "version": "2026a-0+deb13u1" }, { "arch": "riscv64", "dependencies": [], "key": "media-types_13.0.0_riscv64", "name": "media-types", "sha256": "0788e4b0b72db1bcf74a19cb24c3511e7770ad0b341f0f30e361701c3072f53e", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/m/media-types/media-types_13.0.0_all.deb" ], "version": "13.0.0" }, { "arch": "riscv64", "dependencies": [], "key": "zlib1g_1-1.3.dfsg-p-really1.3.1-1-p-b1_riscv64", "name": "zlib1g", "sha256": "38c52eef58e5fc9b13d93f8a7d0a0549c32b4f00402a778d39a135254f554314", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/z/zlib/zlib1g_1.3.dfsg+really1.3.1-1+b1_riscv64.deb" ], "version": "1:1.3.dfsg+really1.3.1-1+b1" }, { "arch": "riscv64", "dependencies": [], "key": "libzstd1_1.5.7-p-dfsg-1_riscv64", "name": "libzstd1", "sha256": "5967f5f97bfb6e7a8036d4e615c0ecd6861a9bb686bd60ee0c81422581faf0ad", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/libz/libzstd/libzstd1_1.5.7+dfsg-1_riscv64.deb" ], "version": "1.5.7+dfsg-1" }, { "arch": "riscv64", "dependencies": [], "key": "gcc-14-base_14.2.0-19_riscv64", "name": "gcc-14-base", "sha256": "bb871e84c5c108463fa6a858e72f15cbf809f3888442b89941fc625449874206", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-14/gcc-14-base_14.2.0-19_riscv64.deb" ], "version": "14.2.0-19" }, { "arch": "riscv64", "dependencies": [], "key": "libgcc-s1_14.2.0-19_riscv64", "name": "libgcc-s1", "sha256": "16d3f9f534028615413d23f649e5d246baef48fe7db739ad564ef8b9a6e5587c", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-14/libgcc-s1_14.2.0-19_riscv64.deb" ], "version": "14.2.0-19" }, { "arch": "riscv64", "dependencies": [], "key": "libgomp1_14.2.0-19_riscv64", "name": "libgomp1", "sha256": "0d457810c609eed431d438aa3e7a0c5a6974d3dca8e16ecd8fe38a949ba63b0f", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-14/libgomp1_14.2.0-19_riscv64.deb" ], "version": "14.2.0-19" }, { "arch": "riscv64", "dependencies": [], "key": "libstdc-p--p-6_14.2.0-19_riscv64", "name": "libstdc++6", "sha256": "f285313f34e0d8f65463c669fac8eb29760a3f3fd6459005dd3110cdd2b10fd7", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-14/libstdc++6_14.2.0-19_riscv64.deb" ], "version": "14.2.0-19" } ], "version": 1 } ================================================ FILE: private/repos/deb/trixie.yaml ================================================ # debian 13 version: 1 sources: - channel: trixie main url: https://snapshot.debian.org/archive/debian/20260314T202839Z - channel: trixie-updates main url: https://snapshot.debian.org/archive/debian/20260314T202839Z - channel: trixie-security main url: https://snapshot.debian.org/archive/debian-security/20260314T202839Z archs: - amd64 - arm64 - armhf - s390x - ppc64el - riscv64 packages: - base-files - ca-certificates - libc6 - libc-bin - libssl3t64 - netbase - openssl - tzdata - tzdata-legacy - media-types - zlib1g - libzstd1 # c++ - gcc-14-base - libgcc-s1 - libgomp1 - libstdc++6 ================================================ FILE: private/repos/deb/trixie_adoptium.lock.json ================================================ { "packages": [ { "arch": "amd64", "dependencies": [], "key": "temurin-17-jre_17.0.18.0.0-p-8-1_amd64", "name": "temurin-17-jre", "sha256": "fada157f316e14b0c8fda17b886b0d0b524b562ee77dc2c146fa471d2342709b", "urls": [ "https://packages.adoptium.net/artifactory/deb/pool/main/t/temurin-17/temurin-17-jre_17.0.18.0.0+8-1_amd64.deb" ], "version": "17.0.18.0.0+8-1" }, { "arch": "amd64", "dependencies": [], "key": "temurin-17-jdk_17.0.18.0.0-p-8-1_amd64", "name": "temurin-17-jdk", "sha256": "ce5e529f453ae11e41ddb3ae25979df491634fd4d3f4ed5fed44db1d13ca502f", "urls": [ "https://packages.adoptium.net/artifactory/deb/pool/main/t/temurin-17/temurin-17-jdk_17.0.18.0.0+8-1_amd64.deb" ], "version": "17.0.18.0.0+8-1" }, { "arch": "amd64", "dependencies": [], "key": "temurin-21-jre_21.0.10.0.0-p-7-1_amd64", "name": "temurin-21-jre", "sha256": "93282daa88301f2502e6e4e1d9f63c3b5ebc64a56e74d8c9d0e7a0a28263a82b", "urls": [ "https://packages.adoptium.net/artifactory/deb/pool/main/t/temurin-21/temurin-21-jre_21.0.10.0.0+7-1_amd64.deb" ], "version": "21.0.10.0.0+7-1" }, { "arch": "amd64", "dependencies": [], "key": "temurin-21-jdk_21.0.10.0.0-p-7-1_amd64", "name": "temurin-21-jdk", "sha256": "ec89ad6f51af0511ab1e3ed1c354cbcc7c7a08462ca16ac4a874f5a6728139e8", "urls": [ "https://packages.adoptium.net/artifactory/deb/pool/main/t/temurin-21/temurin-21-jdk_21.0.10.0.0+7-1_amd64.deb" ], "version": "21.0.10.0.0+7-1" }, { "arch": "amd64", "dependencies": [], "key": "temurin-25-jre_25.0.2.0.0-p-10-1_amd64", "name": "temurin-25-jre", "sha256": "279d043f5849f94895dfa32252748bdbb40c87b9bf75dffae141434cbc9eb8f3", "urls": [ "https://packages.adoptium.net/artifactory/deb/pool/main/t/temurin-25/temurin-25-jre_25.0.2.0.0+10-1_amd64.deb" ], "version": "25.0.2.0.0+10-1" }, { "arch": "amd64", "dependencies": [], "key": "temurin-25-jdk_25.0.2.0.0-p-10-1_amd64", "name": "temurin-25-jdk", "sha256": "a04db715e851b2a5c1fa27db5f3e68d8d488877d5da6f0030b86a140b2c4029d", "urls": [ "https://packages.adoptium.net/artifactory/deb/pool/main/t/temurin-25/temurin-25-jdk_25.0.2.0.0+10-1_amd64.deb" ], "version": "25.0.2.0.0+10-1" }, { "arch": "arm64", "dependencies": [], "key": "temurin-17-jre_17.0.18.0.0-p-8-0_arm64", "name": "temurin-17-jre", "sha256": "54581ac52cde67e6d1dfa214777aa2bbe818b4fda4f0b2c8d1d4d644f9322487", "urls": [ "https://packages.adoptium.net/artifactory/deb/pool/main/t/temurin-17/temurin-17-jre_17.0.18.0.0+8-0_arm64.deb" ], "version": "17.0.18.0.0+8-0" }, { "arch": "arm64", "dependencies": [], "key": "temurin-17-jdk_17.0.18.0.0-p-8-0_arm64", "name": "temurin-17-jdk", "sha256": "2410ea398569b5981e436626f148b1fcfebd0dfe61b1d8a73e63959c313a6ba4", "urls": [ "https://packages.adoptium.net/artifactory/deb/pool/main/t/temurin-17/temurin-17-jdk_17.0.18.0.0+8-0_arm64.deb" ], "version": "17.0.18.0.0+8-0" }, { "arch": "arm64", "dependencies": [], "key": "temurin-21-jre_21.0.10.0.0-p-7-0_arm64", "name": "temurin-21-jre", "sha256": "dc256aebf81f8e7c0a859c0894233830c698cd105de62332d02ac3df70141f2a", "urls": [ "https://packages.adoptium.net/artifactory/deb/pool/main/t/temurin-21/temurin-21-jre_21.0.10.0.0+7-0_arm64.deb" ], "version": "21.0.10.0.0+7-0" }, { "arch": "arm64", "dependencies": [], "key": "temurin-21-jdk_21.0.10.0.0-p-7-0_arm64", "name": "temurin-21-jdk", "sha256": "dd9b54ff7f8fc809730a34608656dc3be4369c94c39923e7e00ef83192166168", "urls": [ "https://packages.adoptium.net/artifactory/deb/pool/main/t/temurin-21/temurin-21-jdk_21.0.10.0.0+7-0_arm64.deb" ], "version": "21.0.10.0.0+7-0" }, { "arch": "arm64", "dependencies": [], "key": "temurin-25-jre_25.0.2.0.0-p-10-0_arm64", "name": "temurin-25-jre", "sha256": "7472db63d005e331f9311ebb93798ac94d8ac247ee0b5266c13206c21058800c", "urls": [ "https://packages.adoptium.net/artifactory/deb/pool/main/t/temurin-25/temurin-25-jre_25.0.2.0.0+10-0_arm64.deb" ], "version": "25.0.2.0.0+10-0" }, { "arch": "arm64", "dependencies": [], "key": "temurin-25-jdk_25.0.2.0.0-p-10-0_arm64", "name": "temurin-25-jdk", "sha256": "346d974fa90fcaca91260ead05f08b6b2cc3d2c4f324d3619a6d2080d8211103", "urls": [ "https://packages.adoptium.net/artifactory/deb/pool/main/t/temurin-25/temurin-25-jdk_25.0.2.0.0+10-0_arm64.deb" ], "version": "25.0.2.0.0+10-0" }, { "arch": "s390x", "dependencies": [], "key": "temurin-17-jre_17.0.18.0.0-p-8-0_s390x", "name": "temurin-17-jre", "sha256": "c3e8b38312ce0e0c4ca6f317ccc0e27744c09728bd654de726f76f692eee655a", "urls": [ "https://packages.adoptium.net/artifactory/deb/pool/main/t/temurin-17/temurin-17-jre_17.0.18.0.0+8-0_s390x.deb" ], "version": "17.0.18.0.0+8-0" }, { "arch": "s390x", "dependencies": [], "key": "temurin-17-jdk_17.0.18.0.0-p-8-0_s390x", "name": "temurin-17-jdk", "sha256": "cce158ab3d50ac6a23397bf2a095db95d78484ebe44ee37fec2b6093059c091b", "urls": [ "https://packages.adoptium.net/artifactory/deb/pool/main/t/temurin-17/temurin-17-jdk_17.0.18.0.0+8-0_s390x.deb" ], "version": "17.0.18.0.0+8-0" }, { "arch": "s390x", "dependencies": [], "key": "temurin-21-jre_21.0.10.0.0-p-7-0_s390x", "name": "temurin-21-jre", "sha256": "0da663187c25289add32f65fddf13604542b5d32d359a6d5e13ab345a7ab544c", "urls": [ "https://packages.adoptium.net/artifactory/deb/pool/main/t/temurin-21/temurin-21-jre_21.0.10.0.0+7-0_s390x.deb" ], "version": "21.0.10.0.0+7-0" }, { "arch": "s390x", "dependencies": [], "key": "temurin-21-jdk_21.0.10.0.0-p-7-0_s390x", "name": "temurin-21-jdk", "sha256": "ef9b01f844c2523eb2c26e9c585ce2669d2e781b874ed33514bd15aa254c18c7", "urls": [ "https://packages.adoptium.net/artifactory/deb/pool/main/t/temurin-21/temurin-21-jdk_21.0.10.0.0+7-0_s390x.deb" ], "version": "21.0.10.0.0+7-0" }, { "arch": "s390x", "dependencies": [], "key": "temurin-25-jre_25.0.2.0.0-p-10-0_s390x", "name": "temurin-25-jre", "sha256": "7318035d9ff137622ad368e2159cb9d1c45635d05f8185b2f82af5ae89d672b6", "urls": [ "https://packages.adoptium.net/artifactory/deb/pool/main/t/temurin-25/temurin-25-jre_25.0.2.0.0+10-0_s390x.deb" ], "version": "25.0.2.0.0+10-0" }, { "arch": "s390x", "dependencies": [], "key": "temurin-25-jdk_25.0.2.0.0-p-10-0_s390x", "name": "temurin-25-jdk", "sha256": "7abab559d6d751713bfa6ba09ff75076b454fdec05dcb95ec897eb92e8d34e15", "urls": [ "https://packages.adoptium.net/artifactory/deb/pool/main/t/temurin-25/temurin-25-jdk_25.0.2.0.0+10-0_s390x.deb" ], "version": "25.0.2.0.0+10-0" }, { "arch": "ppc64el", "dependencies": [], "key": "temurin-17-jre_17.0.18.0.0-p-8-0_ppc64el", "name": "temurin-17-jre", "sha256": "693ce1870ab6ed087aa8c803cc36094154fcbfed3793ff89dffec915e694d71e", "urls": [ "https://packages.adoptium.net/artifactory/deb/pool/main/t/temurin-17/temurin-17-jre_17.0.18.0.0+8-0_ppc64el.deb" ], "version": "17.0.18.0.0+8-0" }, { "arch": "ppc64el", "dependencies": [], "key": "temurin-17-jdk_17.0.18.0.0-p-8-0_ppc64el", "name": "temurin-17-jdk", "sha256": "bf7bae624e25fdfae61d93dc1206aa98284e9be9b4158a2492e0a75d4203a71b", "urls": [ "https://packages.adoptium.net/artifactory/deb/pool/main/t/temurin-17/temurin-17-jdk_17.0.18.0.0+8-0_ppc64el.deb" ], "version": "17.0.18.0.0+8-0" }, { "arch": "ppc64el", "dependencies": [], "key": "temurin-21-jre_21.0.10.0.0-p-7-0_ppc64el", "name": "temurin-21-jre", "sha256": "537f072bdcd06e55b9635d55612190eb830df0e8165c1b4a55b67cc46be26089", "urls": [ "https://packages.adoptium.net/artifactory/deb/pool/main/t/temurin-21/temurin-21-jre_21.0.10.0.0+7-0_ppc64el.deb" ], "version": "21.0.10.0.0+7-0" }, { "arch": "ppc64el", "dependencies": [], "key": "temurin-21-jdk_21.0.10.0.0-p-7-0_ppc64el", "name": "temurin-21-jdk", "sha256": "9f192399ed2756baf5f5d90b83c62d9e562498e5168440b43721bb2c20db0bae", "urls": [ "https://packages.adoptium.net/artifactory/deb/pool/main/t/temurin-21/temurin-21-jdk_21.0.10.0.0+7-0_ppc64el.deb" ], "version": "21.0.10.0.0+7-0" }, { "arch": "ppc64el", "dependencies": [], "key": "temurin-25-jre_25.0.2.0.0-p-10-0_ppc64el", "name": "temurin-25-jre", "sha256": "2d5908ae4952668d23f5c89a77d7fe6a460b7bed1c4b8514ca755fa87aa21417", "urls": [ "https://packages.adoptium.net/artifactory/deb/pool/main/t/temurin-25/temurin-25-jre_25.0.2.0.0+10-0_ppc64el.deb" ], "version": "25.0.2.0.0+10-0" }, { "arch": "ppc64el", "dependencies": [], "key": "temurin-25-jdk_25.0.2.0.0-p-10-0_ppc64el", "name": "temurin-25-jdk", "sha256": "8b6bed3265dac51a23c1dbb4fb252f4f7d628729c00d3f835705e66fc0c23d93", "urls": [ "https://packages.adoptium.net/artifactory/deb/pool/main/t/temurin-25/temurin-25-jdk_25.0.2.0.0+10-0_ppc64el.deb" ], "version": "25.0.2.0.0+10-0" }, { "arch": "riscv64", "dependencies": [], "key": "temurin-17-jre_17.0.18.0.0-p-8-0_riscv64", "name": "temurin-17-jre", "sha256": "0dcc823cfa1757c2f3739b59ce8ebfe32f2d619343ef77dfb501bf79a5165748", "urls": [ "https://packages.adoptium.net/artifactory/deb/pool/main/t/temurin-17/temurin-17-jre_17.0.18.0.0+8-0_riscv64.deb" ], "version": "17.0.18.0.0+8-0" }, { "arch": "riscv64", "dependencies": [], "key": "temurin-17-jdk_17.0.18.0.0-p-8-0_riscv64", "name": "temurin-17-jdk", "sha256": "92fe04052404438f5b65173c2cc9feb760cdab2992d0f4feb7dc32452532be0c", "urls": [ "https://packages.adoptium.net/artifactory/deb/pool/main/t/temurin-17/temurin-17-jdk_17.0.18.0.0+8-0_riscv64.deb" ], "version": "17.0.18.0.0+8-0" }, { "arch": "riscv64", "dependencies": [], "key": "temurin-21-jre_21.0.10.0.0-p-7-0_riscv64", "name": "temurin-21-jre", "sha256": "0518002b3ce24936615f2996ec9bc29b6e868a5156f134df16c6a271edfe54a8", "urls": [ "https://packages.adoptium.net/artifactory/deb/pool/main/t/temurin-21/temurin-21-jre_21.0.10.0.0+7-0_riscv64.deb" ], "version": "21.0.10.0.0+7-0" }, { "arch": "riscv64", "dependencies": [], "key": "temurin-21-jdk_21.0.10.0.0-p-7-0_riscv64", "name": "temurin-21-jdk", "sha256": "c85788afa927d86254b351d9a5af6628a7cad7182c8e700469d0244f296fa6b4", "urls": [ "https://packages.adoptium.net/artifactory/deb/pool/main/t/temurin-21/temurin-21-jdk_21.0.10.0.0+7-0_riscv64.deb" ], "version": "21.0.10.0.0+7-0" }, { "arch": "riscv64", "dependencies": [], "key": "temurin-25-jre_25.0.2.0.0-p-10-0_riscv64", "name": "temurin-25-jre", "sha256": "c93c327e0aa5b7a1d249ddadfe4ba071a7fcda1b7c82a33f2d5ff4931d6ad51d", "urls": [ "https://packages.adoptium.net/artifactory/deb/pool/main/t/temurin-25/temurin-25-jre_25.0.2.0.0+10-0_riscv64.deb" ], "version": "25.0.2.0.0+10-0" }, { "arch": "riscv64", "dependencies": [], "key": "temurin-25-jdk_25.0.2.0.0-p-10-0_riscv64", "name": "temurin-25-jdk", "sha256": "99eebd085906b13f7b25fc26b8cc85d3f6635373f0a9d202b916445f243cd0b5", "urls": [ "https://packages.adoptium.net/artifactory/deb/pool/main/t/temurin-25/temurin-25-jdk_25.0.2.0.0+10-0_riscv64.deb" ], "version": "25.0.2.0.0+10-0" } ], "version": 1 } ================================================ FILE: private/repos/deb/trixie_adoptium.yaml ================================================ # debian 13, java from adoptium repositories version: 1 sources: # adoptium - channel: trixie main url: https://packages.adoptium.net/artifactory/deb archs: - amd64 - arm64 - s390x - ppc64el - riscv64 packages: - temurin-17-jre - temurin-17-jdk - temurin-21-jre - temurin-21-jdk - temurin-25-jre - temurin-25-jdk ================================================ FILE: private/repos/deb/trixie_java.lock.json ================================================ { "packages": [ { "arch": "amd64", "dependencies": [], "key": "fontconfig-config_2.15.0-2.3_amd64", "name": "fontconfig-config", "sha256": "0475c00d02660c07a15085051818625331bb502e053242106aaaa1f2ddb41225", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/f/fontconfig/fontconfig-config_2.15.0-2.3_amd64.deb" ], "version": "2.15.0-2.3" }, { "arch": "amd64", "dependencies": [], "key": "fonts-dejavu-core_2.37-8_amd64", "name": "fonts-dejavu-core", "sha256": "86635b3d25b3655fc11cb3ecc3af59f0bf19643b02b94f2de48bd10253cdba12", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/f/fonts-dejavu/fonts-dejavu-core_2.37-8_all.deb" ], "version": "2.37-8" }, { "arch": "amd64", "dependencies": [], "key": "libbrotli1_1.1.0-2-p-b7_amd64", "name": "libbrotli1", "sha256": "0fb79f88db210afbd69282ab9649e525f393ec6950ca34da1a6b359250b8d7db", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/b/brotli/libbrotli1_1.1.0-2+b7_amd64.deb" ], "version": "1.1.0-2+b7" }, { "arch": "amd64", "dependencies": [], "key": "libbz2-1.0_1.0.8-6_amd64", "name": "libbz2-1.0", "sha256": "cba4cda04244b5e481bb15524bc3c983a7d1b6f330013b9b381706a2fcb65310", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/b/bzip2/libbz2-1.0_1.0.8-6_amd64.deb" ], "version": "1.0.8-6" }, { "arch": "amd64", "dependencies": [], "key": "libcrypt1_1-4.4.38-1_amd64", "name": "libcrypt1", "sha256": "0ebc144d662e3197982d1bf3a7b8b35ca845e54c68811de0328b1f0d7c67585c", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/libx/libxcrypt/libcrypt1_4.4.38-1_amd64.deb" ], "version": "1:4.4.38-1" }, { "arch": "amd64", "dependencies": [], "key": "libexpat1_2.7.1-2_amd64", "name": "libexpat1", "sha256": "f875f56675be5b074da877f9a93b09d47dc2eb4e679951d36e2943b8d4843344", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/e/expat/libexpat1_2.7.1-2_amd64.deb" ], "version": "2.7.1-2" }, { "arch": "amd64", "dependencies": [], "key": "libfontconfig1_2.15.0-2.3_amd64", "name": "libfontconfig1", "sha256": "7ae91ec59857cc8e375eb2bdd371a4a69daea38f7787d06d474a847867d852b1", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/f/fontconfig/libfontconfig1_2.15.0-2.3_amd64.deb" ], "version": "2.15.0-2.3" }, { "arch": "amd64", "dependencies": [], "key": "libfreetype6_2.13.3-p-dfsg-1_amd64", "name": "libfreetype6", "sha256": "1fcf0600356ff0d9b387ad908a897e1e5418705ffb8d7cb66d6dcb25af55b76f", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/f/freetype/libfreetype6_2.13.3+dfsg-1_amd64.deb" ], "version": "2.13.3+dfsg-1" }, { "arch": "amd64", "dependencies": [], "key": "libglib2.0-0t64_2.84.4-3_deb13u2_amd64", "name": "libglib2.0-0t64", "sha256": "6d4c07e17b9809eca7078b49851da8e1d16e510e80897cc96681bd4c75b27353", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/glib2.0/libglib2.0-0t64_2.84.4-3~deb13u2_amd64.deb" ], "version": "2.84.4-3~deb13u2" }, { "arch": "amd64", "dependencies": [], "key": "libgraphite2-3_1.3.14-2-p-b1_amd64", "name": "libgraphite2-3", "sha256": "e3ca92b45f951d65542c9309e7d68b1fc36e6aa3cc3de69b5123859fd6988d25", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/graphite2/libgraphite2-3_1.3.14-2+b1_amd64.deb" ], "version": "1.3.14-2+b1" }, { "arch": "amd64", "dependencies": [], "key": "libharfbuzz0b_10.2.0-1-p-b1_amd64", "name": "libharfbuzz0b", "sha256": "153daeed7f6bec0b0573600c4063badac3bb65d6005a14f3c0296fb5728b54c2", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/h/harfbuzz/libharfbuzz0b_10.2.0-1+b1_amd64.deb" ], "version": "10.2.0-1+b1" }, { "arch": "amd64", "dependencies": [], "key": "libjpeg62-turbo_1-2.1.5-4_amd64", "name": "libjpeg62-turbo", "sha256": "5504299ad0e3c0a9ca9f962a68a650a040db52f9f416a109e74df48d55601d3f", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/libj/libjpeg-turbo/libjpeg62-turbo_2.1.5-4_amd64.deb" ], "version": "1:2.1.5-4" }, { "arch": "amd64", "dependencies": [], "key": "liblcms2-2_2.16-2_amd64", "name": "liblcms2-2", "sha256": "726ef00f17a41bd9735c8df8e9562e6243baa13275164ad942f06f2a3772f520", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/l/lcms2/liblcms2-2_2.16-2_amd64.deb" ], "version": "2.16-2" }, { "arch": "amd64", "dependencies": [], "key": "libpcre2-8-0_10.46-1_deb13u1_amd64", "name": "libpcre2-8-0", "sha256": "6aa452af6a07e34498bf8e734e8789c9dd602fb34f12572e62dc1bba4889a60e", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/p/pcre2/libpcre2-8-0_10.46-1~deb13u1_amd64.deb" ], "version": "10.46-1~deb13u1" }, { "arch": "amd64", "dependencies": [], "key": "libpng16-16t64_1.6.48-1-p-deb13u3_amd64", "name": "libpng16-16t64", "sha256": "679adfba65710f40666b80216877e9df18649244936b5ee39f406367dd21ba79", "urls": [ "https://snapshot.debian.org/archive/debian-security/20260314T202839Z/pool/updates/main/libp/libpng1.6/libpng16-16t64_1.6.48-1+deb13u3_amd64.deb" ], "version": "1.6.48-1+deb13u3" }, { "arch": "amd64", "dependencies": [], "key": "libuuid1_2.41-5_amd64", "name": "libuuid1", "sha256": "10247744737c1bb574f9667b3f06a3b43a5055c67bdfcc1945803451cc036db3", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/u/util-linux/libuuid1_2.41-5_amd64.deb" ], "version": "2.41-5" }, { "arch": "amd64", "dependencies": [], "key": "zlib1g_1-1.3.dfsg-p-really1.3.1-1-p-b1_amd64", "name": "zlib1g", "sha256": "015be740d6236ad114582dea500c1d907f29e16d6db00566ca32fb68d71ac90d", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/z/zlib/zlib1g_1.3.dfsg+really1.3.1-1+b1_amd64.deb" ], "version": "1:1.3.dfsg+really1.3.1-1+b1" }, { "arch": "amd64", "dependencies": [], "key": "gcc-14-base_14.2.0-19_amd64", "name": "gcc-14-base", "sha256": "5b6825de4263824b78c4c51f6476414f3b4e89c2ab63e81dc8b9b5501e867cf6", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-14/gcc-14-base_14.2.0-19_amd64.deb" ], "version": "14.2.0-19" }, { "arch": "amd64", "dependencies": [], "key": "libgcc-s1_14.2.0-19_amd64", "name": "libgcc-s1", "sha256": "3c71917b490d1a17aed43196a2787a256ecf060526cdb20216a74bedc061b150", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-14/libgcc-s1_14.2.0-19_amd64.deb" ], "version": "14.2.0-19" }, { "arch": "amd64", "dependencies": [], "key": "libstdc-p--p-6_14.2.0-19_amd64", "name": "libstdc++6", "sha256": "ab1fa05837aa7a92aae748fd07a18a35f7d18bb4a71c4724fe2bbf0e32089de0", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-14/libstdc++6_14.2.0-19_amd64.deb" ], "version": "14.2.0-19" }, { "arch": "arm64", "dependencies": [], "key": "fontconfig-config_2.15.0-2.3_arm64", "name": "fontconfig-config", "sha256": "10f643f467b51cf25fc18d1945bc61246dd8d8d1fe6bc712a2b1712c74ebc4d6", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/f/fontconfig/fontconfig-config_2.15.0-2.3_arm64.deb" ], "version": "2.15.0-2.3" }, { "arch": "arm64", "dependencies": [], "key": "fonts-dejavu-core_2.37-8_arm64", "name": "fonts-dejavu-core", "sha256": "86635b3d25b3655fc11cb3ecc3af59f0bf19643b02b94f2de48bd10253cdba12", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/f/fonts-dejavu/fonts-dejavu-core_2.37-8_all.deb" ], "version": "2.37-8" }, { "arch": "arm64", "dependencies": [], "key": "libbrotli1_1.1.0-2-p-b7_arm64", "name": "libbrotli1", "sha256": "10270398c4842e71c72b4081fa1761728b3225d6c8dce7c58d5baafe58a5e18f", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/b/brotli/libbrotli1_1.1.0-2+b7_arm64.deb" ], "version": "1.1.0-2+b7" }, { "arch": "arm64", "dependencies": [], "key": "libbz2-1.0_1.0.8-6_arm64", "name": "libbz2-1.0", "sha256": "3537fe4fc577a60c8a9568873cd577db7ebc135eb8bb1825f18caf8972d9d2f2", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/b/bzip2/libbz2-1.0_1.0.8-6_arm64.deb" ], "version": "1.0.8-6" }, { "arch": "arm64", "dependencies": [], "key": "libcrypt1_1-4.4.38-1_arm64", "name": "libcrypt1", "sha256": "b9aaa808aa3812b3de3e54eb5dfb16762c1779db032604abef2354c02fdc29b8", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/libx/libxcrypt/libcrypt1_4.4.38-1_arm64.deb" ], "version": "1:4.4.38-1" }, { "arch": "arm64", "dependencies": [], "key": "libexpat1_2.7.1-2_arm64", "name": "libexpat1", "sha256": "7f6868227f4893a11123e43b9ed291950b550c7dc209905b2fb871c74678d1bf", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/e/expat/libexpat1_2.7.1-2_arm64.deb" ], "version": "2.7.1-2" }, { "arch": "arm64", "dependencies": [], "key": "libfontconfig1_2.15.0-2.3_arm64", "name": "libfontconfig1", "sha256": "872781cf62926b68c34a4302a3caae334ff8d4d83a2b2477f8fb454460aadc99", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/f/fontconfig/libfontconfig1_2.15.0-2.3_arm64.deb" ], "version": "2.15.0-2.3" }, { "arch": "arm64", "dependencies": [], "key": "libfreetype6_2.13.3-p-dfsg-1_arm64", "name": "libfreetype6", "sha256": "dcb545c78601b14049e85901f8f83ddb5d05b7792ae6188b21d0edf7dc449ac0", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/f/freetype/libfreetype6_2.13.3+dfsg-1_arm64.deb" ], "version": "2.13.3+dfsg-1" }, { "arch": "arm64", "dependencies": [], "key": "libglib2.0-0t64_2.84.4-3_deb13u2_arm64", "name": "libglib2.0-0t64", "sha256": "61ac86d96726c10403028a7674575504f46c0e0a4f6fac7c9447502d579b7649", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/glib2.0/libglib2.0-0t64_2.84.4-3~deb13u2_arm64.deb" ], "version": "2.84.4-3~deb13u2" }, { "arch": "arm64", "dependencies": [], "key": "libgraphite2-3_1.3.14-2-p-b1_arm64", "name": "libgraphite2-3", "sha256": "77e3063bf319dcc5c421352d576330d5896764098d81afc15236da6bd2a8f438", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/graphite2/libgraphite2-3_1.3.14-2+b1_arm64.deb" ], "version": "1.3.14-2+b1" }, { "arch": "arm64", "dependencies": [], "key": "libharfbuzz0b_10.2.0-1-p-b1_arm64", "name": "libharfbuzz0b", "sha256": "16cbe882396bedde9224797925595142f9115aede8bf62d7d407696a1e307384", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/h/harfbuzz/libharfbuzz0b_10.2.0-1+b1_arm64.deb" ], "version": "10.2.0-1+b1" }, { "arch": "arm64", "dependencies": [], "key": "libjpeg62-turbo_1-2.1.5-4_arm64", "name": "libjpeg62-turbo", "sha256": "e4989073bb0bac8a6ec043c7adb80e1dfe601d8552233da48bb24ab45d1a1d4a", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/libj/libjpeg-turbo/libjpeg62-turbo_2.1.5-4_arm64.deb" ], "version": "1:2.1.5-4" }, { "arch": "arm64", "dependencies": [], "key": "liblcms2-2_2.16-2_arm64", "name": "liblcms2-2", "sha256": "c2a9e32455134df3ad9f39b1109980e3d93f8369f1a35f6ea8e45ca2a25dc0b1", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/l/lcms2/liblcms2-2_2.16-2_arm64.deb" ], "version": "2.16-2" }, { "arch": "arm64", "dependencies": [], "key": "libpcre2-8-0_10.46-1_deb13u1_arm64", "name": "libpcre2-8-0", "sha256": "f74d3e1082c2d6d2f7b4d47e41070de4a7e2f7f9d0e6e0c901ebfe0e82cdd3ee", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/p/pcre2/libpcre2-8-0_10.46-1~deb13u1_arm64.deb" ], "version": "10.46-1~deb13u1" }, { "arch": "arm64", "dependencies": [], "key": "libpng16-16t64_1.6.48-1-p-deb13u3_arm64", "name": "libpng16-16t64", "sha256": "89f31e282ef54e29c28313fda75360559348edf18a0dcda459876acae20d7df7", "urls": [ "https://snapshot.debian.org/archive/debian-security/20260314T202839Z/pool/updates/main/libp/libpng1.6/libpng16-16t64_1.6.48-1+deb13u3_arm64.deb" ], "version": "1.6.48-1+deb13u3" }, { "arch": "arm64", "dependencies": [], "key": "libuuid1_2.41-5_arm64", "name": "libuuid1", "sha256": "85b7d04605f9d423d5699b3c07f027e8380649fd164a51e0712cded0cc56eced", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/u/util-linux/libuuid1_2.41-5_arm64.deb" ], "version": "2.41-5" }, { "arch": "arm64", "dependencies": [], "key": "zlib1g_1-1.3.dfsg-p-really1.3.1-1-p-b1_arm64", "name": "zlib1g", "sha256": "209aa5cf671e97b9eb0410844fa6df4cae2e75b0c72e7802ab6c8ece13e6ddef", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/z/zlib/zlib1g_1.3.dfsg+really1.3.1-1+b1_arm64.deb" ], "version": "1:1.3.dfsg+really1.3.1-1+b1" }, { "arch": "arm64", "dependencies": [], "key": "gcc-14-base_14.2.0-19_arm64", "name": "gcc-14-base", "sha256": "34ee90679b018c0e64234747a4c4c0ae6b7f63541115037465a8627c2dfbc594", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-14/gcc-14-base_14.2.0-19_arm64.deb" ], "version": "14.2.0-19" }, { "arch": "arm64", "dependencies": [], "key": "libgcc-s1_14.2.0-19_arm64", "name": "libgcc-s1", "sha256": "1108bc87879833d6d9a145f22a4a15cddb34e065b4b5f4b97bee586adbac2851", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-14/libgcc-s1_14.2.0-19_arm64.deb" ], "version": "14.2.0-19" }, { "arch": "arm64", "dependencies": [], "key": "libstdc-p--p-6_14.2.0-19_arm64", "name": "libstdc++6", "sha256": "6669b0c52a2e7c6af9adfdabce3ff6e286065cdfbc7b85280862b5f799daebee", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-14/libstdc++6_14.2.0-19_arm64.deb" ], "version": "14.2.0-19" }, { "arch": "s390x", "dependencies": [], "key": "fontconfig-config_2.15.0-2.3_s390x", "name": "fontconfig-config", "sha256": "67579884a5d0b140ddeec9425d2e45d8b7351f60e12a324db3b44bb36b51c0a8", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/f/fontconfig/fontconfig-config_2.15.0-2.3_s390x.deb" ], "version": "2.15.0-2.3" }, { "arch": "s390x", "dependencies": [], "key": "fonts-dejavu-core_2.37-8_s390x", "name": "fonts-dejavu-core", "sha256": "86635b3d25b3655fc11cb3ecc3af59f0bf19643b02b94f2de48bd10253cdba12", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/f/fonts-dejavu/fonts-dejavu-core_2.37-8_all.deb" ], "version": "2.37-8" }, { "arch": "s390x", "dependencies": [], "key": "libbrotli1_1.1.0-2-p-b7_s390x", "name": "libbrotli1", "sha256": "4b258faa654f95a7b3911956436d8556657af28dda91a05dd4045bb3bdf673fd", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/b/brotli/libbrotli1_1.1.0-2+b7_s390x.deb" ], "version": "1.1.0-2+b7" }, { "arch": "s390x", "dependencies": [], "key": "libbz2-1.0_1.0.8-6_s390x", "name": "libbz2-1.0", "sha256": "d1f51ce5ef4b7232b079fa21e222a1aafe3d631344dfbe369c8c77a79d5265e7", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/b/bzip2/libbz2-1.0_1.0.8-6_s390x.deb" ], "version": "1.0.8-6" }, { "arch": "s390x", "dependencies": [], "key": "libcrypt1_1-4.4.38-1_s390x", "name": "libcrypt1", "sha256": "c8c4cd4f66171c7607665141e2f8a8c60c8f9309ce62b6ac2eeeb0edbab2fe40", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/libx/libxcrypt/libcrypt1_4.4.38-1_s390x.deb" ], "version": "1:4.4.38-1" }, { "arch": "s390x", "dependencies": [], "key": "libexpat1_2.7.1-2_s390x", "name": "libexpat1", "sha256": "d16e16898d3726847e96a5f3eb35e4c721b838b50f61f7515ee6700a564d388c", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/e/expat/libexpat1_2.7.1-2_s390x.deb" ], "version": "2.7.1-2" }, { "arch": "s390x", "dependencies": [], "key": "libfontconfig1_2.15.0-2.3_s390x", "name": "libfontconfig1", "sha256": "dabbb1b7358525900cc98aba5d25f78bac953fdaaf96b1bb09a6b570ae917be0", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/f/fontconfig/libfontconfig1_2.15.0-2.3_s390x.deb" ], "version": "2.15.0-2.3" }, { "arch": "s390x", "dependencies": [], "key": "libfreetype6_2.13.3-p-dfsg-1_s390x", "name": "libfreetype6", "sha256": "ad73bbee549e4e28f6334fc11d01571f0c445d1ae877c4e6ce21838fb265685d", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/f/freetype/libfreetype6_2.13.3+dfsg-1_s390x.deb" ], "version": "2.13.3+dfsg-1" }, { "arch": "s390x", "dependencies": [], "key": "libglib2.0-0t64_2.84.4-3_deb13u2_s390x", "name": "libglib2.0-0t64", "sha256": "7f3b66433fa74de544297719ab11318bc4234cb0b3cf658920d1a1ce44a7c4e4", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/glib2.0/libglib2.0-0t64_2.84.4-3~deb13u2_s390x.deb" ], "version": "2.84.4-3~deb13u2" }, { "arch": "s390x", "dependencies": [], "key": "libgraphite2-3_1.3.14-2-p-b1_s390x", "name": "libgraphite2-3", "sha256": "724140c5dedd0778a3e701c9d8aff45a2c83a355b38b97cc1aecedb46fef74e5", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/graphite2/libgraphite2-3_1.3.14-2+b1_s390x.deb" ], "version": "1.3.14-2+b1" }, { "arch": "s390x", "dependencies": [], "key": "libharfbuzz0b_10.2.0-1-p-b1_s390x", "name": "libharfbuzz0b", "sha256": "5932a76bbdc14bacb3e99d6dfa5e9eadba907d745e2f775b841561090f8a55f7", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/h/harfbuzz/libharfbuzz0b_10.2.0-1+b1_s390x.deb" ], "version": "10.2.0-1+b1" }, { "arch": "s390x", "dependencies": [], "key": "libjpeg62-turbo_1-2.1.5-4_s390x", "name": "libjpeg62-turbo", "sha256": "cbfd8a7724b8f89d6c0922f77b523ce8ebecbcc6455bb9364435c18f563790c4", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/libj/libjpeg-turbo/libjpeg62-turbo_2.1.5-4_s390x.deb" ], "version": "1:2.1.5-4" }, { "arch": "s390x", "dependencies": [], "key": "liblcms2-2_2.16-2_s390x", "name": "liblcms2-2", "sha256": "f3cec223271a0612f20bf164cf4732e9a31ccaa575ef58fbbfa51d98dd178515", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/l/lcms2/liblcms2-2_2.16-2_s390x.deb" ], "version": "2.16-2" }, { "arch": "s390x", "dependencies": [], "key": "libpcre2-8-0_10.46-1_deb13u1_s390x", "name": "libpcre2-8-0", "sha256": "ac6b596afaa99888dadf7ff8464c1f082f9d16421f51b505e038142364cbace3", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/p/pcre2/libpcre2-8-0_10.46-1~deb13u1_s390x.deb" ], "version": "10.46-1~deb13u1" }, { "arch": "s390x", "dependencies": [], "key": "libpng16-16t64_1.6.48-1-p-deb13u3_s390x", "name": "libpng16-16t64", "sha256": "a464a4a9a669978450ae5509b0a6bead90e1f4e7aec2fa2c7d9f57660f6f2d68", "urls": [ "https://snapshot.debian.org/archive/debian-security/20260314T202839Z/pool/updates/main/libp/libpng1.6/libpng16-16t64_1.6.48-1+deb13u3_s390x.deb" ], "version": "1.6.48-1+deb13u3" }, { "arch": "s390x", "dependencies": [], "key": "libuuid1_2.41-5_s390x", "name": "libuuid1", "sha256": "bc039ffc1143510981f97d97939016753f94d06b0e9049eaeeef99116ef04363", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/u/util-linux/libuuid1_2.41-5_s390x.deb" ], "version": "2.41-5" }, { "arch": "s390x", "dependencies": [], "key": "zlib1g_1-1.3.dfsg-p-really1.3.1-1-p-b1_s390x", "name": "zlib1g", "sha256": "e38a94c60e944dfcf1937a12b02785afbbb2bedf356da18984c4dac0acc47ed9", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/z/zlib/zlib1g_1.3.dfsg+really1.3.1-1+b1_s390x.deb" ], "version": "1:1.3.dfsg+really1.3.1-1+b1" }, { "arch": "s390x", "dependencies": [], "key": "gcc-14-base_14.2.0-19_s390x", "name": "gcc-14-base", "sha256": "7db20fd710eadefff128e82b4d4de68b466ce2aa1c53255004eb1d3d1d168495", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-14/gcc-14-base_14.2.0-19_s390x.deb" ], "version": "14.2.0-19" }, { "arch": "s390x", "dependencies": [], "key": "libgcc-s1_14.2.0-19_s390x", "name": "libgcc-s1", "sha256": "b5e87f11a8ac0537d500bf2dba37165bf8d25b5b44add1035a32deddbd4bfdda", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-14/libgcc-s1_14.2.0-19_s390x.deb" ], "version": "14.2.0-19" }, { "arch": "s390x", "dependencies": [], "key": "libstdc-p--p-6_14.2.0-19_s390x", "name": "libstdc++6", "sha256": "6a91f4a1c8c30dc6d0a23ad7ead8a56271b9f6966d6d74734f4b423cdfe5c21b", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-14/libstdc++6_14.2.0-19_s390x.deb" ], "version": "14.2.0-19" }, { "arch": "ppc64el", "dependencies": [], "key": "fontconfig-config_2.15.0-2.3_ppc64el", "name": "fontconfig-config", "sha256": "116cf37c74debed705140ed8215fc74450979a9135cd1d5b22a8656e4d76d5f6", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/f/fontconfig/fontconfig-config_2.15.0-2.3_ppc64el.deb" ], "version": "2.15.0-2.3" }, { "arch": "ppc64el", "dependencies": [], "key": "fonts-dejavu-core_2.37-8_ppc64el", "name": "fonts-dejavu-core", "sha256": "86635b3d25b3655fc11cb3ecc3af59f0bf19643b02b94f2de48bd10253cdba12", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/f/fonts-dejavu/fonts-dejavu-core_2.37-8_all.deb" ], "version": "2.37-8" }, { "arch": "ppc64el", "dependencies": [], "key": "libbrotli1_1.1.0-2-p-b7_ppc64el", "name": "libbrotli1", "sha256": "bdbb6171de2ff9d22d1a5b98e06a4979506f8e5ac1f4dfafabd5c3b952e9c7ab", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/b/brotli/libbrotli1_1.1.0-2+b7_ppc64el.deb" ], "version": "1.1.0-2+b7" }, { "arch": "ppc64el", "dependencies": [], "key": "libbz2-1.0_1.0.8-6_ppc64el", "name": "libbz2-1.0", "sha256": "10390b9ded521aaf6c37df8f63b32a0f127f96d0818c34e60c6ea5260fd99e39", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/b/bzip2/libbz2-1.0_1.0.8-6_ppc64el.deb" ], "version": "1.0.8-6" }, { "arch": "ppc64el", "dependencies": [], "key": "libcrypt1_1-4.4.38-1_ppc64el", "name": "libcrypt1", "sha256": "271558e9158d9c01e706d2b8702b9ffcca50858e52e840482789d1e52ee7c5d2", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/libx/libxcrypt/libcrypt1_4.4.38-1_ppc64el.deb" ], "version": "1:4.4.38-1" }, { "arch": "ppc64el", "dependencies": [], "key": "libexpat1_2.7.1-2_ppc64el", "name": "libexpat1", "sha256": "0bee337d77fbe3f2da4a4bc01fca418c12488f2a52edf8d71ff2ff9d1eec0dee", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/e/expat/libexpat1_2.7.1-2_ppc64el.deb" ], "version": "2.7.1-2" }, { "arch": "ppc64el", "dependencies": [], "key": "libfontconfig1_2.15.0-2.3_ppc64el", "name": "libfontconfig1", "sha256": "8850e0627a3c934d1a0ee507a2a3ca3a40ba9fbdc835283a05f835cc8ba0c608", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/f/fontconfig/libfontconfig1_2.15.0-2.3_ppc64el.deb" ], "version": "2.15.0-2.3" }, { "arch": "ppc64el", "dependencies": [], "key": "libfreetype6_2.13.3-p-dfsg-1_ppc64el", "name": "libfreetype6", "sha256": "23ebc1c4388cd9610049a933c609daf7e36be2ce2610e6d7a6214fdccbfe4173", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/f/freetype/libfreetype6_2.13.3+dfsg-1_ppc64el.deb" ], "version": "2.13.3+dfsg-1" }, { "arch": "ppc64el", "dependencies": [], "key": "libglib2.0-0t64_2.84.4-3_deb13u2_ppc64el", "name": "libglib2.0-0t64", "sha256": "1f5efffa7a48ec7154c78820751c467a9e38a699135280a2c96d6e342ab38bdf", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/glib2.0/libglib2.0-0t64_2.84.4-3~deb13u2_ppc64el.deb" ], "version": "2.84.4-3~deb13u2" }, { "arch": "ppc64el", "dependencies": [], "key": "libgraphite2-3_1.3.14-2-p-b1_ppc64el", "name": "libgraphite2-3", "sha256": "10ba655d80e1b67a34ff3a2de16dd4f25a210c0e83d460637c912deea40d46fc", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/graphite2/libgraphite2-3_1.3.14-2+b1_ppc64el.deb" ], "version": "1.3.14-2+b1" }, { "arch": "ppc64el", "dependencies": [], "key": "libharfbuzz0b_10.2.0-1-p-b1_ppc64el", "name": "libharfbuzz0b", "sha256": "4b202116b68a726b3df0d0e5cfc5e60fc041c185dbf1dc075bf8df0620c652fe", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/h/harfbuzz/libharfbuzz0b_10.2.0-1+b1_ppc64el.deb" ], "version": "10.2.0-1+b1" }, { "arch": "ppc64el", "dependencies": [], "key": "libjpeg62-turbo_1-2.1.5-4_ppc64el", "name": "libjpeg62-turbo", "sha256": "e64e9c819ae310538e8e8273784c291cd347a6ecf8f52fa1cbc36b5c3f20399b", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/libj/libjpeg-turbo/libjpeg62-turbo_2.1.5-4_ppc64el.deb" ], "version": "1:2.1.5-4" }, { "arch": "ppc64el", "dependencies": [], "key": "liblcms2-2_2.16-2_ppc64el", "name": "liblcms2-2", "sha256": "b21cfab91854a77e643cdf7b6bc8cbb9b6d42663a21f5638a68cd9e12e104e00", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/l/lcms2/liblcms2-2_2.16-2_ppc64el.deb" ], "version": "2.16-2" }, { "arch": "ppc64el", "dependencies": [], "key": "libpcre2-8-0_10.46-1_deb13u1_ppc64el", "name": "libpcre2-8-0", "sha256": "9c78fe76ba1f39cc2a2bec4182fb816606b7d4e217b2c8c7d46e2b4ab335f92b", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/p/pcre2/libpcre2-8-0_10.46-1~deb13u1_ppc64el.deb" ], "version": "10.46-1~deb13u1" }, { "arch": "ppc64el", "dependencies": [], "key": "libpng16-16t64_1.6.48-1-p-deb13u3_ppc64el", "name": "libpng16-16t64", "sha256": "863897dcd7be77a7bb88d883a1506454c85d06254cc37f4ed405c85e806cd091", "urls": [ "https://snapshot.debian.org/archive/debian-security/20260314T202839Z/pool/updates/main/libp/libpng1.6/libpng16-16t64_1.6.48-1+deb13u3_ppc64el.deb" ], "version": "1.6.48-1+deb13u3" }, { "arch": "ppc64el", "dependencies": [], "key": "libuuid1_2.41-5_ppc64el", "name": "libuuid1", "sha256": "7600e5c742c0231bbbd91f37304bc7a19855984de6313886ea4f09ef2fced4be", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/u/util-linux/libuuid1_2.41-5_ppc64el.deb" ], "version": "2.41-5" }, { "arch": "ppc64el", "dependencies": [], "key": "zlib1g_1-1.3.dfsg-p-really1.3.1-1-p-b1_ppc64el", "name": "zlib1g", "sha256": "f526e830310db11983cf51cfde95a74bc449a7bdc44b6ce68827d78802f1b4ae", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/z/zlib/zlib1g_1.3.dfsg+really1.3.1-1+b1_ppc64el.deb" ], "version": "1:1.3.dfsg+really1.3.1-1+b1" }, { "arch": "ppc64el", "dependencies": [], "key": "gcc-14-base_14.2.0-19_ppc64el", "name": "gcc-14-base", "sha256": "ebb80291fedd8db88488eef76573df0b4a1a11648a16406d9a0c0d4aaf229593", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-14/gcc-14-base_14.2.0-19_ppc64el.deb" ], "version": "14.2.0-19" }, { "arch": "ppc64el", "dependencies": [], "key": "libgcc-s1_14.2.0-19_ppc64el", "name": "libgcc-s1", "sha256": "9fef01c88bc508ff05ff9ce5d0cc05de36798591e060b07749c3835616ed5696", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-14/libgcc-s1_14.2.0-19_ppc64el.deb" ], "version": "14.2.0-19" }, { "arch": "ppc64el", "dependencies": [], "key": "libstdc-p--p-6_14.2.0-19_ppc64el", "name": "libstdc++6", "sha256": "ee601ab87b7c7ac01f3d7be0fe2423f0ddc3a51b46d3331b4e9dff4110e6a8b9", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-14/libstdc++6_14.2.0-19_ppc64el.deb" ], "version": "14.2.0-19" }, { "arch": "riscv64", "dependencies": [], "key": "fontconfig-config_2.15.0-2.3_riscv64", "name": "fontconfig-config", "sha256": "4fd18a83b8d86f3493ad7ab714a77bfdb18ca19139168aea7161231a420963b5", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/f/fontconfig/fontconfig-config_2.15.0-2.3_riscv64.deb" ], "version": "2.15.0-2.3" }, { "arch": "riscv64", "dependencies": [], "key": "fonts-dejavu-core_2.37-8_riscv64", "name": "fonts-dejavu-core", "sha256": "86635b3d25b3655fc11cb3ecc3af59f0bf19643b02b94f2de48bd10253cdba12", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/f/fonts-dejavu/fonts-dejavu-core_2.37-8_all.deb" ], "version": "2.37-8" }, { "arch": "riscv64", "dependencies": [], "key": "libbrotli1_1.1.0-2-p-b7_riscv64", "name": "libbrotli1", "sha256": "c18cc200551f11cc2e22514c1625c12e83a2c4155ddee78f77fb1f2c26fe3c6a", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/b/brotli/libbrotli1_1.1.0-2+b7_riscv64.deb" ], "version": "1.1.0-2+b7" }, { "arch": "riscv64", "dependencies": [], "key": "libbz2-1.0_1.0.8-6_riscv64", "name": "libbz2-1.0", "sha256": "27c7937eb4d2e314e1f0a57a99a20c141c55f720e5ee93d2244de432fd247a55", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/b/bzip2/libbz2-1.0_1.0.8-6_riscv64.deb" ], "version": "1.0.8-6" }, { "arch": "riscv64", "dependencies": [], "key": "libcrypt1_1-4.4.38-1_riscv64", "name": "libcrypt1", "sha256": "85ae0d868b2a27043249ca332dac782a1a67e3171139b0f57d63414eaf4ec887", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/libx/libxcrypt/libcrypt1_4.4.38-1_riscv64.deb" ], "version": "1:4.4.38-1" }, { "arch": "riscv64", "dependencies": [], "key": "libexpat1_2.7.1-2_riscv64", "name": "libexpat1", "sha256": "73d5d2aae20867ccd38d92e68f04ec63887964d1704836a6e3ee550142218b76", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/e/expat/libexpat1_2.7.1-2_riscv64.deb" ], "version": "2.7.1-2" }, { "arch": "riscv64", "dependencies": [], "key": "libfontconfig1_2.15.0-2.3_riscv64", "name": "libfontconfig1", "sha256": "dc06597ba8578cccf2e39ef1aa0cb281e805b3c51588ffa185dc83d5d5fa8a89", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/f/fontconfig/libfontconfig1_2.15.0-2.3_riscv64.deb" ], "version": "2.15.0-2.3" }, { "arch": "riscv64", "dependencies": [], "key": "libfreetype6_2.13.3-p-dfsg-1_riscv64", "name": "libfreetype6", "sha256": "60f12a364d14006ac3db690d48bfb612aad9a63b7a48c984b46d64d5c8efd7d1", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/f/freetype/libfreetype6_2.13.3+dfsg-1_riscv64.deb" ], "version": "2.13.3+dfsg-1" }, { "arch": "riscv64", "dependencies": [], "key": "libglib2.0-0t64_2.84.4-3_deb13u2_riscv64", "name": "libglib2.0-0t64", "sha256": "871f0878240b26721d952d348fdb76b4bcc31ef97a65260e40fd5ae6d5a8040a", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/glib2.0/libglib2.0-0t64_2.84.4-3~deb13u2_riscv64.deb" ], "version": "2.84.4-3~deb13u2" }, { "arch": "riscv64", "dependencies": [], "key": "libgraphite2-3_1.3.14-2-p-b1_riscv64", "name": "libgraphite2-3", "sha256": "e53a9debf6b8e2fafe9d22952c3a6de720b318ff592ef67dc354c748c810ba40", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/graphite2/libgraphite2-3_1.3.14-2+b1_riscv64.deb" ], "version": "1.3.14-2+b1" }, { "arch": "riscv64", "dependencies": [], "key": "libharfbuzz0b_10.2.0-1-p-b1_riscv64", "name": "libharfbuzz0b", "sha256": "1982c5b99ec2ed7dff65482ad816966dbffb35818a81ddb453b226d48cee2c0b", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/h/harfbuzz/libharfbuzz0b_10.2.0-1+b1_riscv64.deb" ], "version": "10.2.0-1+b1" }, { "arch": "riscv64", "dependencies": [], "key": "libjpeg62-turbo_1-2.1.5-4_riscv64", "name": "libjpeg62-turbo", "sha256": "859970b9a4379c1cdef6127fcdc21fd6a445f0188e9bd8a35199d2d6bcd49a3b", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/libj/libjpeg-turbo/libjpeg62-turbo_2.1.5-4_riscv64.deb" ], "version": "1:2.1.5-4" }, { "arch": "riscv64", "dependencies": [], "key": "liblcms2-2_2.16-2_riscv64", "name": "liblcms2-2", "sha256": "9bebcd4f35358b340c3c4b2006df7cbf0bc7461ddfbae3d9f3ce7ce5c095b4e0", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/l/lcms2/liblcms2-2_2.16-2_riscv64.deb" ], "version": "2.16-2" }, { "arch": "riscv64", "dependencies": [], "key": "libpcre2-8-0_10.46-1_deb13u1_riscv64", "name": "libpcre2-8-0", "sha256": "862091023de3e70cf4e4f80347e54873800169a2f39d8111f5faa6c7a7f5009c", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/p/pcre2/libpcre2-8-0_10.46-1~deb13u1_riscv64.deb" ], "version": "10.46-1~deb13u1" }, { "arch": "riscv64", "dependencies": [], "key": "libpng16-16t64_1.6.48-1-p-deb13u3_riscv64", "name": "libpng16-16t64", "sha256": "257a8ed3ba11a471764ef20a0b12b46c6c70f41277dad4d56f5886d82da013fd", "urls": [ "https://snapshot.debian.org/archive/debian-security/20260314T202839Z/pool/updates/main/libp/libpng1.6/libpng16-16t64_1.6.48-1+deb13u3_riscv64.deb" ], "version": "1.6.48-1+deb13u3" }, { "arch": "riscv64", "dependencies": [], "key": "libuuid1_2.41-5_riscv64", "name": "libuuid1", "sha256": "01e0da9223fe9963270227f532f1bb57c01013ede0411710836181ab72192839", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/u/util-linux/libuuid1_2.41-5_riscv64.deb" ], "version": "2.41-5" }, { "arch": "riscv64", "dependencies": [], "key": "zlib1g_1-1.3.dfsg-p-really1.3.1-1-p-b1_riscv64", "name": "zlib1g", "sha256": "38c52eef58e5fc9b13d93f8a7d0a0549c32b4f00402a778d39a135254f554314", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/z/zlib/zlib1g_1.3.dfsg+really1.3.1-1+b1_riscv64.deb" ], "version": "1:1.3.dfsg+really1.3.1-1+b1" }, { "arch": "riscv64", "dependencies": [], "key": "gcc-14-base_14.2.0-19_riscv64", "name": "gcc-14-base", "sha256": "bb871e84c5c108463fa6a858e72f15cbf809f3888442b89941fc625449874206", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-14/gcc-14-base_14.2.0-19_riscv64.deb" ], "version": "14.2.0-19" }, { "arch": "riscv64", "dependencies": [], "key": "libgcc-s1_14.2.0-19_riscv64", "name": "libgcc-s1", "sha256": "16d3f9f534028615413d23f649e5d246baef48fe7db739ad564ef8b9a6e5587c", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-14/libgcc-s1_14.2.0-19_riscv64.deb" ], "version": "14.2.0-19" }, { "arch": "riscv64", "dependencies": [], "key": "libstdc-p--p-6_14.2.0-19_riscv64", "name": "libstdc++6", "sha256": "f285313f34e0d8f65463c669fac8eb29760a3f3fd6459005dd3110cdd2b10fd7", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/gcc-14/libstdc++6_14.2.0-19_riscv64.deb" ], "version": "14.2.0-19" } ], "version": 1 } ================================================ FILE: private/repos/deb/trixie_java.yaml ================================================ # debian 13, limited architectures, java only version: 1 sources: - channel: trixie main url: https://snapshot.debian.org/archive/debian/20260314T202839Z - channel: trixie-updates main url: https://snapshot.debian.org/archive/debian/20260314T202839Z - channel: trixie-security main url: https://snapshot.debian.org/archive/debian-security/20260314T202839Z archs: - amd64 - arm64 - s390x - ppc64el - riscv64 packages: - fontconfig-config - fonts-dejavu-core - libbrotli1 - libbz2-1.0 - libcrypt1 # TODO: glibc library for -lcrypt; maybe should be in cc? - libexpat1 - libfontconfig1 - libfreetype6 - libglib2.0-0t64 - libgraphite2-3 - libharfbuzz0b - libjpeg62-turbo - liblcms2-2 - libpcre2-8-0 - libpng16-16t64 - libuuid1 - zlib1g # java image builds off base (not cc) - gcc-14-base - libgcc-s1 - libstdc++6 ================================================ FILE: private/repos/deb/trixie_python.lock.json ================================================ { "packages": [ { "arch": "amd64", "dependencies": [], "key": "libbz2-1.0_1.0.8-6_amd64", "name": "libbz2-1.0", "sha256": "cba4cda04244b5e481bb15524bc3c983a7d1b6f330013b9b381706a2fcb65310", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/b/bzip2/libbz2-1.0_1.0.8-6_amd64.deb" ], "version": "1.0.8-6" }, { "arch": "amd64", "dependencies": [], "key": "libcom-err2_1.47.2-3-p-b10_amd64", "name": "libcom-err2", "sha256": "a130de40aba78abeea8c9db49a26457ba74ef5c6194c9da3018935a088269397", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/e/e2fsprogs/libcom-err2_1.47.2-3+b10_amd64.deb" ], "version": "1.47.2-3+b10" }, { "arch": "amd64", "dependencies": [], "key": "libcrypt1_1-4.4.38-1_amd64", "name": "libcrypt1", "sha256": "0ebc144d662e3197982d1bf3a7b8b35ca845e54c68811de0328b1f0d7c67585c", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/libx/libxcrypt/libcrypt1_4.4.38-1_amd64.deb" ], "version": "1:4.4.38-1" }, { "arch": "amd64", "dependencies": [], "key": "libdb5.3t64_5.3.28-p-dfsg2-9_amd64", "name": "libdb5.3t64", "sha256": "18d02510ee78b67e4504ba050176797a200ff24214a7cd318082ab60ad7bf3fc", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/d/db5.3/libdb5.3t64_5.3.28+dfsg2-9_amd64.deb" ], "version": "5.3.28+dfsg2-9" }, { "arch": "amd64", "dependencies": [], "key": "libexpat1_2.7.1-2_amd64", "name": "libexpat1", "sha256": "f875f56675be5b074da877f9a93b09d47dc2eb4e679951d36e2943b8d4843344", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/e/expat/libexpat1_2.7.1-2_amd64.deb" ], "version": "2.7.1-2" }, { "arch": "amd64", "dependencies": [], "key": "libc-bin_2.41-12-p-deb13u2_amd64", "name": "libc-bin", "sha256": "e30df1bcd947889cd96b5a094e0bf6be6acb4d6d7d2b6def0507f36b432916be", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/glibc/libc-bin_2.41-12+deb13u2_amd64.deb" ], "version": "2.41-12+deb13u2" }, { "arch": "amd64", "dependencies": [], "key": "libffi8_3.4.8-2_amd64", "name": "libffi8", "sha256": "0ebdc340de33333639c3c63874cd4b15ac2e83dfa1ef3053b7eefaf4919f4f68", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/libf/libffi/libffi8_3.4.8-2_amd64.deb" ], "version": "3.4.8-2" }, { "arch": "amd64", "dependencies": [], "key": "libgssapi-krb5-2_1.21.3-5_amd64", "name": "libgssapi-krb5-2", "sha256": "53678c63919fc717816941947a9d275be8d6cb101a3753ae8fda0cf6e752d9d7", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/k/krb5/libgssapi-krb5-2_1.21.3-5_amd64.deb" ], "version": "1.21.3-5" }, { "arch": "amd64", "dependencies": [], "key": "libk5crypto3_1.21.3-5_amd64", "name": "libk5crypto3", "sha256": "3368c4b8fd7f0172ba0f1cbd31d150d9ab3c67cc3f4bc3a4c77d895ade0701c4", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/k/krb5/libk5crypto3_1.21.3-5_amd64.deb" ], "version": "1.21.3-5" }, { "arch": "amd64", "dependencies": [], "key": "libkeyutils1_1.6.3-6_amd64", "name": "libkeyutils1", "sha256": "0b11ad17be0300b63ad4eeb4c6450fed24d34b7b740f23e5363dcb29ee6d5eba", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/k/keyutils/libkeyutils1_1.6.3-6_amd64.deb" ], "version": "1.6.3-6" }, { "arch": "amd64", "dependencies": [], "key": "libkrb5-3_1.21.3-5_amd64", "name": "libkrb5-3", "sha256": "7e286fff31330a174a0df0ddfee19e388d7b1825f684aa55a3b62bcab5737c9a", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/k/krb5/libkrb5-3_1.21.3-5_amd64.deb" ], "version": "1.21.3-5" }, { "arch": "amd64", "dependencies": [], "key": "libkrb5support0_1.21.3-5_amd64", "name": "libkrb5support0", "sha256": "15254b79d38d3f3abdc9385ccd56e0a84fc67738ec5af1fcd5e2723b0ef38b92", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/k/krb5/libkrb5support0_1.21.3-5_amd64.deb" ], "version": "1.21.3-5" }, { "arch": "amd64", "dependencies": [], "key": "liblzma5_5.8.1-1_amd64", "name": "liblzma5", "sha256": "3a4b863e62478b1895909c5d3b719da0395d6fe6da46f2218db2b0436e0fe892", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/x/xz-utils/liblzma5_5.8.1-1_amd64.deb" ], "version": "5.8.1-1" }, { "arch": "amd64", "dependencies": [], "key": "libncursesw6_6.5-p-20250216-2_amd64", "name": "libncursesw6", "sha256": "47baa2e11579583654583a066b69bd5a5d2f22423081f707ed6c0c3ba6d538b7", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/n/ncurses/libncursesw6_6.5+20250216-2_amd64.deb" ], "version": "6.5+20250216-2" }, { "arch": "amd64", "dependencies": [], "key": "libnsl2_1.3.0-3-p-b3_amd64", "name": "libnsl2", "sha256": "f1f11fc62a44cc8ca0fee6cf032b56d3554ea7355b300538b01085ee624f09dc", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/libn/libnsl/libnsl2_1.3.0-3+b3_amd64.deb" ], "version": "1.3.0-3+b3" }, { "arch": "amd64", "dependencies": [], "key": "libpython3.13-minimal_3.13.5-2_amd64", "name": "libpython3.13-minimal", "sha256": "d4972bf4b407236b1751e2346bfdd92848c224f6117992a1b13cbffeb91ad3cb", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/p/python3.13/libpython3.13-minimal_3.13.5-2_amd64.deb" ], "version": "3.13.5-2" }, { "arch": "amd64", "dependencies": [], "key": "libpython3.13-stdlib_3.13.5-2_amd64", "name": "libpython3.13-stdlib", "sha256": "b05308cc6697b2b93e3504c25638abc4c2b0d1293b626a265aca2dbc5bd2eea4", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/p/python3.13/libpython3.13-stdlib_3.13.5-2_amd64.deb" ], "version": "3.13.5-2" }, { "arch": "amd64", "dependencies": [], "key": "libreadline8t64_8.2-6_amd64", "name": "libreadline8t64", "sha256": "eeadf2b5e755c9f183883feea2d9b5b28560284275d5f54d3e55d0923b1d0967", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/r/readline/libreadline8t64_8.2-6_amd64.deb" ], "version": "8.2-6" }, { "arch": "amd64", "dependencies": [], "key": "libsqlite3-0_3.46.1-7-p-deb13u1_amd64", "name": "libsqlite3-0", "sha256": "edeacbdd6a86ee82d314dccc180b740905fd7f6392b72e5c0533079fda449361", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/s/sqlite3/libsqlite3-0_3.46.1-7+deb13u1_amd64.deb" ], "version": "3.46.1-7+deb13u1" }, { "arch": "amd64", "dependencies": [], "key": "libtinfo6_6.5-p-20250216-2_amd64", "name": "libtinfo6", "sha256": "8b9f6a7983e9418564e48a627518de4c03917b56efe68d7f3e93bd8fffa1cc10", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/n/ncurses/libtinfo6_6.5+20250216-2_amd64.deb" ], "version": "6.5+20250216-2" }, { "arch": "amd64", "dependencies": [], "key": "libtirpc3t64_1.3.6-p-ds-1_amd64", "name": "libtirpc3t64", "sha256": "ef4536c09bf5063554310e22d586ae90990100ba66d2fe7c35660e9e658913b6", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/libt/libtirpc/libtirpc3t64_1.3.6+ds-1_amd64.deb" ], "version": "1.3.6+ds-1" }, { "arch": "amd64", "dependencies": [], "key": "libuuid1_2.41-5_amd64", "name": "libuuid1", "sha256": "10247744737c1bb574f9667b3f06a3b43a5055c67bdfcc1945803451cc036db3", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/u/util-linux/libuuid1_2.41-5_amd64.deb" ], "version": "2.41-5" }, { "arch": "amd64", "dependencies": [], "key": "python3.13-venv_3.13.5-2_amd64", "name": "python3.13-venv", "sha256": "15138cb3306f06a2d336eabe563f6aeda9e42453261090f70ef32afaff40c425", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/p/python3.13/python3.13-venv_3.13.5-2_amd64.deb" ], "version": "3.13.5-2" }, { "arch": "amd64", "dependencies": [], "key": "python3.13-minimal_3.13.5-2_amd64", "name": "python3.13-minimal", "sha256": "d2d51b516de9e9b9fb6f7c4411deb3dd049b81eca400087c3457bc85c026eca8", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/p/python3.13/python3.13-minimal_3.13.5-2_amd64.deb" ], "version": "3.13.5-2" }, { "arch": "amd64", "dependencies": [], "key": "zlib1g_1-1.3.dfsg-p-really1.3.1-1-p-b1_amd64", "name": "zlib1g", "sha256": "015be740d6236ad114582dea500c1d907f29e16d6db00566ca32fb68d71ac90d", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/z/zlib/zlib1g_1.3.dfsg+really1.3.1-1+b1_amd64.deb" ], "version": "1:1.3.dfsg+really1.3.1-1+b1" }, { "arch": "arm64", "dependencies": [], "key": "libbz2-1.0_1.0.8-6_arm64", "name": "libbz2-1.0", "sha256": "3537fe4fc577a60c8a9568873cd577db7ebc135eb8bb1825f18caf8972d9d2f2", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/b/bzip2/libbz2-1.0_1.0.8-6_arm64.deb" ], "version": "1.0.8-6" }, { "arch": "arm64", "dependencies": [], "key": "libcom-err2_1.47.2-3-p-b10_arm64", "name": "libcom-err2", "sha256": "1b525834224b1fdfcc817f2a5a199a001de4ca4ea627f81ebd666798fe351ae1", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/e/e2fsprogs/libcom-err2_1.47.2-3+b10_arm64.deb" ], "version": "1.47.2-3+b10" }, { "arch": "arm64", "dependencies": [], "key": "libcrypt1_1-4.4.38-1_arm64", "name": "libcrypt1", "sha256": "b9aaa808aa3812b3de3e54eb5dfb16762c1779db032604abef2354c02fdc29b8", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/libx/libxcrypt/libcrypt1_4.4.38-1_arm64.deb" ], "version": "1:4.4.38-1" }, { "arch": "arm64", "dependencies": [], "key": "libdb5.3t64_5.3.28-p-dfsg2-9_arm64", "name": "libdb5.3t64", "sha256": "bfef56508d69fd3f940668f6abd0a466a362cabf63c4cc1c787cc58d28f6e92f", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/d/db5.3/libdb5.3t64_5.3.28+dfsg2-9_arm64.deb" ], "version": "5.3.28+dfsg2-9" }, { "arch": "arm64", "dependencies": [], "key": "libexpat1_2.7.1-2_arm64", "name": "libexpat1", "sha256": "7f6868227f4893a11123e43b9ed291950b550c7dc209905b2fb871c74678d1bf", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/e/expat/libexpat1_2.7.1-2_arm64.deb" ], "version": "2.7.1-2" }, { "arch": "arm64", "dependencies": [], "key": "libc-bin_2.41-12-p-deb13u2_arm64", "name": "libc-bin", "sha256": "c533ba20b97e8cec1ad816936043e7c2cfa24e724e13e99eaa66cad74fbff0c8", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/g/glibc/libc-bin_2.41-12+deb13u2_arm64.deb" ], "version": "2.41-12+deb13u2" }, { "arch": "arm64", "dependencies": [], "key": "libffi8_3.4.8-2_arm64", "name": "libffi8", "sha256": "d84a783b818f2386627604e64b793eb4ac5bb9ea1ba321a194a1c9c82fe09a01", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/libf/libffi/libffi8_3.4.8-2_arm64.deb" ], "version": "3.4.8-2" }, { "arch": "arm64", "dependencies": [], "key": "libgssapi-krb5-2_1.21.3-5_arm64", "name": "libgssapi-krb5-2", "sha256": "99fd6203890ac144ba9907fefb76c84e733f17f31853af8c312c16d5c077c351", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/k/krb5/libgssapi-krb5-2_1.21.3-5_arm64.deb" ], "version": "1.21.3-5" }, { "arch": "arm64", "dependencies": [], "key": "libk5crypto3_1.21.3-5_arm64", "name": "libk5crypto3", "sha256": "5ed29027bb77365ecbf4e1b54701cf802871e0a82c08f29c4177057e08d5469a", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/k/krb5/libk5crypto3_1.21.3-5_arm64.deb" ], "version": "1.21.3-5" }, { "arch": "arm64", "dependencies": [], "key": "libkeyutils1_1.6.3-6_arm64", "name": "libkeyutils1", "sha256": "5e680f317a6613161986417fb3ed63007c9228343f5ac2348551b103cc7fd7b4", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/k/keyutils/libkeyutils1_1.6.3-6_arm64.deb" ], "version": "1.6.3-6" }, { "arch": "arm64", "dependencies": [], "key": "libkrb5-3_1.21.3-5_arm64", "name": "libkrb5-3", "sha256": "0f8d4555b39483ac003814b6f9b9d312dca4492ff4b34b084745b01dac514b4d", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/k/krb5/libkrb5-3_1.21.3-5_arm64.deb" ], "version": "1.21.3-5" }, { "arch": "arm64", "dependencies": [], "key": "libkrb5support0_1.21.3-5_arm64", "name": "libkrb5support0", "sha256": "2c7bb86d48262263b0c1df9bc45e9330aaa32bcd1a8860c2e0be25fc4cb14053", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/k/krb5/libkrb5support0_1.21.3-5_arm64.deb" ], "version": "1.21.3-5" }, { "arch": "arm64", "dependencies": [], "key": "liblzma5_5.8.1-1_arm64", "name": "liblzma5", "sha256": "cf6dcb3a8ee0b86c4f021c7dc07458fe6db6686c1d4e7b12217cecd2a80a40b9", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/x/xz-utils/liblzma5_5.8.1-1_arm64.deb" ], "version": "5.8.1-1" }, { "arch": "arm64", "dependencies": [], "key": "libncursesw6_6.5-p-20250216-2_arm64", "name": "libncursesw6", "sha256": "72121aeb08be2d915da321ddfae74f62a0764286f336279b2c2609ba07496d6d", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/n/ncurses/libncursesw6_6.5+20250216-2_arm64.deb" ], "version": "6.5+20250216-2" }, { "arch": "arm64", "dependencies": [], "key": "libnsl2_1.3.0-3-p-b3_arm64", "name": "libnsl2", "sha256": "9d7f225630711e67d0159f7f05763e76e752fa7b36b39f59d72204a59940d3ca", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/libn/libnsl/libnsl2_1.3.0-3+b3_arm64.deb" ], "version": "1.3.0-3+b3" }, { "arch": "arm64", "dependencies": [], "key": "libpython3.13-minimal_3.13.5-2_arm64", "name": "libpython3.13-minimal", "sha256": "e1fbde71bf7f0de82a70c0a7bc6e1100fd7001b90ce36b4f346476a5b671b5e6", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/p/python3.13/libpython3.13-minimal_3.13.5-2_arm64.deb" ], "version": "3.13.5-2" }, { "arch": "arm64", "dependencies": [], "key": "libpython3.13-stdlib_3.13.5-2_arm64", "name": "libpython3.13-stdlib", "sha256": "80364ce9f7f1efefc6e4aed73793fa21040b86b17fd1c51f7a7b1fd9e16c0157", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/p/python3.13/libpython3.13-stdlib_3.13.5-2_arm64.deb" ], "version": "3.13.5-2" }, { "arch": "arm64", "dependencies": [], "key": "libreadline8t64_8.2-6_arm64", "name": "libreadline8t64", "sha256": "f78ff432b2a627bc04f7eef0e6e2696501c9e06feca748a5b741d5e594429033", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/r/readline/libreadline8t64_8.2-6_arm64.deb" ], "version": "8.2-6" }, { "arch": "arm64", "dependencies": [], "key": "libsqlite3-0_3.46.1-7-p-deb13u1_arm64", "name": "libsqlite3-0", "sha256": "69dd4b705eca29fe134c17f18aaa4cc9e7ecd01c0250d5e195358801514c76ac", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/s/sqlite3/libsqlite3-0_3.46.1-7+deb13u1_arm64.deb" ], "version": "3.46.1-7+deb13u1" }, { "arch": "arm64", "dependencies": [], "key": "libtinfo6_6.5-p-20250216-2_arm64", "name": "libtinfo6", "sha256": "2a747f7fff3c2347c357387a7133df997410f07ba1b1df1a1461a97bd7fbc2fc", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/n/ncurses/libtinfo6_6.5+20250216-2_arm64.deb" ], "version": "6.5+20250216-2" }, { "arch": "arm64", "dependencies": [], "key": "libtirpc3t64_1.3.6-p-ds-1_arm64", "name": "libtirpc3t64", "sha256": "ae390ce96435829f0d5252305fb9b22001f5bcc85477e452373ddb2a4fa4dbc1", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/libt/libtirpc/libtirpc3t64_1.3.6+ds-1_arm64.deb" ], "version": "1.3.6+ds-1" }, { "arch": "arm64", "dependencies": [], "key": "libuuid1_2.41-5_arm64", "name": "libuuid1", "sha256": "85b7d04605f9d423d5699b3c07f027e8380649fd164a51e0712cded0cc56eced", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/u/util-linux/libuuid1_2.41-5_arm64.deb" ], "version": "2.41-5" }, { "arch": "arm64", "dependencies": [], "key": "python3.13-venv_3.13.5-2_arm64", "name": "python3.13-venv", "sha256": "02d75b0c903efbe5e06ce079ff3967bafd08c621c846d7fe332b71d69de31c4c", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/p/python3.13/python3.13-venv_3.13.5-2_arm64.deb" ], "version": "3.13.5-2" }, { "arch": "arm64", "dependencies": [], "key": "python3.13-minimal_3.13.5-2_arm64", "name": "python3.13-minimal", "sha256": "a30123d05bc5f8ffec984efbfd138b3c8719f352797e29e643a7486457473982", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/p/python3.13/python3.13-minimal_3.13.5-2_arm64.deb" ], "version": "3.13.5-2" }, { "arch": "arm64", "dependencies": [], "key": "zlib1g_1-1.3.dfsg-p-really1.3.1-1-p-b1_arm64", "name": "zlib1g", "sha256": "209aa5cf671e97b9eb0410844fa6df4cae2e75b0c72e7802ab6c8ece13e6ddef", "urls": [ "https://snapshot.debian.org/archive/debian/20260314T202839Z/pool/main/z/zlib/zlib1g_1.3.dfsg+really1.3.1-1+b1_arm64.deb" ], "version": "1:1.3.dfsg+really1.3.1-1+b1" } ], "version": 1 } ================================================ FILE: private/repos/deb/trixie_python.yaml ================================================ # debian 13, limited architectures, python only version: 1 sources: - channel: trixie main url: https://snapshot.debian.org/archive/debian/20260314T202839Z - channel: trixie-updates main url: https://snapshot.debian.org/archive/debian/20260314T202839Z - channel: trixie-security main url: https://snapshot.debian.org/archive/debian-security/20260314T202839Z archs: - amd64 - arm64 packages: - libbz2-1.0 - libcom-err2 - libcrypt1 # TODO: glibc library for -lcrypt; maybe should be in cc? - libdb5.3t64 - libexpat1 - libc-bin - libffi8 - libgssapi-krb5-2 - libk5crypto3 - libkeyutils1 - libkrb5-3 - libkrb5support0 - liblzma5 - libncursesw6 - libnsl2 - libpython3.13-minimal - libpython3.13-stdlib - libreadline8t64 - libsqlite3-0 - libtinfo6 - libtirpc3t64 - libuuid1 - python3.13-venv - python3.13-minimal - zlib1g ================================================ FILE: private/stamp.bash ================================================ #!/usr/bin/env bash set -o pipefail -o errexit -o nounset # Do not error if the user doesn't have gcloud installed. if [ -z "${PROJECT_ID:-}" ]; then if which gcloud > /dev/null; then PROJECT_ID="$(gcloud config get-value core/project)" else # some registries don't allow uppercase chars. we'll use lowercase ones to get meaningful error messages. PROJECT_ID="no-project" fi fi echo "PROJECT_ID ${PROJECT_ID}" echo "COMMIT_SHA ${COMMIT_SHA:-no-commit-sha}" echo "REGISTRY ${REGISTRY:-gcr.io}" ================================================ FILE: private/tools/diff/BUILD.bazel ================================================ sh_binary( name = "diff", srcs = ["diff.bash"], args = [ "--head-ref", "test", "--base-ref", "test", "--report", "./report.log", "--query-bazel", "--registry-spawn-https", "--cd-into-workspace", ], ) ================================================ FILE: private/tools/diff/diff.bash ================================================ #!/usr/bin/env bash set -o pipefail -o errexit -o nounset # ./private/tools/diff/diff.bash --head-ref test --base-ref test --query-bazel --registry-spawn --report ./report.log STDERR=$(mktemp) # Upon exiting, stop the registry and print STDERR on non-zero exit code. on_exit() { last_exit_code=$? set +o errexit if [[ $last_exit_code != 0 ]]; then echo "" echo "💥 Something went wrong." if [[ $(wc -c <"${STDERR}") -gt 0 ]]; then echo "" echo "Here's the STDERR:" echo "" cat $STDERR fi fi pkill -P $$ } trap "on_exit" EXIT PID= HEAD_REF= BASE_REF= QUERY_FILE= REPORT_FILE= REGISTRY= JOBS= STDERR=$(mktemp) CHANGED_IMAGES_FILE=$(mktemp) SET_GITHUB_OUTPUT="0" ONLY= SKIP_INDEX="0" while (($# > 0)); do case $1 in --base-ref) BASE_REF="$2" shift 2 ;; --head-ref) HEAD_REF="$2" shift 2 ;; --registry) REGISTRY="$2" shift 2 ;; --registry-spawn) REGISTRY="spawn" shift ;; --registry-spawn-https) REGISTRY="spawn_https" shift ;; --query) QUERY_FILE="$2" shift 2 ;; --query-bazel) QUERY_FILE="bazel" shift ;; --report) REPORT_FILE="$2" shift 2 ;; --set-github-output-on-diff) SET_GITHUB_OUTPUT="1" echo "changed_targets=" >> "$GITHUB_OUTPUT" shift ;; --jobs) JOBS="$2" shift 2 ;; --logs) STDERR="$2" shift 2 ;; --only) ONLY="$2" shift 2 ;; --cd-into-workspace) cd $BUILD_WORKSPACE_DIRECTORY shift ;; --skip-image-index) SKIP_INDEX="1" shift ;; *) echo "unknown arg $1" exit 1 ;; esac done if [[ -z "${REGISTRY}" ]]; then echo "--registry is required." exit 1 fi if [[ -z "${BASE_REF}" ]]; then echo "--base-ref is required." exit 1 fi if [[ -z "${HEAD_REF}" ]]; then echo "--head-ref is required." exit 1 fi if [[ -z "${QUERY_FILE}" ]]; then echo "--query or --query-bazel must be provided" exit 1 fi # Redirect stderr to the $STDERR temp file for the rest of the script. exec 2>>"${STDERR}" DISK_STORAGE="/tmp/diff-storage" if [[ "${QUERY_FILE}" == "bazel" ]]; then bazel build :sign_and_push.query QUERY_FILE=$(bazel cquery --output=files :sign_and_push.query) fi if [[ "${REGISTRY}" == "spawn_https" ]]; then # Make a self signed cert rm -f /tmp/localhost.pem /tmp/localhost-key.pem rm -rf $DISK_STORAGE mkcert -install (cd /tmp && mkcert localhost) echo '{ "http":{ "address":"127.0.0.1", "port":"4564", "tls": { "cert":"/tmp/localhost.pem", "key":"/tmp/localhost-key.pem" } }, "log": { "level": "info" }, "storage":{"rootDirectory":"/tmp/diff-storage"} }' >/tmp/cfg.json REGISTRY="localhost:4564" zot serve /tmp/cfg.json 1>&2 & sleep 1 fi if [[ "${REGISTRY}" == "spawn" ]]; then rm -rf $DISK_STORAGE mkdir $DISK_STORAGE REGISTRY="localhost:4564" crane registry serve --address "$REGISTRY" --disk "$DISK_STORAGE" & fi stamp_stage() { local str="$1" str=${str/"{COMMIT_SHA}"/"${HEAD_REF}"} str=${str/"{REGISTRY}"/"${REGISTRY}"} echo ${str/"{PROJECT_ID}"/"stage"} } stamp_origin() { local str=$1 str=${str/"{COMMIT_SHA}"/"${BASE_REF}"} str=${str/"{REGISTRY}"/"gcr.io"} echo ${str/"{PROJECT_ID}"/"distroless"} } function test_image() { IFS=" " read -r repo image_label <<<"$1" if [[ "${ONLY}" != "" && "${ONLY}" != "$image_label" ]]; then return fi repo_origin=$(stamp_origin "$repo") repo_stage=$(stamp_stage "$repo") if ! crane manifest "$repo_origin" > /dev/null; then echo "🆕 New image will be added to $repo_origin" if [[ "${SET_GITHUB_OUTPUT}" == "1" ]]; then echo "$image_label (new)" >> "$CHANGED_IMAGES_FILE" fi return fi if [[ "${SKIP_INDEX}" == "1" ]]; then if ! crane manifest "$repo_origin" | jq -e '.mediaType == "application/vnd.oci.image.manifest.v1+json"' > /dev/null; then echo "⏭️ Skipping image index $repo_origin" return fi fi echo "" echo "🚧 Diffing $repo_origin against $repo_stage" echo "" bazel build "$image_label" crane push "$(bazel cquery --output=files $image_label)" "$repo_stage" if ! diffoci diff --pull=always --all-platforms "$repo_origin" "$repo_stage"; then echo "" echo " 🔬 To reproduce: bazel run //private/tools/diff:diff -- --only $image_label" echo "" echo "👎 $repo_origin and $repo_stage are different." if [[ "${SET_GITHUB_OUTPUT}" == "1" ]]; then echo "$image_label" >> "$CHANGED_IMAGES_FILE" fi else echo "" echo "👍 $repo_origin and $repo_stage are identical." fi } if [[ -n "${REPORT_FILE}" ]]; then echo "Report can be found in: $REPORT_FILE" echo -n "" >$REPORT_FILE sleep 1 # Redirect rest of the file into both report file and stdout exec 1> >(tee -a "${REPORT_FILE}") fi # Parallelize using gnu parallel if [[ "${JOBS}" -gt 0 ]]; then export HEAD_REF BASE_REF REGISTRY REPORT_FILE SET_GITHUB_OUTPUT ONLY CHANGED_IMAGES_FILE SKIP_INDEX export -f stamp_origin stamp_stage test_image cat "${QUERY_FILE}" | parallel --eta --progress --jobs "${JOBS}" "set -o pipefail -o errexit -o nounset && test_image" else while IFS= read -r line || [ -n "$line" ]; do test_image "${line}" done <"${QUERY_FILE}" fi if [[ "${SET_GITHUB_OUTPUT}" == "1" ]]; then echo "changed_targets<> "$GITHUB_OUTPUT" cat "$CHANGED_IMAGES_FILE" >> "$GITHUB_OUTPUT" echo "EOF" >> "$GITHUB_OUTPUT" fi ================================================ FILE: private/tools/lifecycle/BUILD.bazel ================================================ "rules to deal with auto_vm lifecycle tagging" exports_files(["tag.sh"]) ================================================ FILE: private/tools/lifecycle/defs.bzl ================================================ load(":tag.bzl", _attach_lifecycle_tags = "attach_lifecycle_tags") attach_lifecycle_tags = _attach_lifecycle_tags ================================================ FILE: private/tools/lifecycle/tag.bzl ================================================ "rules for attaching lifecycle tags to older published images" load("@bazel_skylib//rules:write_file.bzl", "write_file") def _tag(ctx): script_file = ctx.executable.script runner_script = ctx.actions.declare_file(ctx.label.name + "_runner.sh") commands = ["#!/usr/bin/env bash", "set -euo pipefail"] for ref in ctx.attr.targets: commands.append("{script} update {ref}".format( script = script_file.short_path, ref = ref, )) ctx.actions.write( output = runner_script, content = "\n".join(commands), is_executable = True, ) return [ DefaultInfo( executable = runner_script, runfiles = ctx.runfiles(files = [script_file]), ), RunEnvironmentInfo( environment = {"DRY_RUN": "false"}, # maybe inherit this, need cloud build testing # inherited_environment = ["GOOGLE_APPLICATION_CREDENTIALS"], ), ] tag = rule( implementation = _tag, attrs = { "targets": attr.string_list(), "script": attr.label( mandatory = True, allow_single_file = True, executable = True, cfg = "exec", ), }, executable = True, ) def attach_lifecycle_tags(name, images): """simple macro to assign lifecycle tags to older images Args: name: name of the target images: a dict where keys are fully qualified image references and values are image label """ all_images = dict() for (ref, _) in images.items(): repository_and_tag = ref.split(":") # TODO: have these leverage ../stamp.bash repository = repository_and_tag[0].format(REGISTRY = "gcr.io", PROJECT_ID = "distroless") all_images[repository] = "ignored" write_file( name = name + ".query", content = sorted(all_images.keys()), out = name + "_query", ) tag( name = name, targets = sorted(all_images.keys()), script = Label("//private/tools/lifecycle:tag.sh"), ) ================================================ FILE: private/tools/lifecycle/tag.sh ================================================ #!/usr/bin/env bash set -euo pipefail trap 'echo "Ctrl+C caught, exiting..."; exit 130' INT function exec_tag() { local image=$1 local tag_prefix=$2 local -n hashes=$3 local count=0 local total="${#hashes[@]}" for h in "${hashes[@]}"; do local sha256="${h#sha256:}" local img_path="${image}@${h}" local tag="${tag_prefix}${sha256}" echo -n "tagging $img_path with $tag " if [[ ${dry_run} == false ]]; then gcrane tag "$img_path" "$tag" && echo "SUCCESS $((++count))/$total" || { echo "FAILED"; exit 1; } else echo "DRY_RUN" fi done } function tag_update() { local tag_prefix="update-available-" local image="$1" local NOW local images_json NOW=$(date +%s000) images_json=$(gcrane ls "$image" --json) # get all hashes for images that have no tags (or just the commit hash tag) # jq behavior for all(test(pattern)) matches the empty list [] # or are older than 24 hours (we don't want to accidentally mess with any # ongoing builds) readarray -t targets < <(echo "$images_json" | jq -r --arg now "$NOW" ' .manifest | to_entries | sort_by(.value.timeUploadedMs|tonumber) | .[] | select( (.value.tag // [] | all(test(".*-[a-f0-9]{40}$|^[a-f0-9]{40}$"))) and (($now | tonumber) - (.value.timeUploadedMs | tonumber) > 86400000) ) | .key '); background_pid=$! wait "$background_pid" echo "tagging ${#targets[@]} images of $image" exec_tag "$image" "$tag_prefix" targets } function tag_deprecate() { local targets local tag_prefix="deprecated-public-image-" local image=$1 local images_json images_json=$(gcrane ls "$image" --json) # get all hashes for all images don't have the deprecated tag # also skip images that already have an update-available tag # this is only for wholesale deprecation of an image, it also # will deprecate all cosign tag based signatures by nature of select(...) # automatically adding deprecation tags to sha256.*(att|sig). readarray -t targets < <(echo "$images_json" | jq -r ' .manifest | to_entries | sort_by(.value.timeUploadedMs|tonumber) | .[] | select( (.value.tag // [] | all(test("deprecated-public-image-[a-f0-9]{64}$") | not)) and (.value.tag // [] | all(test("update-available-") | not)) ) | .key '); background_pid=$! wait "$background_pid" echo "tagging ${#targets[@]} images of $image" echo "1. Careful about builds happening, this doesn't account for them." printf "2. Be sure images are not in the currently supported list at:\n\thttps://github.com/GoogleContainerTools/distroless/?tab=readme-ov-file#what-images-are-available\n" read -r -p "Continue? [y/N] " response if [[ ! "$response" =~ ^[Yy]$ ]]; then echo "Aborted." exit 1 fi exec_tag "$image" "$tag_prefix" targets } dry_run=${DRY_RUN:-true} if [[ "${dry_run}" != "true" && "${dry_run}" != "false" ]]; then echo "Error: DRY_RUN needs to have value (true|false)." exit 1 fi function tag() { local tag_mode=$1 local image=$2 case "$tag_mode" in update) tag_update "$image" ;; deprecate) tag_deprecate "$image" ;; *) echo "wtf?" exit 1 esac } function usage() { echo "USAGE: $1 [deprecate|update] " >&2 exit 1 } case "${1:-"~~nocmd"}" in update | deprecate) if [[ "$#" -ne 2 ]]; then usage "$0" fi tag "$@" ;; ~~nocmd | *) usage "$0" ;; esac ================================================ FILE: private/tools/lifecycle/tag.sh.README.md ================================================ # Container Image Lifecycle Tagger (Distroless Admin Tooling) A Bash utility to bulk-tag container images in a registry. This is particularly useful for marking old images as "available for update" or "deprecated" without deleting them, allowing for safer cleanup or auditing. ## Prerequisites * **[gcrane](https://github.com/google/go-containerregistry/tree/main/cmd/gcrane):** Used for interacting with the container registry. * **[jq](https://github.com/jqlang/jq/):** Used for parsing registry JSON manifests. * **Authentication:** Ensure you are authenticated to your registry (e.g., `gcloud auth configure-docker`). ## Functionality The script operates in two primary modes: ### 1. `update` mode Identifies images that are "stale" but likely safe to mark for replacement. It selects images that: * Have no tags **OR** only have auto-generated git commit hash based tags (40-character hex strings). * Are older than **48 hours** (to avoid interfering with active CI/CD pipelines). * **Action:** Tags them with the prefix `update-available-`. ### 2. `deprecate` mode Identifies images that have not yet been marked as deprecated. * Selects images that do **not** already have a tag matching the deprecation pattern. * **Action:** Tags them with the prefix `deprecated-public-image-`. * *Note: The execution for this mode is currently commented out in the script as a safety measure.* --- ## Usage ```bash ./tag.sh [update|deprecate] ``` ### Examples **Dry Run (Default):** By default, the script only prints what it *would* do. ```bash ./tag.sh update gcr.io/distroless/python3-debian12 ``` **Live Execution:** To actually apply tags to the registry, set `DRY_RUN` to `false`. ```bash DRY_RUN=false ./tag.sh update gcr.io/distroless/python3-debian12 ``` ================================================ FILE: private/util/BUILD ================================================ ================================================ FILE: private/util/deb.bzl ================================================ "utility functions for constructing debian package labels" load("@versions//:versions.bzl", "version") DIST_ALIAS = dict( # bullseye (deprecated) debian11 = "bullseye", bullseye = "debian11", # bookworm debian12 = "bookworm", bookworm = "debian12", # trixie debian13 = "trixie", trixie = "debian13", ) ARCH_ALIAS = dict( arm = "armhf", ppc64le = "ppc64el", arm64 = "arm64", amd64 = "amd64", s390x = "s390x", riscv64 = "riscv64", ) def _get_dist_arch_alias(arch, dist, repo_suffix): dist = DIST_ALIAS[dist] arch = ARCH_ALIAS[arch] if repo_suffix != None: dist += "_" + repo_suffix return (arch, dist) def _package(arch, dist, package, repo_suffix = None): (arch, dist) = _get_dist_arch_alias(arch, dist, repo_suffix) return "@{dist}//{package}/{arch}".format(arch = arch, dist = dist, package = package) def _data(arch, dist, package, repo_suffix = None): (arch, dist) = _get_dist_arch_alias(arch, dist, repo_suffix) return "@{dist}//{package}/{arch}:data".format(arch = arch, dist = dist, package = package) def _version(arch, dist, package, repo_suffix = None): (arch, dist) = _get_dist_arch_alias(arch, dist, repo_suffix) return version(dist, arch, package).raw deb = struct( package = _package, data = _data, version = _version, ) ================================================ FILE: private/util/extract.bzl ================================================ "a utility that extracts files from tar" load("@aspect_bazel_lib//lib:tar.bzl", "tar_lib") def _tar_extract_file_impl(ctx): bsdtar = ctx.toolchains[tar_lib.toolchain_type] parts = ctx.attr.file.split("/") output = ctx.actions.declare_file("/".join([ctx.label.name, parts[-1]])) args = ctx.actions.args() args.add("--extract") args.add("-C", "/".join([ctx.bin_dir.path, ctx.label.package, ctx.label.name])) args.add("--file", ctx.file.archive) args.add("--include", ctx.attr.file) args.add("--strip-components={}".format(len(parts) - 1)) ctx.actions.run( executable = bsdtar.tarinfo.binary, inputs = [ctx.file.archive], outputs = [output], tools = bsdtar.default.files, arguments = [args], ) return [ DefaultInfo(files = depset([output])), ] tar_extract_file = rule( implementation = _tar_extract_file_impl, attrs = { "archive": attr.label(allow_single_file = True, mandatory = True), "file": attr.string(mandatory = True), }, toolchains = [tar_lib.toolchain_type], ) ================================================ FILE: private/util/java_cacerts.bzl ================================================ "java ca certificates" load("@rules_distroless//distroless:defs.bzl", "java_keystore") load(":extract.bzl", "tar_extract_file") def java_cacerts(name, archive): tar_extract_file( name = name + "_extract", archive = archive, file = "./etc/ssl/certs/ca-certificates.crt", ) java_keystore( name = name, certificates = [ ":" + name + "_extract", ], ) ================================================ FILE: private/util/merge_providers.bzl ================================================ "a utility rule that merges DefaultInfo and OutputGroupInfo providers" SKIP = "_hidden_top_level_INTERNAL_" def _impl(ctx): output_group_info = {} default_info = {"files": depset(), "runfiles": ctx.runfiles()} for src in ctx.attr.srcs: if DefaultInfo in src: default_info = { "files": depset(transitive = [default_info["files"], src[DefaultInfo].files]), "runfiles": default_info["runfiles"].merge(src[DefaultInfo].default_runfiles), } if OutputGroupInfo in src: for key in src[OutputGroupInfo]: if key == SKIP: continue depsets = [src[OutputGroupInfo][key]] if key in output_group_info: depsets.append(output_group_info[key]) output_group_info[key] = depset(transitive = depsets) return [ OutputGroupInfo(**output_group_info), DefaultInfo(**default_info), ] merge_providers = rule( implementation = _impl, attrs = { "srcs": attr.label_list(), }, ) ================================================ FILE: private/util/tar.bzl ================================================ "Wrapper around tar rules for creating tar archives" load("@aspect_bazel_lib//lib:tar.bzl", _aspect_tar = "tar") load("@rules_pkg//:pkg.bzl", "pkg_tar") def tar( name, srcs = [], deps = [], extension = "tar.gz", package_dir = None, strip_prefix = None, symlinks = {}, args = [], mtree = [], **kwargs): """Create a tar archive. Uses aspect_bazel_lib tar when mtree is provided for precise control. Uses pkg_tar otherwise for compatibility with deps merging. Args: name: Name of the target srcs: Source files to include deps: Other tar files to merge extension: Output extension (tar.gz, tar, etc.) package_dir: Directory prefix for files in the archive strip_prefix: Prefix to strip from source file paths symlinks: Dict of symlink path -> target args: Additional arguments to pass to tar (aspect_bazel_lib only) mtree: mtree specification for file metadata (aspect_bazel_lib only) **kwargs: Additional arguments passed to underlying rule """ # Use aspect_bazel_lib tar when mtree is provided if mtree: compress = None if extension == "tar.gz": compress = "gzip" elif extension == "tar.bz2": compress = "bzip2" elif extension == "tar.xz": compress = "xz" elif extension == "tar.zst": compress = "zstd" _aspect_tar( name = name, srcs = srcs + deps, args = args, mtree = mtree, compress = compress, **kwargs ) else: # Use pkg_tar for deps merging and legacy compatibility pkg_tar( name = name, srcs = srcs, deps = deps, extension = extension, package_dir = package_dir, strip_prefix = strip_prefix, symlinks = symlinks, **kwargs ) ================================================ FILE: python3/BUILD ================================================ load("//private/util:tar.bzl", "tar") load(":config.bzl", "PYTHON_ARCHITECTURES", "PYTHON_DISTROS", "PYTHON_PACKAGES") load(":ldconfig.bzl", "python3_ldconfig") load(":python.bzl", "python3_image", "python3_image_index") package(default_visibility = ["//visibility:public"]) [ tar( name = "ldconfig_cache_{}".format(arch), srcs = ["ldconfig/ld.so.cache.{}".format(arch)], args = [ "--format", "gnutar", ], extension = "tar.gz", mtree = ["etc/ld.so.cache uid=0 gid=0 uname=root gname=root mode=0644 time=0 type=file content=$(location ldconfig/ld.so.cache.{})".format(arch)], ) for arch in PYTHON_ARCHITECTURES["debian13"] ] [ python3_image( arch = arch, distro = distro, packages = PYTHON_PACKAGES[distro], ) for distro in PYTHON_DISTROS for arch in PYTHON_ARCHITECTURES[distro] ] [ python3_image_index( architectures = PYTHON_ARCHITECTURES[distro], distro = distro, ) for distro in PYTHON_DISTROS ] # ldconfig.so.cache generation python3_ldconfig( architectures = PYTHON_ARCHITECTURES["debian13"], distro = "debian13", ) ================================================ FILE: python3/README.md ================================================ # Documentation for `gcr.io/distroless/python3` ## Image Contents This image contains a minimal Linux, Python-based runtime. Specifically, the image contains everything in the [base image](../base/README.md), plus: * Python 3 and its dependencies. * 3.11 on debian 12 * 3.13 on debian 13 * No shell ## ldconfig and ctypes On debian13+ we include a pre-generated `ld.so.cache` to support user/framework calls to `ctypes.util.find_library()`. If a user modifies the image by adding a new library, it will not be found in the cache without calling ldconfig to refresh the cache. ## Usage The entrypoint of this image is set to "python", so this image expects users to supply a path to a .py file in the CMD. See the Python [Hello World](../examples/python3/) directory for an example. ================================================ FILE: python3/config.bzl ================================================ PYTHON_DISTROS = ["debian12", "debian13"] PYTHON_ARCHITECTURES = { "debian12": ["amd64", "arm64"], "debian13": ["amd64", "arm64"], } PYTHON_PACKAGES = { "debian12": [ "libbz2-1.0", "libdb5.3", "libexpat1", "liblzma5", "libsqlite3-0", "libuuid1", "libncursesw6", "libtinfo6", "python3-distutils", "zlib1g", "libcom-err2", "libcrypt1", "libgssapi-krb5-2", "libk5crypto3", "libkeyutils1", "libkrb5-3", "libkrb5support0", "libnsl2", "libreadline8", "libtirpc3", "libffi8", "libpython3.11-minimal", "libpython3.11-stdlib", "python3.11-minimal", ], "debian13": [ "libbz2-1.0", "libdb5.3t64", "libexpat1", "liblzma5", "libsqlite3-0", "libuuid1", "libncursesw6", "libtinfo6", "zlib1g", "libcom-err2", "libcrypt1", "libc-bin", "libgssapi-krb5-2", "libk5crypto3", "libkeyutils1", "libkrb5-3", "libkrb5support0", "libnsl2", "libreadline8t64", "libtirpc3t64", "libffi8", "libpython3.13-minimal", "libpython3.13-stdlib", "python3.13-minimal", "python3.13-venv", ], } ================================================ FILE: python3/ldconfig/ldconfig.sh ================================================ #!/usr/bin/env bash set -eo pipefail MODE=$1 shift if [[ "${MODE}" != "update" && "${MODE}" != "check" ]]; then echo "Usage: $0 ..." >&2 exit 1 fi # Root to find the reference cache files ROOT="python3/ldconfig" if [[ -n "${BUILD_WORKSPACE_DIRECTORY}" ]]; then cd "${BUILD_WORKSPACE_DIRECTORY}" elif [[ ! -d "${ROOT}" ]]; then # Fallback to finding it in the same dir as the script ROOT=$(dirname "$0") fi CID="" TEMP_DIR="" cleanup() { local exit_status=$? if [[ -n "${CID}" ]]; then docker rm -f "${CID}"; fi if [[ -n "${TEMP_DIR}" ]]; then rm -rf "${TEMP_DIR}"; fi exit "${exit_status}" } trap cleanup EXIT for arch in "$@"; do echo "===> ${MODE^}ing ldconfig cache for ${arch}..." # Run ldconfig and extract the cache. # We assume the image is ALREADY loaded (handled by Bazel build dependencies) CID=$(docker create --platform "linux/${arch}" --entrypoint /sbin/ldconfig "bazel/python3:python3_root_${arch}_debian13") docker start -a "${CID}" if [[ "${MODE}" == "update" ]]; then docker cp "${CID}:/etc/ld.so.cache" "${ROOT}/ld.so.cache.${arch}" echo "✅ Updated ${arch} cache." else TEMP_DIR=$(mktemp -d) docker cp "${CID}:/etc/ld.so.cache" "${TEMP_DIR}/ld.so.cache.${arch}" if ! cmp -s "${TEMP_DIR}/ld.so.cache.${arch}" "${ROOT}/ld.so.cache.${arch}"; then echo "❌ ERROR: ldconfig cache for ${arch} is out of date!" >&2 echo "Run 'bazel run //python3:update_ldconfig' to regenerate." >&2 exit 1 fi rm -rf "${TEMP_DIR}" TEMP_DIR="" echo "✅ ldconfig cache for ${arch} is up to date." fi docker rm -f "${CID}" CID="" done ================================================ FILE: python3/ldconfig.bzl ================================================ "Macros for generating ldconfig cache for python images" load("@rules_oci//oci:defs.bzl", "oci_load") def python3_ldconfig(architectures, distro): """Generates ldconfig cache targets for python images. Args: architectures: list of architectures to support distro: the distribution name (e.g. debian13) """ # 1. Create the oci_load targets (the scripts that load images into docker) for arch in architectures: oci_load( name = "load_python3_root_{}_{}".format(arch, distro), image = ":python3_root_{}_{}".format(arch, distro), repo_tags = ["bazel/python3:python3_root_{}_{}".format(arch, distro)], ) # 2. Create the genrules that actually trigger the loading during 'bazel build' for arch in architectures: native.genrule( name = "do_load_{}".format(arch), outs = ["do_load_{}.done".format(arch)], cmd = "$(location :load_python3_root_{arch}_{distro}) && touch $@".format( arch = arch, distro = distro, ), tags = [ "local", "no-sandbox", ], tools = [":load_python3_root_{}_{}".format(arch, distro)], ) # 3. Create the update_ldconfig binary native.sh_binary( name = "update_ldconfig", srcs = ["ldconfig/ldconfig.sh"], args = ["update"] + architectures, data = ["ldconfig/ldconfig.sh"] + [":do_load_{}".format(arch) for arch in architectures], tags = ["local"], ) # 4. Create the architecture-specific tests for arch in architectures: native.sh_test( name = "check_ldconfig_{}_test".format(arch), srcs = ["ldconfig/ldconfig.sh"], args = [ "check", arch, ], data = [ "ldconfig/ld.so.cache.{}".format(arch), ":do_load_{}".format(arch), ], tags = [ arch, "local", "manual", "external", "no-cache", ], ) # 5. Create the test suite native.test_suite( name = "check_ldconfig_tests", tests = [ ":check_ldconfig_{}_test".format(arch) for arch in architectures ], tags = ["manual"], ) ================================================ FILE: python3/python.bzl ================================================ "python3 image definitions" load("@container_structure_test//:defs.bzl", "container_structure_test") load("@rules_oci//oci:defs.bzl", "oci_image", "oci_image_index") load("//common:variables.bzl", "DEBUG_MODE", "USERS") load("//private/util:deb.bzl", "deb") load("//private/util:tar.bzl", "tar") DISTRO_VERSION = { "debian12": "3.11", "debian13": "3.13", } def python_alias(distro): if native.existing_rule("python_aliases_" + distro): return tar( name = "python_aliases_" + distro, extension = "tar.gz", symlinks = { "/usr/bin/python": "/usr/bin/python" + DISTRO_VERSION[distro], "/usr/bin/python3": "/usr/bin/python" + DISTRO_VERSION[distro], }, ) def python3_image_index(distro, architectures): """python image index for a distro Args: distro: name of distribution architectures: all architectures included in index """ for mode in DEBUG_MODE: for user in USERS: oci_image_index( name = "python3" + mode + "_" + user + "_" + distro, images = [ "python3" + mode + "_" + user + "_" + arch + "_" + distro for arch in architectures ], ) def python3_image(distro, arch, packages): """python3 and debug image with tests. Args: distro: name of distribution arch: the target architecture packages: list of debian packages to include """ python_alias(distro) for mode in DEBUG_MODE: for user in USERS: oci_image( name = "python3" + mode + "_" + user + "_" + arch + "_" + distro, # Based on //cc so that C extensions work properly. base = "//cc:cc" + mode + "_" + user + "_" + arch + "_" + distro, entrypoint = [ "/usr/bin/python" + DISTRO_VERSION[distro], ], # Use UTF-8 encoding for file system: match modern Linux env = {"LANG": "C.UTF-8"}, tars = [ deb.package(arch, distro, pkg, "python") for pkg in packages ] + [":python_aliases_%s" % distro] + ([":ldconfig_cache_" + arch] if distro == "debian13" else []), ) for user in USERS: container_structure_test( name = "python3_" + user + "_" + arch + "_" + distro + "_test", size = "medium", configs = ["testdata/python3.yaml"], image = ":python3_" + user + "_" + arch + "_" + distro, tags = [ "manual", arch, ], ) # tests for version-specific things for user in USERS: container_structure_test( name = "version_specific_" + user + "_" + arch + "_" + distro + "_test", size = "medium", configs = ["testdata/" + distro + ".yaml"], image = ":python3_" + user + "_" + arch + "_" + distro, tags = [ "manual", arch, ], ) ================================================ FILE: python3/testdata/debian12.yaml ================================================ schemaVersion: "1.0.0" commandTests: - name: version command: ["/usr/bin/python3", "--version"] expectedOutput: ["Python 3.11.2"] - name: symlink command: ["/usr/bin/python", "--version"] expectedOutput: ["Python 3.11.2"] # debian 12's default python3 includes a partial version of distutils causing virtualenv to fail # ensure we have the full version so virtualenvs work with distroless - name: distutils_works command: ["/usr/bin/python3", "-c", "import distutils.dist"] exitCode: 0 # import every module installed with the Python package - name: import_everything exitCode: 0 expectedOutput: ['FINISHED ENTIRE SCRIPT'] command: - "/usr/bin/python3" - "-c" # multi-line YAML string with Python script that imports all modules that are installed. # This ensures we have the right native library dependencies. - | import pkgutil skip_modules = frozenset(( # Windows-specific modules 'asyncio.windows_events', 'asyncio.windows_utils', 'ctypes.wintypes', 'distutils._msvccompiler', 'distutils.command.bdist_msi', 'distutils.msvc9compiler', 'encodings.cp65001', 'encodings.mbcs', 'encodings.oem', 'multiprocessing.popen_spawn_win32', 'winreg', # Python regression tests "for internal use by Python only" 'test', # calls sys.exit 'unittest.__main__', 'venv.__main__', # depends on things not installed by default on Debian 'dbm.gnu', 'lib2to3.pgen2.conv', 'turtle', )) # pass an error handler so the test fails if there are broken standard library packages def walk_packages_onerror(failed_module_name): raise Exception('failed to import module: {}'.format(repr(failed_module_name))) for module_info in pkgutil.walk_packages(onerror=walk_packages_onerror): module_name = module_info.name if module_name in skip_modules or module_name.startswith('test.'): continue __import__(module_name) print('imported {}'.format(module_name)) # ensures some module does not exit early (e.g unittest.__main__) print('FINISHED ENTIRE SCRIPT') ================================================ FILE: python3/testdata/debian13.yaml ================================================ schemaVersion: "1.0.0" commandTests: - name: version command: ["/usr/bin/python3", "--version"] expectedOutput: ["Python 3.13.5"] - name: symlink command: ["/usr/bin/python", "--version"] expectedOutput: ["Python 3.13.5"] # import every module installed with the Python package - name: import_everything exitCode: 0 expectedOutput: ['FINISHED ENTIRE SCRIPT'] command: - "/usr/bin/python3" - "-c" # multi-line YAML string with Python script that imports all modules that are installed. # This ensures we have the right native library dependencies. - | import pkgutil skip_modules = frozenset(( # Windows-specific modules 'asyncio.windows_events', 'asyncio.windows_utils', 'ctypes.wintypes', 'distutils._msvccompiler', 'distutils.command.bdist_msi', 'distutils.msvc9compiler', 'encodings.cp65001', 'encodings.mbcs', 'encodings.oem', 'multiprocessing.popen_spawn_win32', '_pyrepl.windows_console', 'winreg', # Python regression tests "for internal use by Python only" 'test', # no ios support '_ios_support', # pyrepl things '_pyrepl._minimal_curses', # i thought distutils was gone? '_distutils_system_mod', # calls sys.exit 'unittest.__main__', 'venv.__main__', # depends on things not installed by default on Debian 'dbm.gnu', 'lib2to3.pgen2.conv', 'turtle', )) # pass an error handler so the test fails if there are broken standard library packages def walk_packages_onerror(failed_module_name): raise Exception('failed to import module: {}'.format(repr(failed_module_name))) for module_info in pkgutil.walk_packages(onerror=walk_packages_onerror): module_name = module_info.name if module_name in skip_modules or module_name.startswith('test.'): continue print('importing {}'.format(module_name)) __import__(module_name) print('imported {}'.format(module_name)) print('FINISHED ENTIRE SCRIPT') ================================================ FILE: python3/testdata/python3.yaml ================================================ schemaVersion: "1.0.0" commandTests: - name: hello command: ["/usr/bin/python3", "-c", "print('Hello World')"] expectedOutput: ['Hello World'] # ensure there is no shell - name: no_shell command: ["/usr/bin/python3", "-c", "import subprocess, sys; subprocess.check_call(sys.executable + ' -h', shell=True)"] exitCode: 1 # file names are UTF-8: default for modern Linux systems # The \xe9 backslash must be double-escaped to avoid YAML string parsing weirdness - name: filesystem_utf8 command: ["/usr/bin/python3", "-c", "open(u'h\\xe9llo', 'w'); import sys; print(sys.getfilesystemencoding())"] expectedOutput: ['utf-8'] # the print function should output UTF-8 - name: print_utf8 command: ["/usr/bin/python3", "-c", "print(u'h\\xe9llo.txt')"] expectedOutput: ['h\xe9llo'] ================================================ FILE: static/BUILD ================================================ load("//private/util:tar.bzl", "tar") load(":config.bzl", "STATIC_ARCHITECTURES", "STATIC_DISTROS", "STATIC_PACKAGES") load(":static.bzl", "static_image", "static_image_index") package(default_visibility = ["//visibility:public"]) # Build gzip-compressed tar with GNU format and correct metadata tar( name = "nsswitch", srcs = ["nsswitch.conf"], args = [ "--format", "gnutar", ], extension = "tar.gz", mtree = ["etc/nsswitch.conf uid=0 gid=0 uname=root gname=root mode=0644 time=1514722362 type=file content=$(location nsswitch.conf)"], ) [ static_image( arch = arch, distro = distro, packages = STATIC_PACKAGES[distro], ) for distro in STATIC_DISTROS for arch in STATIC_ARCHITECTURES[distro] ] [ static_image_index( architectures = STATIC_ARCHITECTURES[distro], distro = distro, ) for distro in STATIC_DISTROS ] ================================================ FILE: static/config.bzl ================================================ STATIC_DISTROS = ["debian12", "debian13"] STATIC_ARCHITECTURES = { "debian12": ["amd64", "arm64", "arm", "s390x", "ppc64le"], "debian13": ["amd64", "arm64", "arm", "s390x", "ppc64le", "riscv64"], } STATIC_PACKAGES = { "debian12": [ "base-files", "netbase", "tzdata", "media-types", ], "debian13": [ "base-files", "netbase", "tzdata", "tzdata-legacy", "media-types", ], } ================================================ FILE: static/nsswitch.conf ================================================ # /etc/nsswitch.conf # # Example configuration of GNU Name Service Switch functionality. # If you have the `glibc-doc-reference' and `info' packages installed, try: # `info libc "Name Service Switch"' for information about this file. passwd: compat group: compat shadow: compat gshadow: files hosts: files dns networks: files protocols: db files services: db files ethers: db files rpc: db files netgroup: nis ================================================ FILE: static/static.bzl ================================================ "defines a function to build static different distributions" load("@container_structure_test//:defs.bzl", "container_structure_test") load("@rules_go//go:def.bzl", "go_binary") load("@rules_oci//oci:defs.bzl", "oci_image", "oci_image_index") load("//:distro.bzl", "VARIANTS") load("//common:variables.bzl", "DEBUG_MODE", "NONROOT") load("//private/util:deb.bzl", "deb") load("//private/util:tar.bzl", "tar") USER_VARIANTS = [("root", 0, "/"), ("nonroot", NONROOT, "/home/nonroot")] def static_image_index(distro, architectures): """Build image index for a distro Args: distro: name of distribution architectures: all architectures included in index """ for (user, _, _) in USER_VARIANTS: for mode in DEBUG_MODE: oci_image_index( name = "static" + mode + "_" + user + "_" + distro, images = [ "static" + mode + "_" + user + "_" + arch + "_" + distro for arch in architectures ], ) def static_image(distro, arch, packages): """static and debug images and tests for a distro/arch Args: distro: name of the distribution arch: the target architecture packages: distro-specific packages to include """ for (user, uid, workdir) in USER_VARIANTS: oci_image( name = "static_" + user + "_" + arch + "_" + distro, env = { "PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", # allows openssl to find the certificates by default # TODO: We should run update-ca-certifaces, but that requires "openssl rehash" # which would probably need to be run inside the container "SSL_CERT_FILE": "/etc/ssl/certs/ca-certificates.crt", }, tars = [ deb.package(arch, distro, pkg) for pkg in packages ] + [ "//common:rootfs", "//common:passwd", "//common:home", "//common:group", # Create /tmp, too many things assume it exists. # tmp.tar has a /tmp with the correct permissions 01777 "//common:tmp", ":nsswitch", "//common:os_release_" + distro, "//common:cacerts_" + distro + "_" + arch, ], user = "%d" % uid, workdir = workdir, os = "linux", architecture = arch, variant = VARIANTS.get(arch), ) # A static debug image with busybox available. oci_image( name = "static_debug_" + user + "_" + arch + "_" + distro, base = ":static_" + user + "_" + arch + "_" + distro, entrypoint = ["/busybox/sh"], env = {"PATH": "$PATH:/busybox"}, tars = ["//experimental/busybox:busybox_" + arch], ) ########################################################################################## # Check that we can overlay a pure Go binary on a static base to check certificates ########################################################################################## go_binary( name = "check_certs_" + arch + "_" + distro, srcs = ["testdata/check_certs.go"], goarch = arch, # Test image is linux based goos = "linux", pure = "on", ) tar( name = "check_certs_" + arch + "_" + distro + "_tar", extension = "tar.gz", srcs = ["check_certs_" + arch + "_" + distro], symlinks = { "/check_certs": "check_certs_" + arch + "_" + distro, }, ) oci_image( name = "check_certs_image_" + arch + "_" + distro, base = "//static:static_root_" + arch + "_" + distro, tars = [ ":check_certs_" + arch + "_" + distro + "_tar", ], visibility = ["//visibility:private"], ) container_structure_test( name = "static_" + arch + "_" + distro + "_test", configs = ["testdata/static.yaml"], image = ":check_certs_image_" + arch + "_" + distro, tags = ["manual", arch], ) ########################################################################################## # Check for busybox ########################################################################################## container_structure_test( name = "static_debug_" + arch + "_" + distro + "_test", configs = ["testdata/debug.yaml"], image = ":static_debug_root_" + arch + "_" + distro, tags = ["manual", arch], ) ########################################################################################## # Check the /etc/os-release contents. ########################################################################################## container_structure_test( name = "static_release_" + arch + "_" + distro + "_test", configs = ["testdata/" + distro + ".yaml"], image = ":static_root_" + arch + "_" + distro, tags = ["manual", arch], ) container_structure_test( name = "static_debug_release_" + arch + "_" + distro + "_test", configs = ["testdata/" + distro + ".yaml"], image = ":static_debug_root_" + arch + "_" + distro, tags = ["manual", arch], ) ================================================ FILE: static/testdata/check_certs.go ================================================ // Copyright 2017 Google Inc. All rights reserved. // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package main import ( "crypto/x509" "fmt" "os" ) func main() { pool, err := x509.SystemCertPool() if err != nil { fmt.Printf("Error %s loading system certs.\n", err) os.Exit(1) } if pool == nil { fmt.Println("No cert pools.") os.Exit(1) } fmt.Println("Certs working!") } ================================================ FILE: static/testdata/debian12.yaml ================================================ schemaVersion: "1.0.0" fileContentTests: - name: 'os-release contents' path: '/etc/os-release' expectedContents: ['.*\nVERSION="Debian GNU/Linux 12 \(bookworm\)"\n'] ================================================ FILE: static/testdata/debian13.yaml ================================================ schemaVersion: "1.0.0" fileContentTests: - name: 'os-release contents' path: '/etc/os-release' expectedContents: ['.*\nVERSION="Debian GNU/Linux 13 \(trixie\)"\n'] ================================================ FILE: static/testdata/debug.yaml ================================================ schemaVersion: "1.0.0" fileExistenceTests: # Basic FS sanity checks. - name: busybox path: '/busybox' shouldExist: true commandTests: - name: busybox command: ["/busybox/busybox"] expectedOutput: ['BusyBox v1\.37\.0'] ================================================ FILE: static/testdata/static.yaml ================================================ schemaVersion: "1.0.0" commandTests: # Check that Go programs can read the certificates - name: certs command: ["/check_certs"] exitCode: 0 fileExistenceTests: - name: mime-types path: '/etc/mime.types' shouldExist: true