From ae3584dc984c3499e170eafc52a326153c1f634f Mon Sep 17 00:00:00 2001 From: Nick Noce Date: Mon, 5 Jan 2026 14:14:29 -0500 Subject: [PATCH 01/15] feat: add Docker validation step and pre-pull Edgescan image in workflow --- .github/workflows/copilot-setup-steps.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml index e3c2685f7..7bb589486 100644 --- a/.github/workflows/copilot-setup-steps.yml +++ b/.github/workflows/copilot-setup-steps.yml @@ -77,6 +77,12 @@ jobs: distribution: 'temurin' java-version: '17' + - name: Validate Docker and Pre-Pull Edgescan Image + run: | + docker --version + docker ps + docker pull edgescan/cicd-integration # Pre-pull to cache the image for faster agent runs + - name: Verify required environment variables run: | if [ -z "$SONAR_TOKEN" ]; then @@ -91,8 +97,18 @@ jobs: echo "Error: SNYK_TOKEN is not set." exit 1 fi + if [ -z "$ES_API_TOKEN" ]; then + echo "Error: ES_API_TOKEN is not set." + exit 1 + fi + if [ -z "$ES_ASSET_ID" ]; then + echo "Error: ES_ASSET_ID is not set." + exit 1 + fi echo "All required environment variables are set." env: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} GH_TOKEN: ${{ secrets.GH_TOKEN }} SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} + ES_API_TOKEN: ${{ secrets.ES_API_TOKEN }} + ES_ASSET_ID: ${{ secrets.ES_ASSET_ID }} From cc7e5714bed289857c9fb3deda407305acbaf255 Mon Sep 17 00:00:00 2001 From: Nick Noce Date: Mon, 5 Jan 2026 15:08:41 -0500 Subject: [PATCH 02/15] feat: update Snyk configuration and add Edgescan run script in package.json --- .snyk | 7 ++++++- package.json | 8 +++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/.snyk b/.snyk index aaedea816..0c8b35666 100644 --- a/.snyk +++ b/.snyk @@ -27,4 +27,9 @@ ignore: - '@docusaurus/preset-classic@3.9.2 > * > express': reason: 'Transitive dependency in Docusaurus; not exploitable in current usage.' expires: '2025-12-31T00:00:00.000Z' - created: '2025-12-02T09:39:00.000Z' \ No newline at end of file + created: '2025-12-02T09:39:00.000Z' + 'SNYK-JS-QS-14724253': + - '* > qs': + reason: 'Transitive dependency in express, @docusaurus/core, @apollo/server, apollo-link-rest; not exploitable in current usage.' + expires: '2026-01-19T00:00:00.000Z' + created: '2026-01-05T09:39:00.000Z' \ No newline at end of file diff --git a/package.json b/package.json index 489aee8f4..f39eac0da 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,8 @@ "snyk:iac": "snyk iac test iac/build/**/*.json --org=cellixjs --remote-repo-url=https://github.com/CellixJs/cellixjs", "snyk:iac:report": "snyk iac test iac/build/**/*.json --org=cellixjs --remote-repo-url=https://github.com/CellixJs/cellixjs --target-reference=main --target-name=cellixjs-iac --report", "analyze": "pnpm -r exec -- pnpm dlx @e18e/cli analyze", - "prepare": "husky" + "prepare": "husky", + "edgescan:run": "docker run --tty --rm -e ES_API_TOKEN -e ES_ASSET_ID -e MAX_RISK_THRESHOLD=3 edgescan/cicd-integration --wait --color" }, "devDependencies": { "@amiceli/vitest-cucumber": "^5.1.2", @@ -75,6 +76,11 @@ "vitest": "catalog:" }, "pnpm": { + "auditConfig": { + "ignoreGhsas": [ + "GHSA-6rw7-vpxm-498p" + ] + }, "overrides": { "vite": "catalog:", "jiti": "2.6.1" From 014b6ebc67d989a2efe95b8b5e55a2ef29d742a3 Mon Sep 17 00:00:00 2001 From: Nick Noce Date: Mon, 5 Jan 2026 16:27:52 -0500 Subject: [PATCH 03/15] feat: update Snyk expiration date, reorder credential groups, and add EdgeScan CI/CD integration stage --- .snyk | 2 +- azure-pipelines.yml | 14 +++++-- .../core/monorepo-edgescan-stage.yml | 42 +++++++++++++++++++ 3 files changed, 54 insertions(+), 4 deletions(-) create mode 100644 build-pipeline/core/monorepo-edgescan-stage.yml diff --git a/.snyk b/.snyk index 0c8b35666..1d9351d92 100644 --- a/.snyk +++ b/.snyk @@ -3,7 +3,7 @@ ignore: 'SNYK-JS-SIRV-12558119': - '* > sirv@2.0.4': reason: 'Transitive dependency in Docusaurus; not exploitable in static site serving context (dev-only asset handler)' - expires: '2025-12-31T00:00:00.000Z' + expires: '2026-01-19T00:00:00.000Z' created: '2025-11-06T15:57:00.000Z' 'SNYK-JS-JSYAML-13961110': - '* > js-yaml': diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 700826ef0..39cd13fc2 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -12,10 +12,11 @@ pool: vmImage: ubuntu-latest variables: - - group: sonarcloud-credential-cellixjs + - group: edgescan-credential-cellixjs - group: github-credential-cellixjs - - group: ui-community-settings-cellixjs - group: snyk-credential-cellixjs + - group: sonarcloud-credential-cellixjs + - group: ui-community-settings-cellixjs - name: deploymentDefaultLocation value: 'eastus2' - name: ServiceConnectionName @@ -63,4 +64,11 @@ stages: resourceGroupName: 'rg-sharethrift' appSettingsJsonFileRelativePathPri: 'apps/api/build-pipelines/config/dev-pri.json' frontDoorProfileName: 'simnova-afd' - frontDoorEndpointName: 'ocm-fde-ged3a8gxcvfxafaf' \ No newline at end of file + frontDoorEndpointName: 'ocm-fde-ged3a8gxcvfxafaf' + + - template: ./build-pipeline/core/monorepo-edgescan-stage.yml + parameters: + stageName: 'EdgeScan_DEV' + dependsOn: 'DEV' + vmImageName: $(vmImageName) + esAssetId: $(ES_ASSET_ID_DEV) \ No newline at end of file diff --git a/build-pipeline/core/monorepo-edgescan-stage.yml b/build-pipeline/core/monorepo-edgescan-stage.yml new file mode 100644 index 000000000..a0ca1998d --- /dev/null +++ b/build-pipeline/core/monorepo-edgescan-stage.yml @@ -0,0 +1,42 @@ +parameters: +- name: stageName + type: string + default: 'EdgeScan' +- name: dependsOn + type: string +- name: esAssetId + type: string +- name: vmImageName + type: string + default: 'ubuntu-latest' + +stages: +- stage: ${{parameters.stageName}} + displayName: 'EdgeScan Security Scan' + dependsOn: ${{parameters.dependsOn}} + condition: succeeded() + jobs: + - job: EdgeScan + displayName: 'EdgeScan CI/CD Integration' + pool: + vmImage: ${{parameters.vmImageName}} + steps: + - task: Bash@3 + displayName: 'Run EdgeScan Scan' + inputs: + targetType: 'inline' + script: | + if [ -z "$(ES_API_TOKEN)" ]; then + echo "Error: ES_API_TOKEN is not set in the variable group." + exit 1 + fi + + docker pull edgescan/cicd-integration + + echo "Triggering EdgeScan for Asset ID: ${{parameters.esAssetId}}" + + docker run --rm \ + -e ES_API_TOKEN=$(ES_API_TOKEN) \ + -e ES_ASSET_ID=${{parameters.esAssetId}} \ + -e MAX_RISK_THRESHOLD=3 \ + edgescan/cicd-integration --wait --color \ No newline at end of file From 85ef11dae813930ad718ba4234370cc4814d2301 Mon Sep 17 00:00:00 2001 From: Nick Noce Date: Tue, 6 Jan 2026 10:05:41 -0500 Subject: [PATCH 04/15] feat: enhance EdgeScan script to validate both ES_API_TOKEN and ES_ASSET_ID and fail the pipeline on error --- build-pipeline/core/monorepo-edgescan-stage.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/build-pipeline/core/monorepo-edgescan-stage.yml b/build-pipeline/core/monorepo-edgescan-stage.yml index a0ca1998d..0a99fb322 100644 --- a/build-pipeline/core/monorepo-edgescan-stage.yml +++ b/build-pipeline/core/monorepo-edgescan-stage.yml @@ -26,8 +26,10 @@ stages: inputs: targetType: 'inline' script: | - if [ -z "$(ES_API_TOKEN)" ]; then - echo "Error: ES_API_TOKEN is not set in the variable group." + set -euo pipefail + + if [ -z \"${ES_API_TOKEN}\" ] || [ -z "$(ES_ASSET_ID)" ]; then + echo "Error: Error: ES_API_TOKEN and ES_ASSET_ID must be set in the variable group." exit 1 fi From 5c9ede582e78379878daa7e90d72e09f6dc51e90 Mon Sep 17 00:00:00 2001 From: Nick Noce Date: Tue, 6 Jan 2026 10:22:43 -0500 Subject: [PATCH 05/15] feat: update EdgeScan integration to use the latest Docker image tag for consistency --- .github/workflows/copilot-setup-steps.yml | 2 +- build-pipeline/core/monorepo-edgescan-stage.yml | 9 ++++++--- package.json | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml index 7bb589486..6a313fe0e 100644 --- a/.github/workflows/copilot-setup-steps.yml +++ b/.github/workflows/copilot-setup-steps.yml @@ -81,7 +81,7 @@ jobs: run: | docker --version docker ps - docker pull edgescan/cicd-integration # Pre-pull to cache the image for faster agent runs + docker pull edgescan/cicd-integration:latest # Pre-pull to cache the image for faster agent runs - name: Verify required environment variables run: | diff --git a/build-pipeline/core/monorepo-edgescan-stage.yml b/build-pipeline/core/monorepo-edgescan-stage.yml index 0a99fb322..a1b61f54e 100644 --- a/build-pipeline/core/monorepo-edgescan-stage.yml +++ b/build-pipeline/core/monorepo-edgescan-stage.yml @@ -28,12 +28,12 @@ stages: script: | set -euo pipefail - if [ -z \"${ES_API_TOKEN}\" ] || [ -z "$(ES_ASSET_ID)" ]; then + if [ -z "${ES_API_TOKEN}" ] || [ -z "$(ES_ASSET_ID)" ]; then echo "Error: Error: ES_API_TOKEN and ES_ASSET_ID must be set in the variable group." exit 1 fi - docker pull edgescan/cicd-integration + docker pull edgescan/cicd-integration:latest echo "Triggering EdgeScan for Asset ID: ${{parameters.esAssetId}}" @@ -41,4 +41,7 @@ stages: -e ES_API_TOKEN=$(ES_API_TOKEN) \ -e ES_ASSET_ID=${{parameters.esAssetId}} \ -e MAX_RISK_THRESHOLD=3 \ - edgescan/cicd-integration --wait --color \ No newline at end of file + edgescan/cicd-integration:latest --wait --color + env: + ES_API_TOKEN: $(ES_API_TOKEN) + ES_ASSET_ID: $(ES_ASSET_ID) diff --git a/package.json b/package.json index f39eac0da..3aa7b012d 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "snyk:iac:report": "snyk iac test iac/build/**/*.json --org=cellixjs --remote-repo-url=https://github.com/CellixJs/cellixjs --target-reference=main --target-name=cellixjs-iac --report", "analyze": "pnpm -r exec -- pnpm dlx @e18e/cli analyze", "prepare": "husky", - "edgescan:run": "docker run --tty --rm -e ES_API_TOKEN -e ES_ASSET_ID -e MAX_RISK_THRESHOLD=3 edgescan/cicd-integration --wait --color" + "edgescan:run": "docker run --tty --rm -e ES_API_TOKEN -e ES_ASSET_ID -e MAX_RISK_THRESHOLD=3 edgescan/cicd-integration:latest --wait --color" }, "devDependencies": { "@amiceli/vitest-cucumber": "^5.1.2", From b31c002c509617b2d2f12490b16647139949e55d Mon Sep 17 00:00:00 2001 From: Nick Noce Date: Tue, 6 Jan 2026 10:36:31 -0500 Subject: [PATCH 06/15] feat: improve EdgeScan script error handling for ES_API_TOKEN and ES_ASSET_ID validation; fix syntax errors --- build-pipeline/core/monorepo-edgescan-stage.yml | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/build-pipeline/core/monorepo-edgescan-stage.yml b/build-pipeline/core/monorepo-edgescan-stage.yml index a1b61f54e..9e0d328df 100644 --- a/build-pipeline/core/monorepo-edgescan-stage.yml +++ b/build-pipeline/core/monorepo-edgescan-stage.yml @@ -28,20 +28,24 @@ stages: script: | set -euo pipefail - if [ -z "${ES_API_TOKEN}" ] || [ -z "$(ES_ASSET_ID)" ]; then - echo "Error: Error: ES_API_TOKEN and ES_ASSET_ID must be set in the variable group." + if [ -z "$ES_API_TOKEN" ] then + echo "Error: Error: ES_API_TOKEN must be set in the variable group." + exit 1 + fi + + if [ -z "${{ parameters.esAssetId }}" ]; then + echo "Error: ES_ASSET_ID_DEV must be set in the variable group." exit 1 fi docker pull edgescan/cicd-integration:latest - echo "Triggering EdgeScan for Asset ID: ${{parameters.esAssetId}}" + echo "Triggering EdgeScan for Asset ID: ${{ parameters.esAssetId }}" docker run --rm \ - -e ES_API_TOKEN=$(ES_API_TOKEN) \ - -e ES_ASSET_ID=${{parameters.esAssetId}} \ + -e ES_API_TOKEN=$ES_API_TOKEN \ + -e ES_ASSET_ID=${{ parameters.esAssetId }} \ -e MAX_RISK_THRESHOLD=3 \ edgescan/cicd-integration:latest --wait --color env: ES_API_TOKEN: $(ES_API_TOKEN) - ES_ASSET_ID: $(ES_ASSET_ID) From 80f103ea5efb5e30ff7e8192777dc75a02eac83d Mon Sep 17 00:00:00 2001 From: Nick Noce Date: Tue, 6 Jan 2026 10:37:01 -0500 Subject: [PATCH 07/15] chore: temporarily remove build/deploy conditions to test edgescan stage on PR run --- build-pipeline/core/monorepo-build-stage.yml | 12 ++++++------ build-pipeline/core/monorepo-deployment-stage.yml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build-pipeline/core/monorepo-build-stage.yml b/build-pipeline/core/monorepo-build-stage.yml index c972c790a..9e9e5fe72 100644 --- a/build-pipeline/core/monorepo-build-stage.yml +++ b/build-pipeline/core/monorepo-build-stage.yml @@ -434,7 +434,7 @@ stages: # Deploy API package with production dependencies - task: Bash@3 displayName: 'Artifact: Prepare API' - condition: and(succeeded(), eq(variables['BuildJob.HAS_BACKEND_CHANGES'], 'true'), ne(variables['Build.Reason'], 'PullRequest')) + condition: and(succeeded(), eq(variables['BuildJob.HAS_BACKEND_CHANGES'], 'true')) inputs: targetType: 'inline' script: | @@ -495,7 +495,7 @@ stages: # Package UI Community compiled assets into artifact - task: ArchiveFiles@2 displayName: 'Artifact: Prepare UI Community' - condition: and(succeeded(), eq(variables['BuildJob.HAS_FRONTEND_CHANGES'], 'true'), ne(variables['Build.Reason'], 'PullRequest')) + condition: and(succeeded(), eq(variables['BuildJob.HAS_FRONTEND_CHANGES'], 'true')) inputs: rootFolderOrFile: 'apps/ui-community/dist' includeRootFolder: false @@ -506,7 +506,7 @@ stages: # Package Docs compiled assets into artifact - task: ArchiveFiles@2 displayName: 'Artifact: Prepare Docs' - condition: and(succeeded(), eq(variables['BuildJob.HAS_DOCS_CHANGES'], 'true'), ne(variables['Build.Reason'], 'PullRequest')) + condition: and(succeeded(), eq(variables['BuildJob.HAS_DOCS_CHANGES'], 'true')) inputs: rootFolderOrFile: 'apps/docs/build' includeRootFolder: false @@ -517,17 +517,17 @@ stages: # Upload API artifact as build result - publish: $(Build.ArtifactStagingDirectory)/api-$(Build.BuildId).zip displayName: 'Artifact: Publish API' - condition: and(succeeded(), eq(variables['BuildJob.HAS_BACKEND_CHANGES'], 'true'), ne(variables['Build.Reason'], 'PullRequest')) + condition: and(succeeded(), eq(variables['BuildJob.HAS_BACKEND_CHANGES'], 'true')) artifact: api # Upload UI Community artifact as build result - publish: $(Build.ArtifactStagingDirectory)/ui-community-$(Build.BuildId).zip displayName: 'Artifact: Publish UI Community' - condition: and(succeeded(), eq(variables['BuildJob.HAS_FRONTEND_CHANGES'], 'true'), ne(variables['Build.Reason'], 'PullRequest')) + condition: and(succeeded(), eq(variables['BuildJob.HAS_FRONTEND_CHANGES'], 'true')) artifact: ui-community # Upload Docs artifact as build result - publish: $(Build.ArtifactStagingDirectory)/docs-$(Build.BuildId).zip displayName: 'Artifact: Publish Docs' - condition: and(succeeded(), eq(variables['BuildJob.HAS_DOCS_CHANGES'], 'true'), ne(variables['Build.Reason'], 'PullRequest')) + condition: and(succeeded(), eq(variables['BuildJob.HAS_DOCS_CHANGES'], 'true')) artifact: docs \ No newline at end of file diff --git a/build-pipeline/core/monorepo-deployment-stage.yml b/build-pipeline/core/monorepo-deployment-stage.yml index 937780a6b..46c0e1bda 100644 --- a/build-pipeline/core/monorepo-deployment-stage.yml +++ b/build-pipeline/core/monorepo-deployment-stage.yml @@ -33,7 +33,7 @@ stages: - stage: ${{parameters.stageName}} displayName: ${{parameters.stageName}} stage dependsOn: Build - condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) + condition: succeeded() jobs: - template: ../../apps/api/deploy-api.yml parameters: From 6ac888080f33219b0e329aa10487592c47238fc2 Mon Sep 17 00:00:00 2001 From: Nick Noce Date: Tue, 6 Jan 2026 10:38:17 -0500 Subject: [PATCH 08/15] fix: quote environment variable assignments in EdgeScan script for proper handling --- build-pipeline/core/monorepo-edgescan-stage.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build-pipeline/core/monorepo-edgescan-stage.yml b/build-pipeline/core/monorepo-edgescan-stage.yml index 9e0d328df..cf423636d 100644 --- a/build-pipeline/core/monorepo-edgescan-stage.yml +++ b/build-pipeline/core/monorepo-edgescan-stage.yml @@ -43,8 +43,8 @@ stages: echo "Triggering EdgeScan for Asset ID: ${{ parameters.esAssetId }}" docker run --rm \ - -e ES_API_TOKEN=$ES_API_TOKEN \ - -e ES_ASSET_ID=${{ parameters.esAssetId }} \ + -e ES_API_TOKEN="$ES_API_TOKEN" \ + -e ES_ASSET_ID="${{ parameters.esAssetId }}" \ -e MAX_RISK_THRESHOLD=3 \ edgescan/cicd-integration:latest --wait --color env: From fbe0281f1cc9d3f8ca6dbe03c0d55c7b6dd34d40 Mon Sep 17 00:00:00 2001 From: Nick Noce Date: Tue, 6 Jan 2026 10:46:07 -0500 Subject: [PATCH 09/15] fix: improve EdgeScan script error message clarity and ensure Docker run command uses tty for better output --- .github/workflows/copilot-setup-steps.yml | 2 +- build-pipeline/core/monorepo-edgescan-stage.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml index 6a313fe0e..f869ab05d 100644 --- a/.github/workflows/copilot-setup-steps.yml +++ b/.github/workflows/copilot-setup-steps.yml @@ -81,7 +81,7 @@ jobs: run: | docker --version docker ps - docker pull edgescan/cicd-integration:latest # Pre-pull to cache the image for faster agent runs + docker pull edgescan/cicd-integration:latest # Ensure Edgescan image is available in this job and verify Docker access - name: Verify required environment variables run: | diff --git a/build-pipeline/core/monorepo-edgescan-stage.yml b/build-pipeline/core/monorepo-edgescan-stage.yml index cf423636d..7f40afc45 100644 --- a/build-pipeline/core/monorepo-edgescan-stage.yml +++ b/build-pipeline/core/monorepo-edgescan-stage.yml @@ -29,7 +29,7 @@ stages: set -euo pipefail if [ -z "$ES_API_TOKEN" ] then - echo "Error: Error: ES_API_TOKEN must be set in the variable group." + echo "Error: ES_API_TOKEN must be set in the variable group." exit 1 fi @@ -42,7 +42,7 @@ stages: echo "Triggering EdgeScan for Asset ID: ${{ parameters.esAssetId }}" - docker run --rm \ + docker run --tty --rm \ -e ES_API_TOKEN="$ES_API_TOKEN" \ -e ES_ASSET_ID="${{ parameters.esAssetId }}" \ -e MAX_RISK_THRESHOLD=3 \ From 04f244d35fec100b74bc8561270be0ff2b6527df Mon Sep 17 00:00:00 2001 From: Nick Noce Date: Tue, 6 Jan 2026 11:44:05 -0500 Subject: [PATCH 10/15] fix: correct syntax error in EdgeScan script condition for ES_API_TOKEN check --- build-pipeline/core/monorepo-edgescan-stage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build-pipeline/core/monorepo-edgescan-stage.yml b/build-pipeline/core/monorepo-edgescan-stage.yml index 7f40afc45..403390d2c 100644 --- a/build-pipeline/core/monorepo-edgescan-stage.yml +++ b/build-pipeline/core/monorepo-edgescan-stage.yml @@ -28,7 +28,7 @@ stages: script: | set -euo pipefail - if [ -z "$ES_API_TOKEN" ] then + if [ -z "$ES_API_TOKEN" ]; then echo "Error: ES_API_TOKEN must be set in the variable group." exit 1 fi From f1dda612ce067a85cf638e97bbdd8e90b647bfb0 Mon Sep 17 00:00:00 2001 From: Nick Noce Date: Tue, 6 Jan 2026 12:25:56 -0500 Subject: [PATCH 11/15] feat: enhance EdgeScan CI/CD integration with caching and improved image handling --- .../core/monorepo-edgescan-stage.yml | 36 +++++++++++++++---- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/build-pipeline/core/monorepo-edgescan-stage.yml b/build-pipeline/core/monorepo-edgescan-stage.yml index 403390d2c..d552f75fe 100644 --- a/build-pipeline/core/monorepo-edgescan-stage.yml +++ b/build-pipeline/core/monorepo-edgescan-stage.yml @@ -21,6 +21,31 @@ stages: pool: vmImage: ${{parameters.vmImageName}} steps: + - task: Cache@2 + displayName: 'Cache EdgeScan Docker Image' + inputs: + key: 'docker | edgescan | latest' + path: $(Pipeline.Workspace)/docker-cache + cacheHitVar: DOCKER_CACHE_HIT + + - task: Bash@3 + displayName: 'Pull or Restore EdgeScan Image' + inputs: + targetType: 'inline' + script: | + set -euo pipefail + mkdir -p $(Pipeline.Workspace)/docker-cache + + if [ "$DOCKER_CACHE_HIT" == "true" ] && [ -f "$(Pipeline.Workspace)/docker-cache/edgescan.tar" ]; then + echo "Restoring EdgeScan image from cache..." + docker load -i $(Pipeline.Workspace)/docker-cache/edgescan.tar + else + echo "Cache miss or missing tarball. Pulling from Docker Hub..." + docker pull edgescan/cicd-integration:latest + echo "Saving image to cache for future runs..." + docker save edgescan/cicd-integration:latest -o $(Pipeline.Workspace)/docker-cache/edgescan.tar + fi + - task: Bash@3 displayName: 'Run EdgeScan Scan' inputs: @@ -37,15 +62,14 @@ stages: echo "Error: ES_ASSET_ID_DEV must be set in the variable group." exit 1 fi - - docker pull edgescan/cicd-integration:latest echo "Triggering EdgeScan for Asset ID: ${{ parameters.esAssetId }}" docker run --tty --rm \ - -e ES_API_TOKEN="$ES_API_TOKEN" \ - -e ES_ASSET_ID="${{ parameters.esAssetId }}" \ - -e MAX_RISK_THRESHOLD=3 \ - edgescan/cicd-integration:latest --wait --color + edgescan/cicd-integration:latest \ + --api-token "$ES_API_TOKEN" \ + --asset-id "${{ parameters.esAssetId }}" \ + --max-risk-threshold 3 \ + --wait --color env: ES_API_TOKEN: $(ES_API_TOKEN) From e1bd717020d64890317f8868fdc43c033dcde0c9 Mon Sep 17 00:00:00 2001 From: Nick Noce Date: Tue, 6 Jan 2026 13:46:34 -0500 Subject: [PATCH 12/15] fix: add --start-scan option to EdgeScan run command for immediate scanning --- build-pipeline/core/monorepo-edgescan-stage.yml | 1 + package.json | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build-pipeline/core/monorepo-edgescan-stage.yml b/build-pipeline/core/monorepo-edgescan-stage.yml index d552f75fe..e2f823e42 100644 --- a/build-pipeline/core/monorepo-edgescan-stage.yml +++ b/build-pipeline/core/monorepo-edgescan-stage.yml @@ -69,6 +69,7 @@ stages: edgescan/cicd-integration:latest \ --api-token "$ES_API_TOKEN" \ --asset-id "${{ parameters.esAssetId }}" \ + --start-scan \ --max-risk-threshold 3 \ --wait --color env: diff --git a/package.json b/package.json index 3aa7b012d..4526dded5 100644 --- a/package.json +++ b/package.json @@ -48,8 +48,7 @@ "snyk:iac:report": "snyk iac test iac/build/**/*.json --org=cellixjs --remote-repo-url=https://github.com/CellixJs/cellixjs --target-reference=main --target-name=cellixjs-iac --report", "analyze": "pnpm -r exec -- pnpm dlx @e18e/cli analyze", "prepare": "husky", - "edgescan:run": "docker run --tty --rm -e ES_API_TOKEN -e ES_ASSET_ID -e MAX_RISK_THRESHOLD=3 edgescan/cicd-integration:latest --wait --color" - }, + "edgescan:run": "docker run --tty --rm edgescan/cicd-integration:latest --api-token $ES_API_TOKEN --asset-id $ES_ASSET_ID --start-scan --max-risk-threshold 3 --wait --color" }, "devDependencies": { "@amiceli/vitest-cucumber": "^5.1.2", "@biomejs/biome": "2.0.0", From b47ce2b6ea4508b2aac7c3fcbf02b99de5863c39 Mon Sep 17 00:00:00 2001 From: Nick Noce Date: Tue, 6 Jan 2026 14:21:44 -0500 Subject: [PATCH 13/15] fix: update build conditions to exclude Pull Requests for artifact preparation and deployment stages --- build-pipeline/core/monorepo-build-stage.yml | 12 ++++++------ build-pipeline/core/monorepo-deployment-stage.yml | 2 +- build-pipeline/core/monorepo-edgescan-stage.yml | 2 +- package.json | 3 ++- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/build-pipeline/core/monorepo-build-stage.yml b/build-pipeline/core/monorepo-build-stage.yml index 9e9e5fe72..c972c790a 100644 --- a/build-pipeline/core/monorepo-build-stage.yml +++ b/build-pipeline/core/monorepo-build-stage.yml @@ -434,7 +434,7 @@ stages: # Deploy API package with production dependencies - task: Bash@3 displayName: 'Artifact: Prepare API' - condition: and(succeeded(), eq(variables['BuildJob.HAS_BACKEND_CHANGES'], 'true')) + condition: and(succeeded(), eq(variables['BuildJob.HAS_BACKEND_CHANGES'], 'true'), ne(variables['Build.Reason'], 'PullRequest')) inputs: targetType: 'inline' script: | @@ -495,7 +495,7 @@ stages: # Package UI Community compiled assets into artifact - task: ArchiveFiles@2 displayName: 'Artifact: Prepare UI Community' - condition: and(succeeded(), eq(variables['BuildJob.HAS_FRONTEND_CHANGES'], 'true')) + condition: and(succeeded(), eq(variables['BuildJob.HAS_FRONTEND_CHANGES'], 'true'), ne(variables['Build.Reason'], 'PullRequest')) inputs: rootFolderOrFile: 'apps/ui-community/dist' includeRootFolder: false @@ -506,7 +506,7 @@ stages: # Package Docs compiled assets into artifact - task: ArchiveFiles@2 displayName: 'Artifact: Prepare Docs' - condition: and(succeeded(), eq(variables['BuildJob.HAS_DOCS_CHANGES'], 'true')) + condition: and(succeeded(), eq(variables['BuildJob.HAS_DOCS_CHANGES'], 'true'), ne(variables['Build.Reason'], 'PullRequest')) inputs: rootFolderOrFile: 'apps/docs/build' includeRootFolder: false @@ -517,17 +517,17 @@ stages: # Upload API artifact as build result - publish: $(Build.ArtifactStagingDirectory)/api-$(Build.BuildId).zip displayName: 'Artifact: Publish API' - condition: and(succeeded(), eq(variables['BuildJob.HAS_BACKEND_CHANGES'], 'true')) + condition: and(succeeded(), eq(variables['BuildJob.HAS_BACKEND_CHANGES'], 'true'), ne(variables['Build.Reason'], 'PullRequest')) artifact: api # Upload UI Community artifact as build result - publish: $(Build.ArtifactStagingDirectory)/ui-community-$(Build.BuildId).zip displayName: 'Artifact: Publish UI Community' - condition: and(succeeded(), eq(variables['BuildJob.HAS_FRONTEND_CHANGES'], 'true')) + condition: and(succeeded(), eq(variables['BuildJob.HAS_FRONTEND_CHANGES'], 'true'), ne(variables['Build.Reason'], 'PullRequest')) artifact: ui-community # Upload Docs artifact as build result - publish: $(Build.ArtifactStagingDirectory)/docs-$(Build.BuildId).zip displayName: 'Artifact: Publish Docs' - condition: and(succeeded(), eq(variables['BuildJob.HAS_DOCS_CHANGES'], 'true')) + condition: and(succeeded(), eq(variables['BuildJob.HAS_DOCS_CHANGES'], 'true'), ne(variables['Build.Reason'], 'PullRequest')) artifact: docs \ No newline at end of file diff --git a/build-pipeline/core/monorepo-deployment-stage.yml b/build-pipeline/core/monorepo-deployment-stage.yml index 46c0e1bda..937780a6b 100644 --- a/build-pipeline/core/monorepo-deployment-stage.yml +++ b/build-pipeline/core/monorepo-deployment-stage.yml @@ -33,7 +33,7 @@ stages: - stage: ${{parameters.stageName}} displayName: ${{parameters.stageName}} stage dependsOn: Build - condition: succeeded() + condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) jobs: - template: ../../apps/api/deploy-api.yml parameters: diff --git a/build-pipeline/core/monorepo-edgescan-stage.yml b/build-pipeline/core/monorepo-edgescan-stage.yml index e2f823e42..0e5573952 100644 --- a/build-pipeline/core/monorepo-edgescan-stage.yml +++ b/build-pipeline/core/monorepo-edgescan-stage.yml @@ -14,7 +14,7 @@ stages: - stage: ${{parameters.stageName}} displayName: 'EdgeScan Security Scan' dependsOn: ${{parameters.dependsOn}} - condition: succeeded() + condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) jobs: - job: EdgeScan displayName: 'EdgeScan CI/CD Integration' diff --git a/package.json b/package.json index 4526dded5..7f4bda89b 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,8 @@ "snyk:iac:report": "snyk iac test iac/build/**/*.json --org=cellixjs --remote-repo-url=https://github.com/CellixJs/cellixjs --target-reference=main --target-name=cellixjs-iac --report", "analyze": "pnpm -r exec -- pnpm dlx @e18e/cli analyze", "prepare": "husky", - "edgescan:run": "docker run --tty --rm edgescan/cicd-integration:latest --api-token $ES_API_TOKEN --asset-id $ES_ASSET_ID --start-scan --max-risk-threshold 3 --wait --color" }, + "edgescan:run": "docker run --tty --rm edgescan/cicd-integration:latest --api-token $ES_API_TOKEN --asset-id $ES_ASSET_ID --start-scan --max-risk-threshold 3 --wait --color" + }, "devDependencies": { "@amiceli/vitest-cucumber": "^5.1.2", "@biomejs/biome": "2.0.0", From 8e0693995928d1a2ef1efd5187c16b615cc42f35 Mon Sep 17 00:00:00 2001 From: Nick Noce Date: Tue, 6 Jan 2026 14:59:17 -0500 Subject: [PATCH 14/15] fix: update caching key to include monthly refresh for EdgeScan Docker image --- build-pipeline/core/monorepo-edgescan-stage.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/build-pipeline/core/monorepo-edgescan-stage.yml b/build-pipeline/core/monorepo-edgescan-stage.yml index 0e5573952..7e7dab527 100644 --- a/build-pipeline/core/monorepo-edgescan-stage.yml +++ b/build-pipeline/core/monorepo-edgescan-stage.yml @@ -18,13 +18,16 @@ stages: jobs: - job: EdgeScan displayName: 'EdgeScan CI/CD Integration' + variables: + # Generates a monthly key like "2026-01" to ensure the image is refreshed monthly + cacheMonth: $[format('{0:yyyy-MM}', pipeline.startTime)] pool: vmImage: ${{parameters.vmImageName}} steps: - task: Cache@2 displayName: 'Cache EdgeScan Docker Image' inputs: - key: 'docker | edgescan | latest' + key: 'docker | edgescan | latest | $(cacheMonth)' path: $(Pipeline.Workspace)/docker-cache cacheHitVar: DOCKER_CACHE_HIT From e540ec0c4501baea9ba47dd9d065336d65114293 Mon Sep 17 00:00:00 2001 From: Nick Noce Date: Wed, 7 Jan 2026 09:50:19 -0500 Subject: [PATCH 15/15] fix: guard docker cache hit with default according to sourcery suggestion --- build-pipeline/core/monorepo-edgescan-stage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build-pipeline/core/monorepo-edgescan-stage.yml b/build-pipeline/core/monorepo-edgescan-stage.yml index 7e7dab527..d16e5b315 100644 --- a/build-pipeline/core/monorepo-edgescan-stage.yml +++ b/build-pipeline/core/monorepo-edgescan-stage.yml @@ -39,7 +39,7 @@ stages: set -euo pipefail mkdir -p $(Pipeline.Workspace)/docker-cache - if [ "$DOCKER_CACHE_HIT" == "true" ] && [ -f "$(Pipeline.Workspace)/docker-cache/edgescan.tar" ]; then + if [ "${DOCKER_CACHE_HIT:-}" = "true" ] && [ -f "$(Pipeline.Workspace)/docker-cache/edgescan.tar" ]; then echo "Restoring EdgeScan image from cache..." docker load -i $(Pipeline.Workspace)/docker-cache/edgescan.tar else