diff --git a/build/azure-pipelines/devdiv/python-extension-api.yml b/build/azure-pipelines/devdiv/python-extension-api.yml new file mode 100644 index 000000000000..3cb5e9218b17 --- /dev/null +++ b/build/azure-pipelines/devdiv/python-extension-api.yml @@ -0,0 +1,362 @@ +############################################################################################### +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +############################################################################################### + +name: $(Date:yyyyMMdd)$(Rev:.r) + +trigger: none +pr: none + +resources: + repositories: + - repository: MicroBuildTemplate + type: git + name: 1ESPipelineTemplates/MicroBuildTemplate + ref: refs/tags/release + - repository: templates + type: git + name: DevDiv/Pylance-Eng + ref: refs/heads/main + +parameters: + - name: quality + displayName: Release quality + type: string + default: latest + values: + - latest + - next + + - name: publishPythonApi + displayName: Publish pythonExtensionApi + type: boolean + default: false + + - name: runAPIScan + displayName: Run API Scan + type: boolean + default: true + +variables: + - name: TeamName + value: vscode-python + - name: PackageName + value: '@vscode/python-extension' + - name: PackageDirectory + value: pythonExtensionApi + - name: NodeVersion + value: '22.21.1' + - name: NpmTag + value: ${{ parameters.quality }} + - name: AZURE_ARTIFACTS_FEED + value: 'https://devdiv.pkgs.visualstudio.com/DevDiv/_packaging/Pylance_PublicPackages/npm/registry/' + +extends: + template: azure-pipelines/MicroBuild.1ES.Official.Publish.yml@MicroBuildTemplate + parameters: + settings: + networkIsolationPolicy: Preferred,GitHub,NodeTool + sdl: + sourceAnalysisPool: VSEng-MicroBuildVSStable + sbom: + enabled: true + pool: + name: AzurePipelines-EO + image: 1ESPT-Ubuntu22.04 + os: linux + + customBuildTags: + - ES365AIMigrationTooling + + stages: + - stage: Build + displayName: Build, test, and pack + jobs: + - job: ValidateConfiguration + displayName: Validate pipeline parameters + steps: + - ${{ if and(eq(parameters.publishPythonApi, true), eq(parameters.runAPIScan, false)) }}: + - bash: | + echo "Publishing requires API Scan. Set runAPIScan to true." >&2 + exit 1 + displayName: Reject publishing without API Scan + - ${{ else }}: + - bash: echo "Pipeline parameter validation passed." + displayName: Validate parameters + + - job: Linux_Node_22_21_1 + displayName: Linux (Node.js 22.21.1) + dependsOn: ValidateConfiguration + pool: + name: AzurePipelines-EO + image: 1ESPT-Ubuntu22.04 + os: linux + steps: + - checkout: self + clean: true + + - template: azure-pipelines/extension/templates/steps/setup.yml@templates + parameters: + installPython: false + customNPMRegistry: $(AZURE_ARTIFACTS_FEED) + nodeVersion: $(NodeVersion) + + - template: /build/azure-pipelines/templates/test-steps.yml@self + parameters: + package: $(PackageDirectory) + + - job: MacOS_Node_22_21_1 + displayName: macOS (Node.js 22.21.1) + dependsOn: ValidateConfiguration + pool: + name: Azure Pipelines + image: macOS-15 + os: macOS + variables: + BUILDSECMON_OPT_IN: false + steps: + - checkout: self + clean: true + + - template: azure-pipelines/extension/templates/steps/setup.yml@templates + parameters: + installPython: false + customNPMRegistry: $(AZURE_ARTIFACTS_FEED) + nodeVersion: $(NodeVersion) + + - template: /build/azure-pipelines/templates/test-steps.yml@self + parameters: + package: $(PackageDirectory) + + - job: Windows_Node_22_21_1 + displayName: Windows (Node.js 22.21.1) + dependsOn: ValidateConfiguration + pool: + name: AzurePipelines-EO + image: 1ESPT-Windows2022 + os: windows + steps: + - checkout: self + clean: true + + - template: azure-pipelines/extension/templates/steps/setup.yml@templates + parameters: + installPython: false + customNPMRegistry: $(AZURE_ARTIFACTS_FEED) + nodeVersion: $(NodeVersion) + + - template: /build/azure-pipelines/templates/test-steps.yml@self + parameters: + package: $(PackageDirectory) + + - job: Package + displayName: Pack npm package + dependsOn: + - Linux_Node_22_21_1 + - MacOS_Node_22_21_1 + - Windows_Node_22_21_1 + pool: + name: AzurePipelines-EO + image: 1ESPT-Ubuntu22.04 + os: linux + templateContext: + outputs: + - output: pipelineArtifact + targetPath: $(Build.ArtifactStagingDirectory) + artifactName: pythonExtensionApi + steps: + - checkout: self + clean: true + + - template: azure-pipelines/extension/templates/steps/setup.yml@templates + parameters: + installPython: false + customNPMRegistry: $(AZURE_ARTIFACTS_FEED) + nodeVersion: $(NodeVersion) + + - template: /build/azure-pipelines/templates/pack-steps.yml@self + parameters: + package: $(PackageDirectory) + + - script: npm pack --pack-destination $(Build.ArtifactStagingDirectory) + workingDirectory: $(Build.SourcesDirectory)/$(PackageDirectory) + displayName: Pack npm package + + - ${{ if eq(parameters.runAPIScan, true) }}: + - stage: APIScan + displayName: API Scan + dependsOn: Build + condition: succeeded() + jobs: + - job: APIScan + displayName: Scan packed API + pool: + name: VSEngSS-MicroBuild2022-1ES + os: windows + steps: + - checkout: self + clean: true + + - task: DownloadPipelineArtifact@2 + inputs: + artifactName: pythonExtensionApi + targetPath: $(Agent.TempDirectory)/pythonExtensionApi + displayName: Download npm package + + - task: ExtractFiles@1 + inputs: + archiveFilePatterns: $(Agent.TempDirectory)/pythonExtensionApi/*.tgz + destinationFolder: $(Agent.TempDirectory)/apiscan + cleanDestinationFolder: true + displayName: Extract package for API Scan + + - pwsh: | + $config = @{ + areaPath = 'DevDiv\VS Code (compliance tracking only)\Visual Studio Code NPM Packages' + codebaseName = 'devdiv_microsoft_vscode_python' + instanceUrl = 'https://devdiv.visualstudio.com/defaultcollection' + notificationAliases = @('monacotools@microsoft.com') + serviceTreeID = 'f85a34fa-964a-4306-885a-003737c8fe18' + projectName = 'DevDiv' + } | ConvertTo-Json -Depth 4 + + $configDirectory = Join-Path '$(Build.SourcesDirectory)' '.config' + New-Item -Path $configDirectory -ItemType Directory -Force | Out-Null + $configPath = Join-Path $configDirectory 'tsaoptions.json' + Set-Content -Path $configPath -Value $config + Get-Content -Path $configPath + displayName: Generate TSA configuration + + # DevDiv must provide the vscode-apiscan service connection and a secret + # APIScanConnectionString pipeline variable before this job can run. + - task: APIScan@2 + inputs: + softwareFolder: $(Agent.TempDirectory)/apiscan/package + softwareName: pythonExtensionApi + softwareVersionNum: '2024' + symbolsFolder: 'SRV*https://symweb.azurefd.net;$(Agent.TempDirectory)/apiscan' + isLargeApp: false + toolVersion: Latest + azureSubscription: vscode-apiscan + env: + AzureServicesAuthConnectionString: $(APIScanConnectionString) + SYSTEM_ACCESSTOKEN: $(System.AccessToken) + displayName: Run API Scan + + - task: PublishSecurityAnalysisLogs@3 + inputs: + ArtifactName: CodeAnalysisLogs + ArtifactType: Container + AllTools: true + ToolLogsNotFoundAction: Standard + displayName: Publish API Scan logs + + - task: securedevelopmentteam.vss-secure-development-tools.build-task-uploadtotsa.TSAUpload@2 + continueOnError: true + inputs: + GdnPublishTsaConfigFile: $(Build.SourcesDirectory)/.config/tsaoptions.json + GdnPublishTsaOnboard: true + displayName: TSA Upload + + - stage: Publish + displayName: Publish npm package + ${{ if eq(parameters.runAPIScan, true) }}: + dependsOn: APIScan + ${{ else }}: + dependsOn: Build + condition: and(succeeded(), eq('${{ parameters.publishPythonApi }}', 'true')) + jobs: + - job: PublishPackage + displayName: Publish npm package + pool: + name: AzurePipelines-EO + image: 1ESPT-Ubuntu22.04 + os: linux + templateContext: + isReleaseJob: true + steps: + - checkout: self + clean: true + persistCredentials: false + + - download: current + artifact: pythonExtensionApi + displayName: Download npm package + + - template: azure-pipelines/extension/templates/steps/setup.yml@templates + parameters: + installPython: false + customNPMRegistry: $(AZURE_ARTIFACTS_FEED) + nodeVersion: $(NodeVersion) + + - task: ExtractFiles@1 + inputs: + archiveFilePatterns: $(Pipeline.Workspace)/pythonExtensionApi/*.tgz + destinationFolder: $(Build.ArtifactStagingDirectory)/pythonExtensionApi + cleanDestinationFolder: true + displayName: Extract npm package + + - bash: | + set -euo pipefail + packageVersion="$(node -p "require('./package.json').version")" + echo "##vso[task.setvariable variable=PackageVersion]$packageVersion" + echo "Package version: $packageVersion" + workingDirectory: $(Build.ArtifactStagingDirectory)/pythonExtensionApi/package + displayName: Read package version + + - task: EsrpRelease@14 + inputs: + connectedservicename: EsrpThirdPartyPackageManager + usemanagedidentity: true + keyvaultname: DevDiv3rdPartyPkgMngrKV + signcertname: DevDiv3rdPartyPkgMngr + clientid: 15908223-fc42-4083-bd72-71dedfdac47f + intent: PackageDistribution + contentType: npm + contentsource: Folder + folderlocation: $(Pipeline.Workspace)/pythonExtensionApi + waitforreleasecompletion: true + owners: stbatt@microsoft.com,lszomoru@microsoft.com + approvers: stbatt@microsoft.com,lszomoru@microsoft.com + serviceendpointurl: https://api.esrp.microsoft.com + mainpublisher: ESRPRELPACMAN + domaintenantid: 975f013f-7f24-47e8-a7d3-abc4752bf346 + productstate: $(NpmTag) + displayName: Publish package to npm + + - bash: | + set -euo pipefail + echo "registry=$(AZURE_ARTIFACTS_FEED)" > .npmrc + echo "always-auth=true" >> .npmrc + workingDirectory: $(Build.ArtifactStagingDirectory)/pythonExtensionApi/package + displayName: Configure DevDiv npm feed + + - task: npmAuthenticate@0 + inputs: + workingFile: $(Build.ArtifactStagingDirectory)/pythonExtensionApi/package/.npmrc + displayName: Authenticate DevDiv npm feed + + - bash: | + set -euo pipefail + npm install --global npm@11.6.0 --ignore-scripts --userconfig .npmrc --prefix "$(Agent.TempDirectory)/publishing-npm" + echo "##vso[task.prependpath]$(Agent.TempDirectory)/publishing-npm/bin" + workingDirectory: $(Build.ArtifactStagingDirectory)/pythonExtensionApi/package + displayName: Install npm with lifecycle scripts disabled + + - task: Npm@1 + inputs: + command: publish + publishRegistry: useFeed + publishFeed: DevDiv/Pylance_PublicPackages + workingDir: $(Build.ArtifactStagingDirectory)/pythonExtensionApi/package + env: + NPM_CONFIG_IGNORE_SCRIPTS: 'true' + NPM_CONFIG_TAG: $(NpmTag) + displayName: Publish package to DevDiv feed + + - template: azure-pipelines/extension/templates/steps/createGitHubRelease.yml@templates + parameters: + isPreRelease: ${{ ne(parameters.quality, 'latest') }} + ghReleaseAddChangeLog: true + tagName: release/pythonExtensionApi/$(PackageVersion) diff --git a/build/azure-pipelines/devdiv/static-analysis.yml b/build/azure-pipelines/devdiv/static-analysis.yml new file mode 100644 index 000000000000..03be047050f4 --- /dev/null +++ b/build/azure-pipelines/devdiv/static-analysis.yml @@ -0,0 +1,318 @@ +############################################################################################### +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +############################################################################################### + +name: $(Date:yyyyMMdd)$(Rev:.r) + +trigger: none +pr: none + +resources: + repositories: + - repository: MicroBuildTemplate + type: git + name: 1ESPipelineTemplates/MicroBuildTemplate + ref: refs/tags/release + +variables: + - name: TeamName + value: vscode-python + - name: Codeql.SkipTaskAutoInjection + value: true + - name: skipNugetSecurityAnalysis + value: true + +extends: + template: azure-pipelines/MicroBuild.1ES.Official.yml@MicroBuildTemplate + parameters: + settings: + networkIsolationPolicy: Preferred,GitHub,NodeTool + sdl: + sourceAnalysisPool: VSEng-MicroBuildVSStable + bandit: + enabled: false + antimalwareScan: + enabled: false + componentgovernance: + enabled: false + credscan: + enabled: false + eslint: + enabled: false + policheck: + enabled: false + publishLogs: + enabled: false + sdtReport: + enabled: false + tsa: + enabled: false + pool: + name: VSEngSS-MicroBuild2022-1ES + os: windows + + customBuildTags: + - ES365AIMigrationTooling + + stages: + - stage: StaticAnalysis + displayName: Static analysis + jobs: + - job: StaticAnalysis + displayName: Static analysis + steps: + - checkout: self + clean: true + fetchDepth: 0 + + - task: UsePythonVersion@0 + inputs: + versionSpec: 3.x + addToPath: true + architecture: x64 + displayName: Use Python 3.x + + - pwsh: | + $pythonFiles = Get-ChildItem -Path '$(Build.SourcesDirectory)\python_files' -Filter '*.py' -Recurse -File | + Where-Object { $_.FullName -notlike '*\python_files\tests\*' } + if ($pythonFiles.Count -eq 0) { + throw 'Bandit target contains no Python files.' + } + + $poliCheckExceptions = '$(Build.SourcesDirectory)\build\ci\static_analysis\policheck\exceptions.mdb' + if (-not (Test-Path -LiteralPath $poliCheckExceptions -PathType Leaf)) { + throw "PoliCheck exceptions file was not found: $poliCheckExceptions" + } + + Write-Host "Bandit will scan $($pythonFiles.Count) Python files." + Write-Host "PoliCheck exceptions: $poliCheckExceptions" + Write-Host "AntiMalware and CredScan will scan $(Build.SourcesDirectory)." + displayName: Verify scan targets + + - task: Bandit@1 + continueOnError: true + inputs: + aggregate: vuln + baseline: '' + configFile: '' + contextLines: '' + customRules: '' + debug: false + excludedPaths: '' + ignoreNosec: false + minConfidence: low + minSeverity: Low + policyName: Microsoft + profile: '' + quiet: false + ruleset: guardian + skippedRules: '' + targets: 'f|$(Build.SourcesDirectory)\python_files\**\*.py;-|.gdn\**;-|$(Build.SourcesDirectory)\python_files\tests\**\*.py' + targetsBandit: $(Build.SourcesDirectory) + targetsBanditRecursive: true + targetsType: guardianGlob + verbose: false + displayName: Run Bandit + + - task: PoliCheck@1 + continueOnError: true + inputs: + EXGT: false + SOMEnabled: false + cmdLineArgs: '/F:$(Build.SourcesDirectory) /T:9 /O:PoliCheck.xml' + importEx: '' + inputType: Basic + optionsB1: '' + optionsB2: '' + optionsB3: '' + optionsCTGLEN: '' + optionsD: '' + optionsFC: none + optionsFTPATH: '' + optionsHMENABLE: none + optionsHPATH: '' + optionsHVER: '' + optionsOCDB: '' + optionsPE: 1|2 + optionsRule: '' + optionsRulesDBPath: '$(Build.SourcesDirectory)\build\ci\static_analysis\policheck\exceptions.mdb' + optionsSEV: '' + optionsTASKNAME: '' + optionsUEPATH: '' + optionsWORKINGDIRECTORY: '' + optionsXCLASS: '' + optionsXS: none + result: PoliCheck.xml + targetArgument: $(Build.SourcesDirectory) + targetType: F + termTypeK: '' + termTypeL: '' + termTypeT: 0029a9 + termTypeTCustom: 9 + toolVersion: Latest + uploadErrorLevel: Error + uploadToSOM: false + workspaceId: '' + displayName: Run PoliCheck + + - task: AntiMalware@3 + continueOnError: true + inputs: + Arguments: '-Scan -ScanType 3 -DisableRemediation -File "$(Build.SourcesDirectory)"' + BootSectorScan: false + DisableRemediation: true + EnableServices: true + FileDirPath: $(Build.SourcesDirectory) + InputType: Basic + ScanType: CustomScan + SignatureFreshness: UpToDate + SupportLogOnError: false + TreatSignatureUpdateFailureAs: Warning + TreatStaleSignatureAs: Error + displayName: Run AntiMalware + + - task: CredScan@2 + continueOnError: true + inputs: + batchSize: '' + debugMode: false + fileScanReadBufferSize: '' + folderSuppression: false + m365Version: Latest + maxFileScanReadBytes: '' + outputFormat: pre + regexMatchTimeoutInSeconds: '' + scanFolder: $(Build.SourcesDirectory) + searchersFile: '' + searchersFileType: Default + suppressAsError: false + suppressionsFile: '' + toolMajorVersion: V2 + toolVersion: Latest + toolVersionV2: Latest + verboseOutput: true + displayName: Run CredScan + + - task: AutoApplicability@1 + continueOnError: true + inputs: + ApplyRules: Microsoft.Security + DataSensitivity: none + ExternalRelease: true + InternalRelease: false + IsCertAuthority: false + IsCodeSigner: false + IsService: false + IsSoftware: true + UsesHSM: false + VerboseWriter: false + toolVersion: Latest + displayName: Run AutoApplicability + + - task: VulnerabilityAssessment@0 + continueOnError: true + displayName: Run Vulnerability Assessment + + - task: SdtReport@1 + continueOnError: true + inputs: + APIScan: false + AllTools: false + BinSkim: false + BinSkimBreakOn: Error + CodesignValidation: false + CodesignValidationBreakOn: Error + CredScan: true + CustomLogsFolder: '' + FortifySCA: false + FxCop: false + FxCopBreakOn: ErrorAbove + HtmlFile: true + MSRD: false + ModernCop: false + ModernCopBreakOn: Error + PoliCheck: true + PoliCheckBreakOn: Severity1 + RoslynAnalyzers: false + RoslynAnalyzersBreakOn: Error + SDLNativeRules: false + Semmle: false + SemmleBreakOn: Error + TSLint: false + TSLintBreakOn: Error + ToolLogsNotFoundAction: Standard + TsvFile: true + VstsConsole: true + displayName: Create Security Analysis Report + + - task: PublishSecurityAnalysisLogs@2 + inputs: + APIScan: false + AllTools: false + AntiMalware: true + ArtifactName: CodeAnalysisLogs + ArtifactType: Container + BinSkim: false + CodesignValidation: false + CredScan: true + FortifySCA: false + FxCop: false + MSRD: false + ModernCop: false + PoliCheck: true + RoslynAnalyzers: false + SDLNativeRules: false + Semmle: false + TSLint: false + ToolLogsNotFoundAction: Standard + UploadCustomResults: false + WebScout: false + displayName: Publish Security Analysis Logs + + - task: TSAUpload@1 + inputs: + areaPath: 'DevDiv\Python and AI Tools\Python\VS Code\Static Analysis' + codeBaseAdmins: '' + codeBaseName: vscode-python-main + codebase: NewOrUpdate + instanceUrlForTsaV2: DEVDIV + notificationAlias: kanadig@microsoft.com + notifyAlwaysV1: true + notifyAlwaysV2: false + projectNameDEVDIV: DevDiv + serviceTreeID: 6e6194bc-7baa-4486-86d0-9f5419626d46 + tsaEnvironment: PROD + tsaStamp: TSA + tsaVersion: TsaV2 + tsaWebApiUrl: $(TSAStamp) + uploadAPIScan: false + uploadAsync: true + uploadBinSkim: false + uploadCredScan: true + uploadFortifySCA: false + uploadFxCop: false + uploadModernCop: false + uploadPREfast: false + uploadPoliCheck: true + uploadRoslyn: false + uploadTSLint: false + validateCompatibility: Error + validateToolOutput: Warning + displayName: TSA Upload + + - task: ComponentGovernanceComponentDetection@0 + inputs: + alertWarningLevel: High + autoInjected: false + detectorsFilter: '' + detectorsToRun: '' + dockerImagesToScan: '' + failOnAlert: false + ignoreDirectories: .github,build,news + scanType: Register + sourceScanPath: '' + useDefaultDetectors: true + verbosity: Verbose + whatif: false + displayName: Component Detection