From 9a256ae49af361467d79c96bfd7cfb6bd340c5e9 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Tue, 29 Sep 2026 18:07:55 -0700 Subject: [PATCH 1/7] Prototype MicroBuild MSBuild signing without .NET Core 3.1 DDSignFiles requires an out-of-support runtime. Using the MicroBuild MSBuild interface could avoid that dependency, pending verification in an official signing pipeline. --- Herebyfile.mjs | 52 +++++++++++++++++---- tools/pipelines/typescript-build.yml | 8 ---- tools/pipelines/vscode-typescript-build.yml | 5 -- tools/signing/NuGet.config | 7 +++ tools/signing/Sign.csproj | 24 ++++++++++ 5 files changed, 73 insertions(+), 23 deletions(-) create mode 100644 tools/signing/NuGet.config create mode 100644 tools/signing/Sign.csproj diff --git a/Herebyfile.mjs b/Herebyfile.mjs index 3298ed9ec6d83..00c936a3c85df 100644 --- a/Herebyfile.mjs +++ b/Herebyfile.mjs @@ -1603,6 +1603,14 @@ function runCleanSignTempDirectory() { let signCount = 0; +/** + * @param {string} value + */ +function escapeMsbuildXml(value) { + return value.replaceAll("%", "%25").replaceAll("$", "%24").replaceAll("@", "%40").replaceAll(";", "%3B") + .replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """); +} + /** * @typedef {{ * SignFileRecordList: { @@ -1615,8 +1623,7 @@ let signCount = 0; * @param {DDSignFileList} filelist */ async function sign(filelist, unchangedOutputOkay = false) { - let data = JSON.stringify(filelist, undefined, 4); - console.log("filelist:", data); + console.log("filelist:", JSON.stringify(filelist, undefined, 4)); if (!process.env.MBSIGN_APPFOLDER) { console.log(styleText("yellow", "Faking signing because MBSIGN_APPFOLDER is not set.")); @@ -1659,6 +1666,7 @@ async function sign(filelist, unchangedOutputOkay = false) { } const signingWorkaround = true; + let signingFilelist = filelist; /** @type {{ source: string; target: string }[]} */ const signingWorkaroundFiles = []; @@ -1699,8 +1707,8 @@ async function sign(filelist, unchangedOutputOkay = false) { }), }; - data = JSON.stringify(newFileList, undefined, 4); - console.log("new filelist:", data); + signingFilelist = newFileList; + console.log("new filelist:", JSON.stringify(signingFilelist, undefined, 4)); } /** @type {Map} */ @@ -1724,16 +1732,40 @@ async function sign(filelist, unchangedOutputOkay = false) { } const tmp = await getSignTempDir(); - const filelistPath = path.resolve(tmp, `signing-filelist-${signCount++}.json`); - await fs.promises.writeFile(filelistPath, data); + const propsPath = path.resolve(tmp, `signing-items-${signCount++}.props`); + const signingItems = signingFilelist.SignFileRecordList.flatMap(record => record.SignFileList.map(file => ({ path: file.SrcPath, cert: record.Certs, macAppName: record.MacAppName }))); + const items = signingItems.map(({ path: filePath, cert, macAppName }) => + ` + ${escapeMsbuildXml(cert)} + None${ + macAppName ? ` + ${escapeMsbuildXml(macAppName)}` : "" + } + ` + ).join("\n"); + await fs.promises.writeFile( + propsPath, + ` + +${items} + + +`, + ); try { - const dll = path.join(process.env.MBSIGN_APPFOLDER, "DDSignFiles.dll"); - const filelistFlag = `/filelist:${filelistPath}`; - await run("dotnet", [dll, "--", filelistFlag]); + await run("dotnet", [ + "build", + path.resolve("tools/signing/Sign.csproj"), + "--target:AfterBuild", + "-p:SignType=real", + `-p:SignFilesDir=${path.resolve("built")}`, + `-p:FilesToSignPropsFile=${propsPath}`, + `-p:MicroBuildOverridePluginDirectory=${path.dirname(path.dirname(process.env.MBSIGN_APPFOLDER))}`, + ]); } finally { - await fs.promises.unlink(filelistPath); + await fs.promises.unlink(propsPath); } if (signingWorkaround) { diff --git a/tools/pipelines/typescript-build.yml b/tools/pipelines/typescript-build.yml index 84dc67d9af0ae..5accfe0711cd7 100755 --- a/tools/pipelines/typescript-build.yml +++ b/tools/pipelines/typescript-build.yml @@ -70,20 +70,12 @@ extends: condition: eq(variables['Build.Reason'], 'Schedule') # This is copied from https://dev.azure.com/devdiv/1ESPipelineTemplates/_git/MicroBuildTemplate?path=/azure-pipelines/Jobs/Job.yml - # With the difference that we install .NET Core becuase DDSignFiles needs it. - task: NuGetAuthenticate@1 displayName: '🔩 NuGet Authenticate' - task: UsePythonVersion@0 displayName: 'Use Python 3.11' inputs: versionSpec: 3.11 - # This is old, but DDSignFiles is built with it. - # Copying https://github.com/microsoft/vscode-gradle/blob/2f60b4483ef15aa9b196e008939610cdeab60029/.azure-pipelines/vscode-gradle-nightly.yml#L50 - - task: UseDotNet@2 - displayName: 'Use .NET Core 3.1.x' - inputs: - packageType: 'sdk' - version: '3.1.x' # Needed for ESRP. https://dev.azure.com/devdiv/DevDiv/_wiki/wikis/DevDiv.wiki/46279/Real-signing-with-PME-Enforcement - task: UseDotNet@2 displayName: Use .NET Core sdk 8.0.x diff --git a/tools/pipelines/vscode-typescript-build.yml b/tools/pipelines/vscode-typescript-build.yml index a8eb641f4f982..7c1feaf66606c 100644 --- a/tools/pipelines/vscode-typescript-build.yml +++ b/tools/pipelines/vscode-typescript-build.yml @@ -101,11 +101,6 @@ extends: displayName: Use Python 3.11 inputs: versionSpec: 3.11 - - task: UseDotNet@2 - displayName: Use .NET Core 3.1.x - inputs: - packageType: sdk - version: 3.1.x - task: UseDotNet@2 displayName: Use .NET Core SDK 8.0.x inputs: diff --git a/tools/signing/NuGet.config b/tools/signing/NuGet.config new file mode 100644 index 0000000000000..fe93ac64ee1d6 --- /dev/null +++ b/tools/signing/NuGet.config @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tools/signing/Sign.csproj b/tools/signing/Sign.csproj new file mode 100644 index 0000000000000..741da3975efd9 --- /dev/null +++ b/tools/signing/Sign.csproj @@ -0,0 +1,24 @@ + + + net8.0 + false + + + + + + + + + + + + + $([MSBuild]::NormalizeDirectory('$(SignFilesDir)')) + + + + + + + From cb7b5474847db0aaa24dfa671c0f4d7f50071eda Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Tue, 29 Sep 2026 21:12:17 -0700 Subject: [PATCH 2/7] Let MicroBuild templates manage signing prerequisites Avoid duplicating signing setup that the official template already owns, so prerequisite and service connection changes are maintained centrally. Keep explicit .NET setup to avoid relying on the agent image, and preserve release validation before signing setup. --- tools/pipelines/typescript-build.yml | 50 +++----- tools/pipelines/vscode-typescript-build.yml | 121 ++++++++++---------- 2 files changed, 77 insertions(+), 94 deletions(-) diff --git a/tools/pipelines/typescript-build.yml b/tools/pipelines/typescript-build.yml index 5accfe0711cd7..1846773d2c10f 100755 --- a/tools/pipelines/typescript-build.yml +++ b/tools/pipelines/typescript-build.yml @@ -54,8 +54,27 @@ extends: - job: Build displayName: Build and Sign timeoutInMinutes: 180 + pool: + name: AzurePipelines-EO + image: 1ESPT-Ubuntu22.04 + os: linux templateContext: + mb: + signing: + enabled: true + signWithProd: true + signType: real + zipSources: false + mbpresteps: + - bash: echo "##vso[build.addbuildtag]Build.Reason.Schedule" + displayName: 'Set build tag "Build.Reason.Schedule"' + condition: eq(variables['Build.Reason'], 'Schedule') + # Needed for ESRP. https://dev.azure.com/devdiv/DevDiv/_wiki/wikis/DevDiv.wiki/46279/Real-signing-with-PME-Enforcement + - task: UseDotNet@2 + displayName: Use .NET Core sdk 8.0.x + inputs: + version: 8.0.x outputs: - output: pipelineArtifact targetPath: $(Build.ArtifactStagingDirectory)/npm @@ -65,37 +84,6 @@ extends: artifactName: vsix steps: - - bash: echo "##vso[build.addbuildtag]Build.Reason.Schedule" - displayName: 'Set build tag "Build.Reason.Schedule"' - condition: eq(variables['Build.Reason'], 'Schedule') - - # This is copied from https://dev.azure.com/devdiv/1ESPipelineTemplates/_git/MicroBuildTemplate?path=/azure-pipelines/Jobs/Job.yml - - task: NuGetAuthenticate@1 - displayName: '🔩 NuGet Authenticate' - - task: UsePythonVersion@0 - displayName: 'Use Python 3.11' - inputs: - versionSpec: 3.11 - # Needed for ESRP. https://dev.azure.com/devdiv/DevDiv/_wiki/wikis/DevDiv.wiki/46279/Real-signing-with-PME-Enforcement - - task: UseDotNet@2 - displayName: Use .NET Core sdk 8.0.x - inputs: - version: 8.0.x - # https://dev.azure.com/devdiv/DevDiv/_wiki/wikis/DevDiv.wiki/12267/ESRP-Signing-in-Mac-or-Linux-Pipelines - # TODO: switch to the template's signing, now that DDSignFiles should work. - - task: MicroBuildSigningPlugin@4 - displayName: '🔩 Install Signing Plugin' - inputs: - signType: real - # azureSubscription AKA ConnectedServiceName - azureSubscription: 'MicroBuild Signing Task (DevDiv)' - # From "nonwindowspmeservicename" in https://dev.azure.com/devdiv/1ESPipelineTemplates/_git/MicroBuildTemplate?path=/azure-pipelines/Stages/Stage.yml - ConnectedPMEServiceName: beb8cb23-b303-4c95-ab26-9e44bc958d39 - # We do this ourselves. - zipSources: false - env: - MicroBuildOutputFolderOverride: '$(Agent.TempDirectory)' - - checkout: self clean: true submodules: false diff --git a/tools/pipelines/vscode-typescript-build.yml b/tools/pipelines/vscode-typescript-build.yml index 7c1feaf66606c..51a2e9d394095 100644 --- a/tools/pipelines/vscode-typescript-build.yml +++ b/tools/pipelines/vscode-typescript-build.yml @@ -44,77 +44,72 @@ extends: - job: Build displayName: Build and sign vscode-typescript timeoutInMinutes: 90 + pool: + name: AzurePipelines-EO + image: 1ESPT-Ubuntu22.04 + os: linux templateContext: + mb: + signing: + enabled: true + signWithProd: true + signType: real + zipSources: false + mbpresteps: + - checkout: self + clean: true + submodules: false + fetchDepth: 0 + fetchFilter: blob:none + fetchTags: false + + - bash: | + set -euo pipefail + git fetch origin main --no-tags + if ! git merge-base --is-ancestor "$BUILD_SOURCEVERSION" refs/remotes/origin/main; then + echo "Release tags must point to commits already merged into main." >&2 + exit 1 + fi + + tag="${BUILD_SOURCEBRANCH#refs/tags/}" + case "$tag" in + vscode-typescript/v*) ;; + *) + echo "Expected a vscode-typescript/v* tag, got $BUILD_SOURCEBRANCH." >&2 + exit 1 + ;; + esac + + tagVersion="${tag#vscode-typescript/v}" + packageVersion="$(jq -r '.version' packages/vscode-typescript/package.json)" + lockVersion="$(jq -r '.packages["packages/vscode-typescript"].version' package-lock.json)" + if [ "$tagVersion" != "$packageVersion" ]; then + echo "Tag version $tagVersion does not match package version $packageVersion." >&2 + exit 1 + fi + if [ "$packageVersion" != "$lockVersion" ]; then + echo "package.json version $packageVersion does not match package-lock.json version $lockVersion." >&2 + exit 1 + fi + if ! [[ "$packageVersion" =~ ^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$ ]]; then + echo "Extension version must be a stable three-component version." >&2 + exit 1 + fi + + echo "##vso[build.updatebuildnumber]vscode-typescript-$packageVersion" + displayName: Validate release tag + + - task: UseDotNet@2 + displayName: Use .NET Core SDK 8.0.x + inputs: + version: 8.0.x outputs: - output: pipelineArtifact targetPath: $(Build.ArtifactStagingDirectory)/vsix artifactName: vsix steps: - - checkout: self - clean: true - submodules: false - fetchDepth: 0 - fetchFilter: blob:none - fetchTags: false - - - bash: | - set -euo pipefail - git fetch origin main --no-tags - if ! git merge-base --is-ancestor "$BUILD_SOURCEVERSION" refs/remotes/origin/main; then - echo "Release tags must point to commits already merged into main." >&2 - exit 1 - fi - - tag="${BUILD_SOURCEBRANCH#refs/tags/}" - case "$tag" in - vscode-typescript/v*) ;; - *) - echo "Expected a vscode-typescript/v* tag, got $BUILD_SOURCEBRANCH." >&2 - exit 1 - ;; - esac - - tagVersion="${tag#vscode-typescript/v}" - packageVersion="$(jq -r '.version' packages/vscode-typescript/package.json)" - lockVersion="$(jq -r '.packages["packages/vscode-typescript"].version' package-lock.json)" - if [ "$tagVersion" != "$packageVersion" ]; then - echo "Tag version $tagVersion does not match package version $packageVersion." >&2 - exit 1 - fi - if [ "$packageVersion" != "$lockVersion" ]; then - echo "package.json version $packageVersion does not match package-lock.json version $lockVersion." >&2 - exit 1 - fi - if ! [[ "$packageVersion" =~ ^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$ ]]; then - echo "Extension version must be a stable three-component version." >&2 - exit 1 - fi - - echo "##vso[build.updatebuildnumber]vscode-typescript-$packageVersion" - displayName: Validate release tag - - - task: NuGetAuthenticate@1 - displayName: '🔩 NuGet Authenticate' - - task: UsePythonVersion@0 - displayName: Use Python 3.11 - inputs: - versionSpec: 3.11 - - task: UseDotNet@2 - displayName: Use .NET Core SDK 8.0.x - inputs: - version: 8.0.x - - task: MicroBuildSigningPlugin@4 - displayName: '🔩 Install Signing Plugin' - inputs: - signType: real - azureSubscription: MicroBuild Signing Task (DevDiv) - ConnectedPMEServiceName: beb8cb23-b303-4c95-ab26-9e44bc958d39 - zipSources: false - env: - MicroBuildOutputFolderOverride: $(Agent.TempDirectory) - - template: /tools/pipelines/steps/setup-node-npm-ci.yml@self - bash: npm test -w native-preview From 93f8a6abc803a1b0eae5b9fb078c4ff252da224a Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Tue, 29 Sep 2026 21:15:02 -0700 Subject: [PATCH 3/7] Show normal verbosity for MSBuild signing Expose signing progress in pipeline logs instead of leaving long silent intervals while waiting for signing to complete. --- Herebyfile.mjs | 1 + 1 file changed, 1 insertion(+) diff --git a/Herebyfile.mjs b/Herebyfile.mjs index 00c936a3c85df..86a20b10ffa77 100644 --- a/Herebyfile.mjs +++ b/Herebyfile.mjs @@ -1758,6 +1758,7 @@ ${items} "build", path.resolve("tools/signing/Sign.csproj"), "--target:AfterBuild", + "--verbosity:normal", "-p:SignType=real", `-p:SignFilesDir=${path.resolve("built")}`, `-p:FilesToSignPropsFile=${propsPath}`, From cc762315bf102abc04f81dab876af4cf7316704f Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Tue, 29 Sep 2026 21:21:51 -0700 Subject: [PATCH 4/7] Assert supported values in signing XML Signing uses controlled filenames and certificate identifiers. Reject unexpected characters explicitly rather than maintaining general-purpose XML and MSBuild escaping for inputs this pipeline does not need. --- Herebyfile.mjs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Herebyfile.mjs b/Herebyfile.mjs index 86a20b10ffa77..d88801e8caade 100644 --- a/Herebyfile.mjs +++ b/Herebyfile.mjs @@ -1606,9 +1606,9 @@ let signCount = 0; /** * @param {string} value */ -function escapeMsbuildXml(value) { - return value.replaceAll("%", "%25").replaceAll("$", "%24").replaceAll("@", "%40").replaceAll(";", "%3B") - .replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """); +function assertMsbuildXmlValue(value) { + assert(value.length > 0 && !/[^\w./\\: -]/.test(value), `Unsupported MSBuild XML value: ${JSON.stringify(value)}`); + return value; } /** @@ -1735,11 +1735,11 @@ async function sign(filelist, unchangedOutputOkay = false) { const propsPath = path.resolve(tmp, `signing-items-${signCount++}.props`); const signingItems = signingFilelist.SignFileRecordList.flatMap(record => record.SignFileList.map(file => ({ path: file.SrcPath, cert: record.Certs, macAppName: record.MacAppName }))); const items = signingItems.map(({ path: filePath, cert, macAppName }) => - ` - ${escapeMsbuildXml(cert)} + ` + ${assertMsbuildXmlValue(cert)} None${ macAppName ? ` - ${escapeMsbuildXml(macAppName)}` : "" + ${assertMsbuildXmlValue(macAppName)}` : "" } ` ).join("\n"); From 922e2aef3359c0bfce64d87ce2032d886fce317c Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Tue, 29 Sep 2026 21:30:00 -0700 Subject: [PATCH 5/7] Keep extension release validation in regular steps Release-tag validation must precede the build and signing commands, but need not precede signing plugin installation. Reserve MicroBuild presteps for .NET setup rather than coupling release validation to plugin setup. --- tools/pipelines/vscode-typescript-build.yml | 86 ++++++++++----------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/tools/pipelines/vscode-typescript-build.yml b/tools/pipelines/vscode-typescript-build.yml index 51a2e9d394095..6266b4967db33 100644 --- a/tools/pipelines/vscode-typescript-build.yml +++ b/tools/pipelines/vscode-typescript-build.yml @@ -57,49 +57,6 @@ extends: signType: real zipSources: false mbpresteps: - - checkout: self - clean: true - submodules: false - fetchDepth: 0 - fetchFilter: blob:none - fetchTags: false - - - bash: | - set -euo pipefail - git fetch origin main --no-tags - if ! git merge-base --is-ancestor "$BUILD_SOURCEVERSION" refs/remotes/origin/main; then - echo "Release tags must point to commits already merged into main." >&2 - exit 1 - fi - - tag="${BUILD_SOURCEBRANCH#refs/tags/}" - case "$tag" in - vscode-typescript/v*) ;; - *) - echo "Expected a vscode-typescript/v* tag, got $BUILD_SOURCEBRANCH." >&2 - exit 1 - ;; - esac - - tagVersion="${tag#vscode-typescript/v}" - packageVersion="$(jq -r '.version' packages/vscode-typescript/package.json)" - lockVersion="$(jq -r '.packages["packages/vscode-typescript"].version' package-lock.json)" - if [ "$tagVersion" != "$packageVersion" ]; then - echo "Tag version $tagVersion does not match package version $packageVersion." >&2 - exit 1 - fi - if [ "$packageVersion" != "$lockVersion" ]; then - echo "package.json version $packageVersion does not match package-lock.json version $lockVersion." >&2 - exit 1 - fi - if ! [[ "$packageVersion" =~ ^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$ ]]; then - echo "Extension version must be a stable three-component version." >&2 - exit 1 - fi - - echo "##vso[build.updatebuildnumber]vscode-typescript-$packageVersion" - displayName: Validate release tag - - task: UseDotNet@2 displayName: Use .NET Core SDK 8.0.x inputs: @@ -110,6 +67,49 @@ extends: artifactName: vsix steps: + - checkout: self + clean: true + submodules: false + fetchDepth: 0 + fetchFilter: blob:none + fetchTags: false + + - bash: | + set -euo pipefail + git fetch origin main --no-tags + if ! git merge-base --is-ancestor "$BUILD_SOURCEVERSION" refs/remotes/origin/main; then + echo "Release tags must point to commits already merged into main." >&2 + exit 1 + fi + + tag="${BUILD_SOURCEBRANCH#refs/tags/}" + case "$tag" in + vscode-typescript/v*) ;; + *) + echo "Expected a vscode-typescript/v* tag, got $BUILD_SOURCEBRANCH." >&2 + exit 1 + ;; + esac + + tagVersion="${tag#vscode-typescript/v}" + packageVersion="$(jq -r '.version' packages/vscode-typescript/package.json)" + lockVersion="$(jq -r '.packages["packages/vscode-typescript"].version' package-lock.json)" + if [ "$tagVersion" != "$packageVersion" ]; then + echo "Tag version $tagVersion does not match package version $packageVersion." >&2 + exit 1 + fi + if [ "$packageVersion" != "$lockVersion" ]; then + echo "package.json version $packageVersion does not match package-lock.json version $lockVersion." >&2 + exit 1 + fi + if ! [[ "$packageVersion" =~ ^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$ ]]; then + echo "Extension version must be a stable three-component version." >&2 + exit 1 + fi + + echo "##vso[build.updatebuildnumber]vscode-typescript-$packageVersion" + displayName: Validate release tag + - template: /tools/pipelines/steps/setup-node-npm-ci.yml@self - bash: npm test -w native-preview From 8c93ff2f8632b68fedfd140eee573ec48c973491 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Tue, 29 Sep 2026 22:09:04 -0700 Subject: [PATCH 6/7] Keep scheduled build tagging in regular steps Scheduled build tagging does not need to precede MicroBuild setup. Keep presteps limited to .NET installation in both release pipelines. --- tools/pipelines/typescript-build.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/pipelines/typescript-build.yml b/tools/pipelines/typescript-build.yml index 1846773d2c10f..3bc3c391ad5d9 100755 --- a/tools/pipelines/typescript-build.yml +++ b/tools/pipelines/typescript-build.yml @@ -67,9 +67,6 @@ extends: signType: real zipSources: false mbpresteps: - - bash: echo "##vso[build.addbuildtag]Build.Reason.Schedule" - displayName: 'Set build tag "Build.Reason.Schedule"' - condition: eq(variables['Build.Reason'], 'Schedule') # Needed for ESRP. https://dev.azure.com/devdiv/DevDiv/_wiki/wikis/DevDiv.wiki/46279/Real-signing-with-PME-Enforcement - task: UseDotNet@2 displayName: Use .NET Core sdk 8.0.x @@ -84,6 +81,10 @@ extends: artifactName: vsix steps: + - bash: echo "##vso[build.addbuildtag]Build.Reason.Schedule" + displayName: 'Set build tag "Build.Reason.Schedule"' + condition: eq(variables['Build.Reason'], 'Schedule') + - checkout: self clean: true submodules: false From 70d72bb6910093df6670d749a981a0b4434af147 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Wed, 30 Sep 2026 12:35:36 -0700 Subject: [PATCH 7/7] Configure the MicroBuild plugin directory explicitly Avoid deriving the plugin root from DDSignFiles' app folder, whose internal layout is unrelated to MSBuild plugin discovery. Use an explicit pipeline setting for real signing and signature verification so a missing configured plugin fails rather than falling back to fake signing. --- Herebyfile.mjs | 8 ++++---- tools/pipelines/typescript-build.yml | 2 ++ tools/pipelines/vscode-typescript-build.yml | 1 + 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Herebyfile.mjs b/Herebyfile.mjs index d88801e8caade..ca85ddf794695 100644 --- a/Herebyfile.mjs +++ b/Herebyfile.mjs @@ -1625,8 +1625,8 @@ function assertMsbuildXmlValue(value) { async function sign(filelist, unchangedOutputOkay = false) { console.log("filelist:", JSON.stringify(filelist, undefined, 4)); - if (!process.env.MBSIGN_APPFOLDER) { - console.log(styleText("yellow", "Faking signing because MBSIGN_APPFOLDER is not set.")); + if (!process.env.MICROBUILD_PLUGIN_DIRECTORY) { + console.log(styleText("yellow", "Faking signing because MICROBUILD_PLUGIN_DIRECTORY is not set.")); // Fake signing for testing. @@ -1762,7 +1762,7 @@ ${items} "-p:SignType=real", `-p:SignFilesDir=${path.resolve("built")}`, `-p:FilesToSignPropsFile=${propsPath}`, - `-p:MicroBuildOverridePluginDirectory=${path.dirname(path.dirname(process.env.MBSIGN_APPFOLDER))}`, + `-p:MicroBuildOverridePluginDirectory=${process.env.MICROBUILD_PLUGIN_DIRECTORY}`, ]); } finally { @@ -2831,7 +2831,7 @@ async function runSignVsixExtensions() { ], }); - if (!process.env.MBSIGN_APPFOLDER) { + if (!process.env.MICROBUILD_PLUGIN_DIRECTORY) { console.log("Skipping VSIX signature verification because signing was faked."); return; } diff --git a/tools/pipelines/typescript-build.yml b/tools/pipelines/typescript-build.yml index 3bc3c391ad5d9..e46e306268e77 100755 --- a/tools/pipelines/typescript-build.yml +++ b/tools/pipelines/typescript-build.yml @@ -145,6 +145,7 @@ extends: - bash: npx hereby typescript:sign --forRelease --setPrerelease dev.$(initialBuildNumber) displayName: 'Sign packages' env: + MICROBUILD_PLUGIN_DIRECTORY: $(Agent.TempDirectory)/MicroBuild/Plugins # Needed for ESRP SYSTEM_ACCESSTOKEN: $(System.AccessToken) @@ -157,6 +158,7 @@ extends: - bash: npx hereby vscode-typescript:sign --forRelease --setPrerelease dev.$(initialBuildNumber) displayName: 'Sign extensions' env: + MICROBUILD_PLUGIN_DIRECTORY: $(Agent.TempDirectory)/MicroBuild/Plugins # Needed for ESRP SYSTEM_ACCESSTOKEN: $(System.AccessToken) diff --git a/tools/pipelines/vscode-typescript-build.yml b/tools/pipelines/vscode-typescript-build.yml index 6266b4967db33..76d48508e4f68 100644 --- a/tools/pipelines/vscode-typescript-build.yml +++ b/tools/pipelines/vscode-typescript-build.yml @@ -118,6 +118,7 @@ extends: - bash: npx hereby vscode-typescript:release --forRelease --vscodeTypescriptRelease displayName: Build and sign extensions env: + MICROBUILD_PLUGIN_DIRECTORY: $(Agent.TempDirectory)/MicroBuild/Plugins SYSTEM_ACCESSTOKEN: $(System.AccessToken) VSCODE_TYPESCRIPT_SIGN_TYPE: real