From 31ad5cd6501695ccb2193943bdf643dc4ce26e16 Mon Sep 17 00:00:00 2001 From: Lukas Puehringer Date: Mon, 16 Mar 2026 10:32:25 +0000 Subject: [PATCH 1/2] Add 3 SBOM workflows for server and webui components * Adds two workflows to generate SBOMs from webui and server docker images using 'anchore/sbom-action' on 'registry_package' events (i.e. when an image is published in the registry). * Adds one workflow to genrate an SBOM for the server gradle build using the CycloneDX Gradle plugin injected via init script on version tag pushes. * All workflows can also be triggered with workflow_dispatch for backfilling and testing. * SBOMs are uploaded to sbom-staging.eclipse.org via pia-staging.eclipse.org. * Upload logic is extracted into a reusable composite action * Using separate workflows per SBOM upload is currently required by PIA (as it would be by Otterdog). It also makes the workflows simpler, with only little code repetition. Co-Authored-By: Claude Opus 4.6 Signed-off-by: Lukas Puehringer --- .github/actions/upload-sbom/action.yml | 42 +++++++++++++ .github/workflows/sbom-server-docker.yml | 49 +++++++++++++++ .github/workflows/sbom-server-gradle.yml | 80 ++++++++++++++++++++++++ .github/workflows/sbom-webui-docker.yml | 49 +++++++++++++++ 4 files changed, 220 insertions(+) create mode 100644 .github/actions/upload-sbom/action.yml create mode 100644 .github/workflows/sbom-server-docker.yml create mode 100644 .github/workflows/sbom-server-gradle.yml create mode 100644 .github/workflows/sbom-webui-docker.yml diff --git a/.github/actions/upload-sbom/action.yml b/.github/actions/upload-sbom/action.yml new file mode 100644 index 000000000..ac14fcc09 --- /dev/null +++ b/.github/actions/upload-sbom/action.yml @@ -0,0 +1,42 @@ +# TODO: Move to eclipse-csi/workflows +name: Upload SBOM +description: Upload SBOM to DependencyTrack via PIA + +inputs: + sbom-file: + description: Path to the SBOM JSON file + required: true + product-name: + description: Product name to report to DependencyTrack + required: true + product-version: + description: Product version to report to DependencyTrack + required: true + +runs: + using: composite + steps: + # Upload SBOM to sbom-staging.eclipse.org using pia-staging.eclipse.org + - name: Upload SBOM + shell: bash + env: + PIA_DOMAIN: pia-staging.eclipse.org + run: | + echo "Upload SBOM for ${{ inputs.product-name }} ${{ inputs.product-version }}" + + # Get OIDC token from GitHub Identity Provider + ID_TOKEN=$(curl -sS -H "Authorization: bearer ${ACTIONS_ID_TOKEN_REQUEST_TOKEN}" \ + "${ACTIONS_ID_TOKEN_REQUEST_URL}&audience=${{ env.PIA_DOMAIN }}" | jq -r '.value') + + # Build JSON payload and upload to PIA + # Use jq --arg for proper JSON escaping of untrusted inputs, + # and --rawfile to read the large base64 bom from a file + # (passing it as --arg would exceed the argument list limit). + base64 -w0 "${{ inputs.sbom-file }}" > bom.b64 + jq -n --arg name "${{ inputs.product-name }}" \ + --arg version "${{ inputs.product-version }}" \ + --rawfile bom bom.b64 \ + '{product_name: $name, product_version: $version, bom: $bom}' | \ + curl -sS --fail-with-body https://${{ env.PIA_DOMAIN }}/v1/upload/sbom \ + -H "Authorization: Bearer ${ID_TOKEN}" \ + --json @- diff --git a/.github/workflows/sbom-server-docker.yml b/.github/workflows/sbom-server-docker.yml new file mode 100644 index 000000000..5b7fd8dcb --- /dev/null +++ b/.github/workflows/sbom-server-docker.yml @@ -0,0 +1,49 @@ +# FIXME: As temporary workaround this name is used to assign the SBOM to the +# correct product slot within the OpenVSX project on DependencyTrack. +name: Generate SBOM (server docker image) # PLEASE DO NOT CHANGE! + +on: + registry_package: + types: [published] + workflow_dispatch: + inputs: + version: + description: "Version tag (e.g. v1.2.3)" + required: true + +permissions: + id-token: write + +env: + REGISTRY: ghcr.io + OWNER: eclipse + NAME: openvsx-server + # TODO: Make sure that `registry_package.[...].tag.name` can be relied on. + # What if 'docker/metadata-action' in release.yml sets no, or multiple tags? + VERSION: "${{ inputs.version || github.event.registry_package.package_version.container_metadata.tag.name }}" + +jobs: + sbom-server-docker: + if: github.event_name == 'workflow_dispatch' || github.event.registry_package.name == 'openvsx-server' + runs-on: ubuntu-latest + steps: + # Checkout only .github/actions to make the upload-sbom composite action available + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + sparse-checkout: .github/actions + persist-credentials: false + + - name: Generate SBOM + uses: anchore/sbom-action@28d71544de8eaf1b958d335707167c5f783590ad # v0.22.2 + with: + image: ${{ env.REGISTRY }}/${{ env.OWNER }}/${{ env.NAME }}:${{ env.VERSION }} + output-file: sbom.json + format: cyclonedx-json + upload-artifact: false + + - name: Upload SBOM + uses: ./.github/actions/upload-sbom + with: + sbom-file: sbom.json + product-name: "${{ env.NAME }} docker image" + product-version: ${{ env.VERSION }} diff --git a/.github/workflows/sbom-server-gradle.yml b/.github/workflows/sbom-server-gradle.yml new file mode 100644 index 000000000..2f075d4b3 --- /dev/null +++ b/.github/workflows/sbom-server-gradle.yml @@ -0,0 +1,80 @@ +# As temporary workaround this name is used to assign the SBOM to the correct +# product slot within the OpenVSX project on DependencyTrack. +name: Generate SBOM (server gradle) # PLEASE DO NOT CHANGE! + +on: + push: + tags: + - "v*" + workflow_dispatch: + inputs: + version: + description: "Version tag (e.g. v1.2.3)" + required: true + +permissions: + id-token: write + +env: + VERSION: "${{ inputs.version || github.ref_name }}" + +jobs: + sbom-server-gradle: + runs-on: ubuntu-latest + steps: + # Checkout .github/actions to make sure the upload-sbom action is available, + # even if the workflow was triggered manually on an older tag. + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + sparse-checkout: .github/actions + persist-credentials: false + + # Checkout project into subdirectory to avoid collision with above checkout. + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + ref: ${{ env.VERSION }} + fetch-depth: 0 + path: source + persist-credentials: false + + - name: Set up JDK + uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0 + with: + distribution: 'temurin' + java-version: 25 + + - name: Generate SBOM + run: | + # Enable CycloneDX plugin on the fly via init script. This leaves + # project gradle config untouched, and allows backfilling sboms for + # older project checkouts using workflow_dispatch. + + # Generate init script + # see https://github.com/CycloneDX/cyclonedx-gradle-plugin?tab=readme-ov-file#usage-with-initialization-script + + cat > /tmp/cyclonedx-init.gradle.kts << 'EOF' + import org.cyclonedx.gradle.CyclonedxPlugin + + initscript { + repositories { gradlePluginPortal() } + dependencies { + classpath("org.cyclonedx:cyclonedx-gradle-plugin:3.2.0") + } + } + rootProject { + apply() + } + EOF + + # Generate aggregate SBOM + source/server/gradlew --no-daemon --init-script /tmp/cyclonedx-init.gradle.kts -p source/server cyclonedxBom + + env: + DEVELOCITY_ACCESS_KEY: ${{ secrets.DEVELOCITY_API_TOKEN }} + + - name: Upload SBOM + uses: ./.github/actions/upload-sbom + with: + sbom-file: source/server/build/reports/cyclonedx/bom.json + product-name: "openvsx-server" + product-version: ${{ env.VERSION }} diff --git a/.github/workflows/sbom-webui-docker.yml b/.github/workflows/sbom-webui-docker.yml new file mode 100644 index 000000000..a6d011d9b --- /dev/null +++ b/.github/workflows/sbom-webui-docker.yml @@ -0,0 +1,49 @@ +# FIXME: As temporary workaround this name is used to assign the SBOM to the +# correct product slot within the OpenVSX project on DependencyTrack. +name: Generate SBOM (webui docker image) # PLEASE DO NOT CHANGE! + +on: + registry_package: + types: [published] + workflow_dispatch: + inputs: + version: + description: "Version tag (e.g. v1.2.3)" + required: true + +permissions: + id-token: write + +env: + REGISTRY: ghcr.io + OWNER: eclipse + NAME: openvsx-webui + # TODO: Make sure that `registry_package.[...].tag.name` can be relied on. + # What if 'docker/metadata-action' in release.yml sets no, or multiple tags? + VERSION: "${{ inputs.version || github.event.registry_package.package_version.container_metadata.tag.name }}" + +jobs: + sbom-webui-docker: + if: github.event_name == 'workflow_dispatch' || github.event.registry_package.name == 'openvsx-webui' + runs-on: ubuntu-latest + steps: + # Checkout only .github/actions to make the upload-sbom composite action available + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + sparse-checkout: .github/actions + persist-credentials: false + + - name: Generate SBOM + uses: anchore/sbom-action@28d71544de8eaf1b958d335707167c5f783590ad # v0.22.2 + with: + image: ${{ env.REGISTRY }}/${{ env.OWNER }}/${{ env.NAME }}:${{ env.VERSION }} + output-file: sbom.json + format: cyclonedx-json + upload-artifact: false + + - name: Upload SBOM + uses: ./.github/actions/upload-sbom + with: + sbom-file: sbom.json + product-name: "${{ env.NAME }} docker image" + product-version: ${{ env.VERSION }} From 3de705bd300d77990c2ef69f3b9cd2c70582309c Mon Sep 17 00:00:00 2001 From: Lukas Puehringer Date: Mon, 16 Mar 2026 10:44:32 +0000 Subject: [PATCH 2/2] Add 2 SBOM workflows for cli and webui components Split generate-yarn-sboms.yml from #1640 into two separate workflows. Key changes from the original: - Two instead of one workflows. This is currently required by PIA (and would be required by Otterdog). It leads to some code repetition, but removes case handling. - Triggers on tag push (cli-*, webui-*) instead of release events. This simplifies conditional job run and tag name extraction. - Does not strip the webui-/cli- prefix from the version string sent to PIA/DependencyTrack. Co-Authored-By: Claude Opus 4.6 Signed-off-by: Lukas Puehringer --- .github/workflows/sbom-cli-yarn.yml | 71 +++++++++++++++++++++++++++ .github/workflows/sbom-webui-yarn.yml | 71 +++++++++++++++++++++++++++ 2 files changed, 142 insertions(+) create mode 100644 .github/workflows/sbom-cli-yarn.yml create mode 100644 .github/workflows/sbom-webui-yarn.yml diff --git a/.github/workflows/sbom-cli-yarn.yml b/.github/workflows/sbom-cli-yarn.yml new file mode 100644 index 000000000..a6a92a5de --- /dev/null +++ b/.github/workflows/sbom-cli-yarn.yml @@ -0,0 +1,71 @@ +# As temporary workaround this name is used to assign the SBOM to the correct +# product slot within the OpenVSX project on DependencyTrack. +name: Generate SBOM (CLI yarn) # PLEASE DO NOT CHANGE! + +on: + push: + tags: + - 'cli-*' + workflow_dispatch: + inputs: + tag: + description: "Release tag (e.g. cli-1.2.3)" + required: true + type: string + +permissions: + id-token: write + +env: + NAME: openvsx-cli + TAG: "${{ inputs.tag || github.ref_name }}" + CYCLONEDX_YARN_PLUGIN_VERSION: "3.2.1" + +jobs: + sbom-cli-yarn: + if: startsWith(inputs.tag || github.ref_name, 'cli-') + runs-on: ubuntu-latest + steps: + # Checkout .github/actions to make sure the upload-sbom action is available, + # even if the workflow was triggered manually on an older tag. + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + sparse-checkout: .github/actions + persist-credentials: false + + # Checkout project into subdirectory to avoid collision with above checkout. + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + ref: ${{ env.TAG }} + path: source + persist-credentials: false + + - name: Setup Node.js + uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 + with: + node-version: '24.x' + package-manager-cache: false + registry-url: 'https://registry.npmjs.org' + + - name: Enable Corepack (Yarn Berry) + working-directory: source/cli + run: corepack enable + + - name: Install dependencies + working-directory: source/cli + run: yarn install --immutable + + - name: Generate SBOM + working-directory: source/cli + run: | + yarn dlx -q @cyclonedx/yarn-plugin-cyclonedx@${{ env.CYCLONEDX_YARN_PLUGIN_VERSION }} \ + --output-format JSON \ + --output-file bom.json \ + --production + + - name: Upload SBOM + uses: ./.github/actions/upload-sbom + with: + sbom-file: source/cli/bom.json + product-name: ${{ env.NAME }} + product-version: ${{ env.TAG }} diff --git a/.github/workflows/sbom-webui-yarn.yml b/.github/workflows/sbom-webui-yarn.yml new file mode 100644 index 000000000..728ae2053 --- /dev/null +++ b/.github/workflows/sbom-webui-yarn.yml @@ -0,0 +1,71 @@ +# As temporary workaround this name is used to assign the SBOM to the correct +# product slot within the OpenVSX project on DependencyTrack. +name: Generate SBOM (webui yarn) # PLEASE DO NOT CHANGE! + +on: + push: + tags: + - 'webui-*' + workflow_dispatch: + inputs: + tag: + description: "Release tag (e.g. webui-1.2.3)" + required: true + type: string + +permissions: + id-token: write + +env: + NAME: openvsx-webui + TAG: "${{ inputs.tag || github.ref_name }}" + CYCLONEDX_YARN_PLUGIN_VERSION: "3.2.1" + +jobs: + sbom-webui-yarn: + if: startsWith(inputs.tag || github.ref_name, 'webui-') + runs-on: ubuntu-latest + steps: + # Checkout .github/actions to make sure the upload-sbom action is available, + # even if the workflow was triggered manually on an older tag. + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + sparse-checkout: .github/actions + persist-credentials: false + + # Checkout project into subdirectory to avoid collision with above checkout. + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + ref: ${{ env.TAG }} + path: source + persist-credentials: false + + - name: Setup Node.js + uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 + with: + node-version: '24.x' + package-manager-cache: false + registry-url: 'https://registry.npmjs.org' + + - name: Enable Corepack (Yarn Berry) + working-directory: source/webui + run: corepack enable + + - name: Install dependencies + working-directory: source/webui + run: yarn install --immutable + + - name: Generate SBOM + working-directory: source/webui + run: | + yarn dlx -q @cyclonedx/yarn-plugin-cyclonedx@${{ env.CYCLONEDX_YARN_PLUGIN_VERSION }} \ + --output-format JSON \ + --output-file bom.json \ + --production + + - name: Upload SBOM + uses: ./.github/actions/upload-sbom + with: + sbom-file: source/webui/bom.json + product-name: ${{ env.NAME }} + product-version: ${{ env.TAG }}