From ac69ba227b4d59fa9c30bcba1c362f113057f0be Mon Sep 17 00:00:00 2001 From: wenyt Date: Thu, 10 Sep 2026 15:22:40 +0800 Subject: [PATCH 1/5] build: validate dependency updates through CFS --- .azure-pipelines/ci.yml | 47 +++++++++++++++++++++++++++++++++++++++++ .github/dependabot.yml | 12 ----------- 2 files changed, 47 insertions(+), 12 deletions(-) diff --git a/.azure-pipelines/ci.yml b/.azure-pipelines/ci.yml index cc0b039c..f1401be9 100644 --- a/.azure-pipelines/ci.yml +++ b/.azure-pipelines/ci.yml @@ -17,6 +17,26 @@ trigger: branches: include: - main +pr: + branches: + include: + - main + paths: + include: + - package.json + - package-lock.json + - scripts/buildJdtlsExt.js + - jdtls.ext/pom.xml + - jdtls.ext/**/pom.xml + - jdtls.ext/com.microsoft.jdtls.ext.target/com.microsoft.jdtls.ext.tp.target + - jdtls.ext/.mvn/wrapper/maven-wrapper.properties + - jdtls.ext/mvnw + - jdtls.ext/mvnw.cmd + - .azure-pipelines/ci.yml + - .azure-pipelines/npm-cfs.yml + - .azure-pipelines/npm-cfs-variables.yml + - .azure-pipelines/maven-cfs-variables.yml + - .azure-pipelines/cfs-settings.xml extends: template: v1/1ES.Unofficial.PipelineTemplate.yml@1esPipelines parameters: @@ -34,8 +54,35 @@ extends: stages: - stage: Build jobs: + - job: CFSValidation + displayName: Validate dependencies from CFS + condition: eq(variables['Build.Reason'], 'PullRequest') + steps: + - checkout: self + fetchTags: false + - task: JavaToolInstaller@0 + displayName: Use Java 21 + inputs: + versionSpec: "21" + jdkArchitectureOption: x64 + jdkSourceOption: PreInstalled + - task: NodeTool@0 + displayName: Use Node 20.x + inputs: + versionSpec: 20.x + - template: /.azure-pipelines/npm-cfs.yml@self + - script: npm ci --ignore-scripts --prefer-online --cache "$(Agent.TempDirectory)/npm-cache" + displayName: Validate npm dependencies from CFS + - script: npm run build-server + displayName: Validate Maven dependencies from CFS + env: + SYSTEM_ACCESSTOKEN: $(System.AccessToken) + MVNW_PASSWORD: $(System.AccessToken) + MAVEN_USER_HOME: $(Agent.TempDirectory)/m2 + MAVEN_ARGS: -s $(Build.SourcesDirectory)/.azure-pipelines/cfs-settings.xml -Dmaven.repo.local=$(Agent.TempDirectory)/m2/repository -U - job: Job_1 displayName: CI + condition: ne(variables['Build.Reason'], 'PullRequest') templateContext: outputs: - output: pipelineArtifact diff --git a/.github/dependabot.yml b/.github/dependabot.yml index a4a0cf03..b81750ab 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,18 +5,6 @@ version: 2 updates: - - package-ecosystem: "npm" # See documentation for possible values - directory: "/" # Location of package manifests - schedule: - interval: "daily" - # CI restores packages from the Central Feed Service, which withholds - # upstream versions until they are roughly a week old (measured at ~6.8 - # days; both the packument entry and the tarball return 404 before then). - # Dependabot's built-in cooldown is only 3 days, so bumps otherwise land in - # a window where the feed 404s and the build fails. 10 days leaves margin - # in case the feed's ingestion lag drifts. - cooldown: - default-days: 10 - package-ecosystem: "github-actions" directory: "/" groups: From c127719b6e6a472d84f03013d6f1850ef12ca646 Mon Sep 17 00:00:00 2001 From: wenyt Date: Thu, 10 Sep 2026 15:48:34 +0800 Subject: [PATCH 2/5] build: include OSGi manifests in CFS validation --- .azure-pipelines/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.azure-pipelines/ci.yml b/.azure-pipelines/ci.yml index f1401be9..1eefb7f2 100644 --- a/.azure-pipelines/ci.yml +++ b/.azure-pipelines/ci.yml @@ -28,6 +28,7 @@ pr: - scripts/buildJdtlsExt.js - jdtls.ext/pom.xml - jdtls.ext/**/pom.xml + - jdtls.ext/**/META-INF/MANIFEST.MF - jdtls.ext/com.microsoft.jdtls.ext.target/com.microsoft.jdtls.ext.tp.target - jdtls.ext/.mvn/wrapper/maven-wrapper.properties - jdtls.ext/mvnw From bf62ae6aa60e6a3b4bc0d7dcf12931cb674196a2 Mon Sep 17 00:00:00 2001 From: wenyt Date: Thu, 10 Sep 2026 16:33:02 +0800 Subject: [PATCH 3/5] build: restrict CFS validation credentials --- .azure-pipelines/ci.yml | 6 ++++-- .azure-pipelines/npm-cfs.yml | 24 ++++++++++++++++++++---- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/.azure-pipelines/ci.yml b/.azure-pipelines/ci.yml index 1eefb7f2..689235c0 100644 --- a/.azure-pipelines/ci.yml +++ b/.azure-pipelines/ci.yml @@ -72,13 +72,15 @@ extends: inputs: versionSpec: 20.x - template: /.azure-pipelines/npm-cfs.yml@self + parameters: + useReadOnlyCredential: true - script: npm ci --ignore-scripts --prefer-online --cache "$(Agent.TempDirectory)/npm-cache" displayName: Validate npm dependencies from CFS - script: npm run build-server displayName: Validate Maven dependencies from CFS env: - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - MVNW_PASSWORD: $(System.AccessToken) + SYSTEM_ACCESSTOKEN: $(CFS_READ_TOKEN) + MVNW_PASSWORD: $(CFS_READ_TOKEN) MAVEN_USER_HOME: $(Agent.TempDirectory)/m2 MAVEN_ARGS: -s $(Build.SourcesDirectory)/.azure-pipelines/cfs-settings.xml -Dmaven.repo.local=$(Agent.TempDirectory)/m2/repository -U - job: Job_1 diff --git a/.azure-pipelines/npm-cfs.yml b/.azure-pipelines/npm-cfs.yml index c7445e78..f91db92a 100644 --- a/.azure-pipelines/npm-cfs.yml +++ b/.azure-pipelines/npm-cfs.yml @@ -36,6 +36,11 @@ # pipelines is the 1ES extends template in another repository, so the unqualified # form is looked up in 1ESPipelineTemplates and fails YAML compilation. +parameters: + - name: useReadOnlyCredential + type: boolean + default: false + steps: - script: npm config set registry $(npm_config_registry) --location=user --userconfig="$(npm_config_userconfig)" displayName: Configure CFS npm registry @@ -44,10 +49,21 @@ steps: # registry it finds in the file above. `always-auth` is deliberately not written: # it is not read by this task and is rejected outright by the npm 10 shipped with # Node 20. - - task: NpmAuthenticate@0 - displayName: Authenticate to CFS feed - inputs: - workingFile: $(npm_config_userconfig) + - ${{ if not(parameters.useReadOnlyCredential) }}: + - task: NpmAuthenticate@0 + displayName: Authenticate to CFS feed + inputs: + workingFile: $(npm_config_userconfig) + + # PR validation runs repository-controlled code, so it must not receive the + # project-scoped System.AccessToken used by trusted branch builds. Its pipeline + # definition supplies a secret PAT restricted to Packaging Read. + - ${{ if parameters.useReadOnlyCredential }}: + - script: >- + node -e "const fs=require('fs');const r=new URL(process.env.npm_config_registry);const key='//'+r.host+r.pathname.replace(/\/?$/,'/');fs.appendFileSync(process.env.npm_config_userconfig,key+':_authToken='+process.env.CFS_READ_TOKEN+'\n');" + displayName: Authenticate to CFS feed with read-only credential + env: + CFS_READ_TOKEN: $(CFS_READ_TOKEN) # Restore silently falling back to the public registry is the failure mode this # whole template exists to prevent, and it leaves no trace in the build log, so it From c0f184455bb9f4c410ada974c86992125968fe7b Mon Sep 17 00:00:00 2001 From: wenyt Date: Thu, 10 Sep 2026 16:42:36 +0800 Subject: [PATCH 4/5] build: map CFS npm environment variables --- .azure-pipelines/npm-cfs.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.azure-pipelines/npm-cfs.yml b/.azure-pipelines/npm-cfs.yml index f91db92a..d9aba982 100644 --- a/.azure-pipelines/npm-cfs.yml +++ b/.azure-pipelines/npm-cfs.yml @@ -63,6 +63,8 @@ steps: node -e "const fs=require('fs');const r=new URL(process.env.npm_config_registry);const key='//'+r.host+r.pathname.replace(/\/?$/,'/');fs.appendFileSync(process.env.npm_config_userconfig,key+':_authToken='+process.env.CFS_READ_TOKEN+'\n');" displayName: Authenticate to CFS feed with read-only credential env: + npm_config_registry: $(npm_config_registry) + npm_config_userconfig: $(npm_config_userconfig) CFS_READ_TOKEN: $(CFS_READ_TOKEN) # Restore silently falling back to the public registry is the failure mode this From 57f2ef302529712548834f3ee6232f131c9e31dc Mon Sep 17 00:00:00 2001 From: wenyt Date: Thu, 10 Sep 2026 18:10:51 +0800 Subject: [PATCH 5/5] build: use pipeline credentials for CFS validation --- .azure-pipelines/ci.yml | 6 ++---- .azure-pipelines/npm-cfs.yml | 26 ++++---------------------- 2 files changed, 6 insertions(+), 26 deletions(-) diff --git a/.azure-pipelines/ci.yml b/.azure-pipelines/ci.yml index 689235c0..1eefb7f2 100644 --- a/.azure-pipelines/ci.yml +++ b/.azure-pipelines/ci.yml @@ -72,15 +72,13 @@ extends: inputs: versionSpec: 20.x - template: /.azure-pipelines/npm-cfs.yml@self - parameters: - useReadOnlyCredential: true - script: npm ci --ignore-scripts --prefer-online --cache "$(Agent.TempDirectory)/npm-cache" displayName: Validate npm dependencies from CFS - script: npm run build-server displayName: Validate Maven dependencies from CFS env: - SYSTEM_ACCESSTOKEN: $(CFS_READ_TOKEN) - MVNW_PASSWORD: $(CFS_READ_TOKEN) + SYSTEM_ACCESSTOKEN: $(System.AccessToken) + MVNW_PASSWORD: $(System.AccessToken) MAVEN_USER_HOME: $(Agent.TempDirectory)/m2 MAVEN_ARGS: -s $(Build.SourcesDirectory)/.azure-pipelines/cfs-settings.xml -Dmaven.repo.local=$(Agent.TempDirectory)/m2/repository -U - job: Job_1 diff --git a/.azure-pipelines/npm-cfs.yml b/.azure-pipelines/npm-cfs.yml index d9aba982..c7445e78 100644 --- a/.azure-pipelines/npm-cfs.yml +++ b/.azure-pipelines/npm-cfs.yml @@ -36,11 +36,6 @@ # pipelines is the 1ES extends template in another repository, so the unqualified # form is looked up in 1ESPipelineTemplates and fails YAML compilation. -parameters: - - name: useReadOnlyCredential - type: boolean - default: false - steps: - script: npm config set registry $(npm_config_registry) --location=user --userconfig="$(npm_config_userconfig)" displayName: Configure CFS npm registry @@ -49,23 +44,10 @@ steps: # registry it finds in the file above. `always-auth` is deliberately not written: # it is not read by this task and is rejected outright by the npm 10 shipped with # Node 20. - - ${{ if not(parameters.useReadOnlyCredential) }}: - - task: NpmAuthenticate@0 - displayName: Authenticate to CFS feed - inputs: - workingFile: $(npm_config_userconfig) - - # PR validation runs repository-controlled code, so it must not receive the - # project-scoped System.AccessToken used by trusted branch builds. Its pipeline - # definition supplies a secret PAT restricted to Packaging Read. - - ${{ if parameters.useReadOnlyCredential }}: - - script: >- - node -e "const fs=require('fs');const r=new URL(process.env.npm_config_registry);const key='//'+r.host+r.pathname.replace(/\/?$/,'/');fs.appendFileSync(process.env.npm_config_userconfig,key+':_authToken='+process.env.CFS_READ_TOKEN+'\n');" - displayName: Authenticate to CFS feed with read-only credential - env: - npm_config_registry: $(npm_config_registry) - npm_config_userconfig: $(npm_config_userconfig) - CFS_READ_TOKEN: $(CFS_READ_TOKEN) + - task: NpmAuthenticate@0 + displayName: Authenticate to CFS feed + inputs: + workingFile: $(npm_config_userconfig) # Restore silently falling back to the public registry is the failure mode this # whole template exists to prevent, and it leaves no trace in the build log, so it