From 8df0acc272b5b94cfc695402e021d377579f3798 Mon Sep 17 00:00:00 2001 From: Mikhail Preyskurantov <5574159+mpreyskurantov@users.noreply.github.com> Date: Wed, 15 Jul 2026 22:25:12 +0300 Subject: [PATCH 1/8] ci: centralize GitHub Packages npm auth setup --- .github/workflows/build_all.yml | 7 ++++--- .github/workflows/packages_publishing.yml | 13 ++++++++----- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build_all.yml b/.github/workflows/build_all.yml index 414f03b65711..4ff4246ba928 100644 --- a/.github/workflows/build_all.yml +++ b/.github/workflows/build_all.yml @@ -111,13 +111,14 @@ jobs: artifacts/npm/*.tgz retention-days: 1 + - name: Set GitHub Packages auth + run: pnpm set //npm.pkg.github.com/:_authToken='${NODE_AUTH_TOKEN}' + - name: Build SBOMs if: ${{ github.event_name == 'push' || github.event.inputs.SBOM == 'true' }} env: NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - pnpm set //npm.pkg.github.com/:_authToken="$NODE_AUTH_TOKEN"; - pnpm nx build sbom; + run: pnpm nx build sbom - name: Upload SBOM artifacts if: ${{ github.event_name == 'push' || github.event.inputs.SBOM == 'true' }} diff --git a/.github/workflows/packages_publishing.yml b/.github/workflows/packages_publishing.yml index fd1940048b24..e5a7b4ef6822 100644 --- a/.github/workflows/packages_publishing.yml +++ b/.github/workflows/packages_publishing.yml @@ -52,12 +52,13 @@ jobs: BUILD_INTERNAL_PACKAGE: true run: pnpm run all:build + - name: Set GitHub Packages auth + run: pnpm set //npm.pkg.github.com/:_authToken='${NODE_AUTH_TOKEN}' + - name: Build SBOMs env: NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - pnpm set //npm.pkg.github.com/:_authToken="$NODE_AUTH_TOKEN"; - pnpm nx build sbom; + run: pnpm nx build sbom - name: Build artifacts package run: pnpm run make-artifacts-package @@ -124,10 +125,13 @@ jobs: pnpm pkg get version | tr -d '"' | sed -r 's/(.*)/version=\1/' >> "$GITHUB_OUTPUT"; pnpm pkg get version | tr -d '"' | sed -r 's/([0-9]+\.[0-9]+).*/majorVersion=\1/' >> "$GITHUB_OUTPUT"; + - name: Set GitHub Packages auth + run: pnpm set //npm.pkg.github.com/:_authToken='${NODE_AUTH_TOKEN}' + # --ignore-scripts is required for publishing devextreme-angular which fails with error: # 'Trying to publish a package that has been compiled by Ivy in full compilation mode.' # Should be removed. - - name: Publish to npm.pkg.github.com + - name: Publish to GitHub Packages working-directory: ${{ steps.scopedPackage.outputs.packageDir }} env: NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -135,7 +139,6 @@ jobs: PACKAGE_VERSION: ${{ steps.scopedPackage.outputs.version }} PACKAGE_VERSION_MAJOR: ${{ steps.scopedPackage.outputs.majorVersion }} run: | - pnpm set //npm.pkg.github.com/:_authToken="$NODE_AUTH_TOKEN"; pnpm publish --no-git-checks --quiet --ignore-scripts --tag $PACKAGE_VERSION_MAJOR-${{ inputs.tag }} --registry https://npm.pkg.github.com; pnpm dist-tag add $PACKAGE_NAME@$PACKAGE_VERSION latest --registry=https://npm.pkg.github.com; From 78e2ef748bef60b09839438efacf43b1ce9ca3c6 Mon Sep 17 00:00:00 2001 From: Mikhail Preyskurantov <5574159+mpreyskurantov@users.noreply.github.com> Date: Thu, 16 Jul 2026 17:22:01 +0300 Subject: [PATCH 2/8] build_all.yml / consistent guard --- .github/workflows/build_all.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build_all.yml b/.github/workflows/build_all.yml index 4ff4246ba928..1f6e67f821e9 100644 --- a/.github/workflows/build_all.yml +++ b/.github/workflows/build_all.yml @@ -112,6 +112,7 @@ jobs: retention-days: 1 - name: Set GitHub Packages auth + if: ${{ github.event_name == 'push' || github.event.inputs.SBOM == 'true' }} run: pnpm set //npm.pkg.github.com/:_authToken='${NODE_AUTH_TOKEN}' - name: Build SBOMs From 4c25d6ee82f1a3ac71c8b9f95867cc9a91ce84db Mon Sep 17 00:00:00 2001 From: Mikhail Preyskurantov <5574159+mpreyskurantov@users.noreply.github.com> Date: Thu, 16 Jul 2026 20:11:24 +0300 Subject: [PATCH 3/8] ci: publish SBOMs as ghp --- .github/workflows/packages_publishing.yml | 136 ++++++++++++++++++++-- 1 file changed, 129 insertions(+), 7 deletions(-) diff --git a/.github/workflows/packages_publishing.yml b/.github/workflows/packages_publishing.yml index e5a7b4ef6822..8c3dc3848b02 100644 --- a/.github/workflows/packages_publishing.yml +++ b/.github/workflows/packages_publishing.yml @@ -20,6 +20,7 @@ env: NX_SKIP_NX_CACHE: true FILTER: ${{ github.event_name == 'workflow_dispatch' && inputs.filter || '' }} SET_TIMESTAMP_VERSION: ${{ inputs.tag == 'daily' }} + SBOM_PACKAGE_NAMES: devextreme,devextreme-angular,devextreme-react,devextreme-vue,devextreme-themebuilder jobs: build: @@ -52,28 +53,89 @@ jobs: BUILD_INTERNAL_PACKAGE: true run: pnpm run all:build + # Builds the dx-make-sbom package argument list from known package names and the tgz files produced in artifacts/npm. + # Produces SBOM_PACKAGES for the SBOM build step. + - name: Prepare SBOM package inputs + shell: bash + run: | + package_version=$(node -p "require('./package.json').version") + IFS=',' read -ra package_names <<< "$SBOM_PACKAGE_NAMES" + sbom_packages=() + + for package_name in "${package_names[@]}"; do + tgz_path="artifacts/npm/$package_name-$package_version.tgz" + + if [ ! -f "$tgz_path" ]; then + echo "Expected package tarball not found: $tgz_path" + exit 1 + fi + + sbom_packages+=("$package_name(../../$tgz_path)") + done + + sbom_packages_value=$(IFS=,; echo "${sbom_packages[*]}") + echo "SBOM_PACKAGES=$sbom_packages_value" >> "$GITHUB_ENV" + echo "$sbom_packages_value" + - name: Set GitHub Packages auth run: pnpm set //npm.pkg.github.com/:_authToken='${NODE_AUTH_TOKEN}' + # Generates CycloneDX SBOM JSON files for the selected packages using the just-built tgz files. + # Produces packages/sbom/dist/*.cdx.json. - name: Build SBOMs + working-directory: packages/sbom env: NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: pnpm nx build sbom + run: | + pnpm install --frozen-lockfile + rm -rf dist/ + pnpm dx-make-sbom ../../ dist/ "$SBOM_PACKAGES" + cp dist/devextreme.cdx.json dist/devextreme-dist.cdx.json + + # Collects concrete SBOM file paths for validation because the shared action expects explicit file names. + # Produces the sbomFiles.outputs.files multiline output. + - name: Collect SBOM files + id: sbomFiles + shell: bash + run: | + shopt -s nullglob + sbom_files=(packages/sbom/dist/*.cdx.json) + + if [ ${#sbom_files[@]} -eq 0 ]; then + echo "No SBOM files found in packages/sbom/dist" + exit 1 + fi + + { + echo "files<> "$GITHUB_OUTPUT" + + # Validates every generated CycloneDX SBOM file with the shared validation action. + # Produces no artifact; fails the workflow if any SBOM is invalid. + - name: Validate SBOMs + uses: DevExpress/github-actions/validate-sbom@5034a6d5e0fd18fc2826ed20a5140f9c83b8994f + with: + input-format: json + input-files: ${{ steps.sbomFiles.outputs.files }} - name: Build artifacts package run: pnpm run make-artifacts-package - - name: Upload SBOM artifact + # Saves generated SBOM files for the publish job. + # Produces the sbom-packages workflow artifact. + - name: Upload SBOMs uses: actions/upload-artifact@v7 with: - name: sbom + name: sbom-packages path: packages/sbom/dist retention-days: 7 - name: Upload packages uses: actions/upload-artifact@v7 with: - name: packages + name: npm-packages path: artifacts/npm/*.tgz retention-days: 2 @@ -95,10 +157,19 @@ jobs: - name: Get sources uses: actions/checkout@v6 - - name: Download artifacts + - name: Download packages + uses: actions/download-artifact@v8 + with: + name: npm-packages + path: npm-packages + + # Restores generated SBOM files from the build job. + # Produces the local sbom-packages directory for matrix publishing. + - name: Download SBOMs uses: actions/download-artifact@v8 with: - name: packages + name: sbom-packages + path: sbom-packages - name: Use Node.js uses: actions/setup-node@v6 @@ -118,13 +189,50 @@ jobs: PACKAGE: ${{ matrix.package }} run: | SCOPE=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]'); - PACKAGE_DIR=$(pnpm --silent run change-package-scope --tgz $PACKAGE.tgz --scope $SCOPE) + PACKAGE_DIR=$(pnpm --silent run change-package-scope --tgz npm-packages/$PACKAGE.tgz --scope $SCOPE) echo "packageDir=$PACKAGE_DIR" >> "$GITHUB_OUTPUT"; cd $PACKAGE_DIR; pnpm pkg get name | tr -d '"' | sed -r 's/(.*)/name=\1/' >> "$GITHUB_OUTPUT"; pnpm pkg get version | tr -d '"' | sed -r 's/(.*)/version=\1/' >> "$GITHUB_OUTPUT"; pnpm pkg get version | tr -d '"' | sed -r 's/([0-9]+\.[0-9]+).*/majorVersion=\1/' >> "$GITHUB_OUTPUT"; + # Wraps the matching SBOM JSON file into a minimal @/-sbom npm package when the matrix package has an SBOM. + # Produces sbomPackage outputs used by the publish step. + - name: Build SBOM package + id: sbomPackage + env: + PACKAGE_NAME: ${{ steps.scopedPackage.outputs.name }} + PACKAGE_VERSION: ${{ steps.scopedPackage.outputs.version }} + run: | + UNSCOPED_PACKAGE_NAME=$(echo "$PACKAGE_NAME" | sed -r 's#^@[^/]+/##'); + SBOM_FILE="sbom-packages/$UNSCOPED_PACKAGE_NAME.cdx.json"; + + if [[ ",$SBOM_PACKAGE_NAMES," != *",$UNSCOPED_PACKAGE_NAME,"* ]]; then + echo "SBOM publishing is not configured for $UNSCOPED_PACKAGE_NAME" + echo "hasSbom=false" >> "$GITHUB_OUTPUT"; + exit 0; + fi + + if [ ! -f "$SBOM_FILE" ]; then + echo "No SBOM found for $UNSCOPED_PACKAGE_NAME" + echo "hasSbom=false" >> "$GITHUB_OUTPUT"; + exit 0; + fi + + OWNER=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]'); + SBOM_PACKAGE_NAME="@$OWNER/$UNSCOPED_PACKAGE_NAME-sbom"; + SBOM_PACKAGE_DIR="sbom-package/$SBOM_PACKAGE_NAME"; + + mkdir -p "$SBOM_PACKAGE_DIR"; + cp "$SBOM_FILE" "$SBOM_PACKAGE_DIR/"; + cd "$SBOM_PACKAGE_DIR"; + node -e "const fs = require('fs'); const [name, version] = process.argv.slice(1); fs.writeFileSync('package.json', JSON.stringify({ name, version }, null, 2));" "$SBOM_PACKAGE_NAME" "$PACKAGE_VERSION"; + echo "hasSbom=true" >> "$GITHUB_OUTPUT"; + echo "packageDir=$PWD" >> "$GITHUB_OUTPUT"; + pnpm pkg get name | tr -d '"' | sed -r 's/(.*)/name=\1/' >> "$GITHUB_OUTPUT"; + pnpm pkg get version | tr -d '"' | sed -r 's/(.*)/version=\1/' >> "$GITHUB_OUTPUT"; + pnpm pkg get version | tr -d '"' | sed -r 's/([0-9]+\.[0-9]+).*/majorVersion=\1/' >> "$GITHUB_OUTPUT"; + - name: Set GitHub Packages auth run: pnpm set //npm.pkg.github.com/:_authToken='${NODE_AUTH_TOKEN}' @@ -142,6 +250,20 @@ jobs: pnpm publish --no-git-checks --quiet --ignore-scripts --tag $PACKAGE_VERSION_MAJOR-${{ inputs.tag }} --registry https://npm.pkg.github.com; pnpm dist-tag add $PACKAGE_NAME@$PACKAGE_VERSION latest --registry=https://npm.pkg.github.com; + # Publishes the generated @/-sbom npm package to GitHub Packages. + # Produces @/-sbom in the npm.pkg.github.com feed. + - name: Publish SBOM to GitHub Packages + if: ${{ steps.sbomPackage.outputs.hasSbom == 'true' }} + working-directory: ${{ steps.sbomPackage.outputs.packageDir }} + env: + NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PACKAGE_NAME: ${{ steps.sbomPackage.outputs.name }} + PACKAGE_VERSION: ${{ steps.sbomPackage.outputs.version }} + PACKAGE_VERSION_MAJOR: ${{ steps.sbomPackage.outputs.majorVersion }} + run: | + pnpm publish --no-git-checks --quiet --ignore-scripts --tag $PACKAGE_VERSION_MAJOR-${{ inputs.tag }} --registry https://npm.pkg.github.com; + pnpm dist-tag add $PACKAGE_NAME@$PACKAGE_VERSION latest --registry=https://npm.pkg.github.com; + notify: runs-on: ubuntu-latest name: Send notifications From 4d3ef18aae82bb3a875470fd67737082c748e942 Mon Sep 17 00:00:00 2001 From: Mikhail Preyskurantov <5574159+mpreyskurantov@users.noreply.github.com> Date: Fri, 17 Jul 2026 16:54:27 +0300 Subject: [PATCH 4/8] Revert "build_all.yml / consistent guard" This reverts commit 78e2ef748bef60b09839438efacf43b1ce9ca3c6. --- .github/workflows/build_all.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/build_all.yml b/.github/workflows/build_all.yml index 1f6e67f821e9..4ff4246ba928 100644 --- a/.github/workflows/build_all.yml +++ b/.github/workflows/build_all.yml @@ -112,7 +112,6 @@ jobs: retention-days: 1 - name: Set GitHub Packages auth - if: ${{ github.event_name == 'push' || github.event.inputs.SBOM == 'true' }} run: pnpm set //npm.pkg.github.com/:_authToken='${NODE_AUTH_TOKEN}' - name: Build SBOMs From c507d44858545fd15670ddade26949dae4c58413 Mon Sep 17 00:00:00 2001 From: Mikhail Preyskurantov <5574159+mpreyskurantov@users.noreply.github.com> Date: Fri, 17 Jul 2026 16:57:44 +0300 Subject: [PATCH 5/8] Revert "ci: centralize GitHub Packages npm auth setup" This reverts commit 8df0acc272b5b94cfc695402e021d377579f3798. # Conflicts: # .github/workflows/packages_publishing.yml --- .github/workflows/build_all.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build_all.yml b/.github/workflows/build_all.yml index 4ff4246ba928..414f03b65711 100644 --- a/.github/workflows/build_all.yml +++ b/.github/workflows/build_all.yml @@ -111,14 +111,13 @@ jobs: artifacts/npm/*.tgz retention-days: 1 - - name: Set GitHub Packages auth - run: pnpm set //npm.pkg.github.com/:_authToken='${NODE_AUTH_TOKEN}' - - name: Build SBOMs if: ${{ github.event_name == 'push' || github.event.inputs.SBOM == 'true' }} env: NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: pnpm nx build sbom + run: | + pnpm set //npm.pkg.github.com/:_authToken="$NODE_AUTH_TOKEN"; + pnpm nx build sbom; - name: Upload SBOM artifacts if: ${{ github.event_name == 'push' || github.event.inputs.SBOM == 'true' }} From c067c76098550f5c072cf75f0150e45dff90a074 Mon Sep 17 00:00:00 2001 From: Mikhail Preyskurantov <5574159+mpreyskurantov@users.noreply.github.com> Date: Fri, 17 Jul 2026 19:08:09 +0300 Subject: [PATCH 6/8] retention-days: 1 (ghp transport); no explicit shell: bash (always linux); publish runs-on: ubuntu-slim (not yet build) --- .github/workflows/packages_publishing.yml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/.github/workflows/packages_publishing.yml b/.github/workflows/packages_publishing.yml index 8c3dc3848b02..54412b53bb30 100644 --- a/.github/workflows/packages_publishing.yml +++ b/.github/workflows/packages_publishing.yml @@ -56,7 +56,6 @@ jobs: # Builds the dx-make-sbom package argument list from known package names and the tgz files produced in artifacts/npm. # Produces SBOM_PACKAGES for the SBOM build step. - name: Prepare SBOM package inputs - shell: bash run: | package_version=$(node -p "require('./package.json').version") IFS=',' read -ra package_names <<< "$SBOM_PACKAGE_NAMES" @@ -96,7 +95,6 @@ jobs: # Produces the sbomFiles.outputs.files multiline output. - name: Collect SBOM files id: sbomFiles - shell: bash run: | shopt -s nullglob sbom_files=(packages/sbom/dist/*.cdx.json) @@ -130,24 +128,25 @@ jobs: with: name: sbom-packages path: packages/sbom/dist - retention-days: 7 + if-no-files-found: error + retention-days: 1 - name: Upload packages uses: actions/upload-artifact@v7 with: name: npm-packages path: artifacts/npm/*.tgz - retention-days: 2 + if-no-files-found: error + retention-days: 1 - name: Filter packages id: filter working-directory: artifacts/npm - shell: bash run: ls *.tgz | grep -E -i "$FILTER" | sed -r 's/^(.*).tgz$/"\1"/g' | paste -sd "," - | sed -r 's/(.*)/packages=[\1]/' >> "$GITHUB_OUTPUT" publish: name: Publish package - runs-on: ubuntu-latest + runs-on: ubuntu-slim needs: build strategy: fail-fast: false From b029a33fd3a678d24508af201a59e0c35b9d2c62 Mon Sep 17 00:00:00 2001 From: Mikhail Preyskurantov <5574159+mpreyskurantov@users.noreply.github.com> Date: Fri, 17 Jul 2026 19:55:48 +0300 Subject: [PATCH 7/8] build runs-on: ubuntu-slim (like just publish) --- .github/workflows/packages_publishing.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/packages_publishing.yml b/.github/workflows/packages_publishing.yml index 54412b53bb30..66ea1bfacae3 100644 --- a/.github/workflows/packages_publishing.yml +++ b/.github/workflows/packages_publishing.yml @@ -25,7 +25,7 @@ env: jobs: build: name: Build packages - runs-on: ubuntu-latest + runs-on: ubuntu-slim outputs: packages: ${{ steps.filter.outputs.packages }} steps: From 323e290c2c728f42b9b3c09d8fa86fb4cbd4299c Mon Sep 17 00:00:00 2001 From: Mikhail Preyskurantov <5574159+mpreyskurantov@users.noreply.github.com> Date: Fri, 17 Jul 2026 20:20:18 +0300 Subject: [PATCH 8/8] Revert "build runs-on: ubuntu-slim (like just publish)" This reverts commit b029a33fd3a678d24508af201a59e0c35b9d2c62. --- .github/workflows/packages_publishing.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/packages_publishing.yml b/.github/workflows/packages_publishing.yml index 66ea1bfacae3..54412b53bb30 100644 --- a/.github/workflows/packages_publishing.yml +++ b/.github/workflows/packages_publishing.yml @@ -25,7 +25,7 @@ env: jobs: build: name: Build packages - runs-on: ubuntu-slim + runs-on: ubuntu-latest outputs: packages: ${{ steps.filter.outputs.packages }} steps: