From ced767320133af099cc2df43e24b4f7900270eee Mon Sep 17 00:00:00 2001 From: Titus Fortner Date: Fri, 24 Jul 2026 16:36:19 -0500 Subject: [PATCH 1/6] [build] generate cross-platform Selenium Manager SBOM and NOTICE in the Rust release job --- .github/workflows/ci-rust.yml | 33 +++++++++++++++++++- rust/about.hbs | 25 +++++++++++++++ rust/about.toml | 59 +++++++++++++++++++++++++++++++++++ 3 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 rust/about.hbs create mode 100644 rust/about.toml diff --git a/.github/workflows/ci-rust.yml b/.github/workflows/ci-rust.yml index 53067abe9bfb4..6e43d9531576d 100644 --- a/.github/workflows/ci-rust.yml +++ b/.github/workflows/ci-rust.yml @@ -233,16 +233,45 @@ jobs: with: token: ${{ secrets.SELENIUM_CI_TOKEN }} repository: SeleniumHQ/selenium_manager_artifacts + - name: "Checkout selenium source" + uses: actions/checkout@v6 + with: + ref: ${{ inputs.branch }} + path: selenium - name: "Download Artifacts" uses: actions/download-artifact@v8 with: path: artifacts + # SBOM/NOTICE are generated here, once, from cargo's cross-platform crate + # resolution so a single release carries license artifacts covering every + # shipped platform (including Windows-only winapi/windows-*). Bazel later + # downloads these exactly like it downloads the binaries. + - name: "Update Rust" + run: | + rustup update + rustc -vV + - name: "Install SBOM tools" + run: cargo install --locked cargo-cyclonedx@0.5.7 cargo-about@0.6.6 + - name: "Generate SBOM and third-party notices" + working-directory: selenium/rust + run: | + # --target all resolves target-gated crates for every platform, not + # just the ubuntu host; default output name is .cdx.json. + cargo cyclonedx --format json --all-features --target all + # about.toml pins the shipped triples so the NOTICE matches the SBOM. + cargo about generate about.hbs > selenium-manager-THIRD-PARTY-NOTICES.txt + # Guard cross-platform completeness: a host-filtered SBOM would omit + # Windows-only winapi and silently ship an incomplete artifact. + grep -q '"name" *: *"winapi"' selenium-manager.cdx.json \ + || { echo "::error::SBOM is missing winapi; --target all did not include Windows crates"; exit 1; } - name: "Prepare and Commit" run: | linux_sha=$(shasum -a 256 artifacts/selenium-manager-linux/selenium-manager-linux | awk '{print $1}') macos_sha=$(shasum -a 256 artifacts/selenium-manager-macos/selenium-manager-macos | awk '{print $1}') windows_sha=$(shasum -a 256 artifacts/selenium-manager-windows/selenium-manager-windows.exe | awk '{print $1}') - echo "{\"macos\": \"$macos_sha\", \"windows\": \"$windows_sha\", \"linux\": \"$linux_sha\"}" > latest.json + sbom_sha=$(shasum -a 256 selenium/rust/selenium-manager.cdx.json | awk '{print $1}') + notice_sha=$(shasum -a 256 selenium/rust/selenium-manager-THIRD-PARTY-NOTICES.txt | awk '{print $1}') + echo "{\"macos\": \"$macos_sha\", \"windows\": \"$windows_sha\", \"linux\": \"$linux_sha\", \"sbom\": \"$sbom_sha\", \"notice\": \"$notice_sha\"}" > latest.json git config --local user.email "selenium-ci@users.noreply.github.com" git config --local user.name "Selenium CI Bot" git add latest.json @@ -266,3 +295,5 @@ jobs: artifacts/selenium-manager-linux-debug/selenium-manager-linux-debug.tar artifacts/selenium-manager-macos-debug/selenium-manager-macos-debug.tar artifacts/selenium-manager-windows-debug/selenium-manager-windows-debug.exe + selenium/rust/selenium-manager.cdx.json + selenium/rust/selenium-manager-THIRD-PARTY-NOTICES.txt diff --git a/rust/about.hbs b/rust/about.hbs new file mode 100644 index 0000000000000..2f623df291908 --- /dev/null +++ b/rust/about.hbs @@ -0,0 +1,25 @@ +Selenium Manager bundles third-party Rust crates. Their copyright notices and +license terms are reproduced below. Licenses shared by multiple crates are +listed once, followed by every crate that uses them. + +This file is generated; do not edit by hand. Regenerate with: + cargo about generate about.hbs > selenium-manager-THIRD-PARTY-NOTICES.txt + +Overview of licenses: +{{#each overview}} + - {{name}}: {{count}} crate(s) +{{/each}} + +{{#each licenses}} +================================================================================ +{{name}} +================================================================================ + +Used by: +{{#each used_by}} + - {{crate.name}} {{crate.version}} +{{/each}} + +{{text}} + +{{/each}} diff --git a/rust/about.toml b/rust/about.toml new file mode 100644 index 0000000000000..5c2286db4c88a --- /dev/null +++ b/rust/about.toml @@ -0,0 +1,59 @@ +# cargo-about configuration for the Selenium Manager third-party NOTICE. +# +# Used by the ci-rust.yml `release` job: +# cargo about generate about.hbs > selenium-manager-THIRD-PARTY-NOTICES.txt +# +# `targets` is the whole point of generating here rather than in Bazel: a single +# cargo invocation resolves the crate closure for every platform we ship, so the +# NOTICE covers target-gated crates (Windows-only winapi/windows-*) that a +# single-platform build would never see. + +# Evaluate the license closure for every shipped triple. These do not need the +# corresponding rustup targets installed -- cargo-about filters `cargo metadata` +# by platform cfg, it does not compile. +targets = [ + "x86_64-unknown-linux-musl", + "x86_64-apple-darwin", + "aarch64-apple-darwin", + "i686-pc-windows-msvc", + "x86_64-pc-windows-msvc", + "aarch64-pc-windows-msvc", +] + +# Dev-dependencies (assert_cmd, rstest, is_executable, ...) are not linked into +# the shipped binary, so they must not appear in the attribution. +ignore-dev-dependencies = true + +# Do not emit an attribution entry for the workspace crate itself. +[private] +ignore = true + +# Every SPDX license present in the resolved tree must be listed here; an +# un-accepted license fails generation. Keep this list in sync with the tree -- +# a new transitive dependency introducing a new license will (correctly) break +# the release until the license is reviewed and added. +accepted = [ + "MIT", + "Apache-2.0", + "Apache-2.0 WITH LLVM-exception", + "BSD-2-Clause", + "BSD-3-Clause", + "ISC", + "Unicode-3.0", + "Unicode-DFS-2016", + "0BSD", + "Zlib", + "MPL-2.0", + "Unlicense", + "CC0-1.0", + "BSL-1.0", + "OpenSSL", +] + +# ring ships a `license-file` (a concatenation of ISC/MIT/OpenSSL terms) rather +# than an SPDX `license` expression. cargo-about's built-in workaround supplies +# the correct expression and bundled text so it is attributed instead of failing +# as NOASSERTION. +workarounds = [ + "ring", +] From 919d2ad64981f11e1ec81562746a5cb83f918407 Mon Sep 17 00:00:00 2001 From: Titus Fortner Date: Fri, 24 Jul 2026 16:58:57 -0500 Subject: [PATCH 2/6] [build] generate SBOM/NOTICE in a dedicated job, not the release job --- .github/workflows/ci-rust.yml | 64 +++++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 26 deletions(-) diff --git a/.github/workflows/ci-rust.yml b/.github/workflows/ci-rust.yml index 6e43d9531576d..b85ed8463685f 100644 --- a/.github/workflows/ci-rust.yml +++ b/.github/workflows/ci-rust.yml @@ -222,30 +222,16 @@ jobs: path: selenium-manager-macos-debug.tar retention-days: 6 - release: - name: "Release Binaries" + sbom: + name: "SBOM and Notices" runs-on: ubuntu-latest - needs: [ macos-stable, linux-stable, windows-stable, macos-debug, linux-debug, windows-debug ] + needs: tests if: github.event_name != 'schedule' && github.event.repository.fork == false && (github.ref == 'refs/heads/trunk' || inputs.release) steps: - - name: "Checkout selenium_manager_artifacts" - uses: actions/checkout@v6 - with: - token: ${{ secrets.SELENIUM_CI_TOKEN }} - repository: SeleniumHQ/selenium_manager_artifacts - - name: "Checkout selenium source" + - name: "Checkout project" uses: actions/checkout@v6 with: ref: ${{ inputs.branch }} - path: selenium - - name: "Download Artifacts" - uses: actions/download-artifact@v8 - with: - path: artifacts - # SBOM/NOTICE are generated here, once, from cargo's cross-platform crate - # resolution so a single release carries license artifacts covering every - # shipped platform (including Windows-only winapi/windows-*). Bazel later - # downloads these exactly like it downloads the binaries. - name: "Update Rust" run: | rustup update @@ -253,24 +239,50 @@ jobs: - name: "Install SBOM tools" run: cargo install --locked cargo-cyclonedx@0.5.7 cargo-about@0.6.6 - name: "Generate SBOM and third-party notices" - working-directory: selenium/rust + working-directory: rust run: | - # --target all resolves target-gated crates for every platform, not - # just the ubuntu host; default output name is .cdx.json. + # cargo resolves the crate closure for every platform in one pass, so a + # single SBOM/NOTICE covers all targets. --target all keeps target-gated + # crates (Windows-only winapi/windows-*); default output name is + # .cdx.json. about.toml pins the shipped triples so the NOTICE + # matches the SBOM. cargo cyclonedx --format json --all-features --target all - # about.toml pins the shipped triples so the NOTICE matches the SBOM. cargo about generate about.hbs > selenium-manager-THIRD-PARTY-NOTICES.txt # Guard cross-platform completeness: a host-filtered SBOM would omit # Windows-only winapi and silently ship an incomplete artifact. grep -q '"name" *: *"winapi"' selenium-manager.cdx.json \ || { echo "::error::SBOM is missing winapi; --target all did not include Windows crates"; exit 1; } + - name: "Upload SBOM and notices" + uses: actions/upload-artifact@v7 + with: + name: selenium-manager-sbom + path: | + rust/selenium-manager.cdx.json + rust/selenium-manager-THIRD-PARTY-NOTICES.txt + retention-days: 6 + + release: + name: "Release Binaries" + runs-on: ubuntu-latest + needs: [ macos-stable, linux-stable, windows-stable, macos-debug, linux-debug, windows-debug, sbom ] + if: github.event_name != 'schedule' && github.event.repository.fork == false && (github.ref == 'refs/heads/trunk' || inputs.release) + steps: + - name: "Checkout selenium_manager_artifacts" + uses: actions/checkout@v6 + with: + token: ${{ secrets.SELENIUM_CI_TOKEN }} + repository: SeleniumHQ/selenium_manager_artifacts + - name: "Download Artifacts" + uses: actions/download-artifact@v8 + with: + path: artifacts - name: "Prepare and Commit" run: | linux_sha=$(shasum -a 256 artifacts/selenium-manager-linux/selenium-manager-linux | awk '{print $1}') macos_sha=$(shasum -a 256 artifacts/selenium-manager-macos/selenium-manager-macos | awk '{print $1}') windows_sha=$(shasum -a 256 artifacts/selenium-manager-windows/selenium-manager-windows.exe | awk '{print $1}') - sbom_sha=$(shasum -a 256 selenium/rust/selenium-manager.cdx.json | awk '{print $1}') - notice_sha=$(shasum -a 256 selenium/rust/selenium-manager-THIRD-PARTY-NOTICES.txt | awk '{print $1}') + sbom_sha=$(shasum -a 256 artifacts/selenium-manager-sbom/selenium-manager.cdx.json | awk '{print $1}') + notice_sha=$(shasum -a 256 artifacts/selenium-manager-sbom/selenium-manager-THIRD-PARTY-NOTICES.txt | awk '{print $1}') echo "{\"macos\": \"$macos_sha\", \"windows\": \"$windows_sha\", \"linux\": \"$linux_sha\", \"sbom\": \"$sbom_sha\", \"notice\": \"$notice_sha\"}" > latest.json git config --local user.email "selenium-ci@users.noreply.github.com" git config --local user.name "Selenium CI Bot" @@ -295,5 +307,5 @@ jobs: artifacts/selenium-manager-linux-debug/selenium-manager-linux-debug.tar artifacts/selenium-manager-macos-debug/selenium-manager-macos-debug.tar artifacts/selenium-manager-windows-debug/selenium-manager-windows-debug.exe - selenium/rust/selenium-manager.cdx.json - selenium/rust/selenium-manager-THIRD-PARTY-NOTICES.txt + artifacts/selenium-manager-sbom/selenium-manager.cdx.json + artifacts/selenium-manager-sbom/selenium-manager-THIRD-PARTY-NOTICES.txt From 68ba810990a86c039f482688ca81c7015ceb4f2a Mon Sep 17 00:00:00 2001 From: Titus Fortner Date: Fri, 24 Jul 2026 17:09:05 -0500 Subject: [PATCH 3/6] [build] trim comments to essentials in SBOM config --- .github/workflows/ci-rust.yml | 8 +------- rust/about.toml | 27 ++++----------------------- 2 files changed, 5 insertions(+), 30 deletions(-) diff --git a/.github/workflows/ci-rust.yml b/.github/workflows/ci-rust.yml index b85ed8463685f..b696162ebc70a 100644 --- a/.github/workflows/ci-rust.yml +++ b/.github/workflows/ci-rust.yml @@ -241,15 +241,9 @@ jobs: - name: "Generate SBOM and third-party notices" working-directory: rust run: | - # cargo resolves the crate closure for every platform in one pass, so a - # single SBOM/NOTICE covers all targets. --target all keeps target-gated - # crates (Windows-only winapi/windows-*); default output name is - # .cdx.json. about.toml pins the shipped triples so the NOTICE - # matches the SBOM. + # --target all includes target-gated crates for every platform, not just the host. cargo cyclonedx --format json --all-features --target all cargo about generate about.hbs > selenium-manager-THIRD-PARTY-NOTICES.txt - # Guard cross-platform completeness: a host-filtered SBOM would omit - # Windows-only winapi and silently ship an incomplete artifact. grep -q '"name" *: *"winapi"' selenium-manager.cdx.json \ || { echo "::error::SBOM is missing winapi; --target all did not include Windows crates"; exit 1; } - name: "Upload SBOM and notices" diff --git a/rust/about.toml b/rust/about.toml index 5c2286db4c88a..2a42bca0881f0 100644 --- a/rust/about.toml +++ b/rust/about.toml @@ -1,16 +1,6 @@ -# cargo-about configuration for the Selenium Manager third-party NOTICE. -# -# Used by the ci-rust.yml `release` job: -# cargo about generate about.hbs > selenium-manager-THIRD-PARTY-NOTICES.txt -# -# `targets` is the whole point of generating here rather than in Bazel: a single -# cargo invocation resolves the crate closure for every platform we ship, so the -# NOTICE covers target-gated crates (Windows-only winapi/windows-*) that a -# single-platform build would never see. +# cargo-about config for the third-party NOTICE (see the sbom job in ci-rust.yml). -# Evaluate the license closure for every shipped triple. These do not need the -# corresponding rustup targets installed -- cargo-about filters `cargo metadata` -# by platform cfg, it does not compile. +# All shipped triples, so the NOTICE covers target-gated crates (winapi/windows-*). targets = [ "x86_64-unknown-linux-musl", "x86_64-apple-darwin", @@ -20,18 +10,12 @@ targets = [ "aarch64-pc-windows-msvc", ] -# Dev-dependencies (assert_cmd, rstest, is_executable, ...) are not linked into -# the shipped binary, so they must not appear in the attribution. ignore-dev-dependencies = true -# Do not emit an attribution entry for the workspace crate itself. [private] ignore = true -# Every SPDX license present in the resolved tree must be listed here; an -# un-accepted license fails generation. Keep this list in sync with the tree -- -# a new transitive dependency introducing a new license will (correctly) break -# the release until the license is reviewed and added. +# An unlisted license fails generation; add new ones only after review. accepted = [ "MIT", "Apache-2.0", @@ -50,10 +34,7 @@ accepted = [ "OpenSSL", ] -# ring ships a `license-file` (a concatenation of ISC/MIT/OpenSSL terms) rather -# than an SPDX `license` expression. cargo-about's built-in workaround supplies -# the correct expression and bundled text so it is attributed instead of failing -# as NOASSERTION. +# ring has a license-file, not an SPDX expression; the built-in workaround attributes it. workarounds = [ "ring", ] From bc16ea4aec254fab8787aa04de20871351dfc48d Mon Sep 17 00:00:00 2001 From: Titus Fortner Date: Fri, 24 Jul 2026 17:27:39 -0500 Subject: [PATCH 4/6] [build] reduce cargo-about config to the minimum --- rust/about.toml | 27 +++++---------------------- 1 file changed, 5 insertions(+), 22 deletions(-) diff --git a/rust/about.toml b/rust/about.toml index 2a42bca0881f0..c469c5df84010 100644 --- a/rust/about.toml +++ b/rust/about.toml @@ -1,21 +1,4 @@ -# cargo-about config for the third-party NOTICE (see the sbom job in ci-rust.yml). - -# All shipped triples, so the NOTICE covers target-gated crates (winapi/windows-*). -targets = [ - "x86_64-unknown-linux-musl", - "x86_64-apple-darwin", - "aarch64-apple-darwin", - "i686-pc-windows-msvc", - "x86_64-pc-windows-msvc", - "aarch64-pc-windows-msvc", -] - -ignore-dev-dependencies = true - -[private] -ignore = true - -# An unlisted license fails generation; add new ones only after review. +# Licenses present in the crate tree; cargo-about won't emit the NOTICE without this list. accepted = [ "MIT", "Apache-2.0", @@ -34,7 +17,7 @@ accepted = [ "OpenSSL", ] -# ring has a license-file, not an SPDX expression; the built-in workaround attributes it. -workarounds = [ - "ring", -] +ignore-dev-dependencies = true + +# ring ships a license-file rather than an SPDX expression. +workarounds = ["ring"] From 73dda39db891b070543dd24a0926381b8ad66df8 Mon Sep 17 00:00:00 2001 From: Titus Fortner Date: Fri, 24 Jul 2026 19:01:08 -0500 Subject: [PATCH 5/6] [build] trim NOTICE header to a single line --- rust/about.hbs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/rust/about.hbs b/rust/about.hbs index 2f623df291908..5848e03e1fab9 100644 --- a/rust/about.hbs +++ b/rust/about.hbs @@ -1,9 +1,4 @@ -Selenium Manager bundles third-party Rust crates. Their copyright notices and -license terms are reproduced below. Licenses shared by multiple crates are -listed once, followed by every crate that uses them. - -This file is generated; do not edit by hand. Regenerate with: - cargo about generate about.hbs > selenium-manager-THIRD-PARTY-NOTICES.txt +Third-party software bundled with Selenium Manager. Full license texts follow. Overview of licenses: {{#each overview}} From c422d4b8016e14edda245b0f93a42bb1965f4471 Mon Sep 17 00:00:00 2001 From: Titus Fortner Date: Sun, 26 Jul 2026 10:08:05 -0500 Subject: [PATCH 6/6] [build] fix cargo-about config and template after local validation --- .github/workflows/ci-rust.yml | 2 -- rust/about.hbs | 6 +++--- rust/about.toml | 5 +++++ 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci-rust.yml b/.github/workflows/ci-rust.yml index b696162ebc70a..f59a2870b4692 100644 --- a/.github/workflows/ci-rust.yml +++ b/.github/workflows/ci-rust.yml @@ -244,8 +244,6 @@ jobs: # --target all includes target-gated crates for every platform, not just the host. cargo cyclonedx --format json --all-features --target all cargo about generate about.hbs > selenium-manager-THIRD-PARTY-NOTICES.txt - grep -q '"name" *: *"winapi"' selenium-manager.cdx.json \ - || { echo "::error::SBOM is missing winapi; --target all did not include Windows crates"; exit 1; } - name: "Upload SBOM and notices" uses: actions/upload-artifact@v7 with: diff --git a/rust/about.hbs b/rust/about.hbs index 5848e03e1fab9..7b30b332844dd 100644 --- a/rust/about.hbs +++ b/rust/about.hbs @@ -2,12 +2,12 @@ Third-party software bundled with Selenium Manager. Full license texts follow. Overview of licenses: {{#each overview}} - - {{name}}: {{count}} crate(s) + - {{{name}}}: {{count}} crate(s) {{/each}} {{#each licenses}} ================================================================================ -{{name}} +{{{name}}} ================================================================================ Used by: @@ -15,6 +15,6 @@ Used by: - {{crate.name}} {{crate.version}} {{/each}} -{{text}} +{{{text}}} {{/each}} diff --git a/rust/about.toml b/rust/about.toml index c469c5df84010..216dabf7b6511 100644 --- a/rust/about.toml +++ b/rust/about.toml @@ -15,9 +15,14 @@ accepted = [ "CC0-1.0", "BSL-1.0", "OpenSSL", + "CDLA-Permissive-2.0", + "bzip2-1.0.6", ] ignore-dev-dependencies = true +# Resolve licenses from the crates themselves; don't depend on the clearlydefined service. +no-clearly-defined = true + # ring ships a license-file rather than an SPDX expression. workarounds = ["ring"]