diff --git a/Build/18.0/packages.config b/Build/18.0/packages.config index 1c79198ef1..210c9385e2 100644 --- a/Build/18.0/packages.config +++ b/Build/18.0/packages.config @@ -1,7 +1,6 @@ - @@ -83,4 +82,5 @@ + diff --git a/Build/PreBuild.ps1 b/Build/PreBuild.ps1 index 2f7b908c2c..c16482782b 100644 --- a/Build/PreBuild.ps1 +++ b/Build/PreBuild.ps1 @@ -208,7 +208,7 @@ try { if (-not $interactive) { $arglist += "-NonInteractive" } - $nuget = Get-Command nuget.exe -EA 0 + $nuget = Get-Command .\nuget.exe -EA 0 if (-not $nuget) { $nuget = Get-Command .\nuget.exe } diff --git a/Build/azuredevops/test/uitest-integration-stage.yml b/Build/azuredevops/test/uitest-integration-stage.yml new file mode 100644 index 0000000000..07372455b8 --- /dev/null +++ b/Build/azuredevops/test/uitest-integration-stage.yml @@ -0,0 +1,157 @@ +parameters: + - name: BinariesDirectory + type: string + default: '$(Drop)/binaries' + - name: CleanupProcesses + type: string + default: 'devenv, vshub, microsoft.vshub.server.httphost, python, ipy, microsoft.pythontools.analyzer, vstest.executionengine.x86, vstest.discoveryengine.x86' + - name: Drop + type: string + default: '$(System.ArtifactsDirectory)/$(DefinitionName)' + - name: TestFilterCriteria + type: string + default: 'Priority=0' + - name: UITestNames + type: string + default: '' + +steps: + - task: ExtractFiles@1 + displayName: Extract files + condition: succeeded() + inputs: + archiveFilePatterns: '${{ parameters.Drop }}/TestData.zip' + destinationFolder: '${{ parameters.Drop }}/TestData' + cleanDestinationFolder: false + overwriteExistingFiles: false + + - task: PowerShell@2 + displayName: Cleanup + condition: succeeded() + continueOnError: true + timeoutInMinutes: 5 + inputs: + targetType: inline + script: | + $names = @( + '${{ parameters.CleanupProcesses }}' + -split ',' | + ForEach-Object { $_.Trim() } | + Where-Object { -not [string]::IsNullOrWhiteSpace($_) } + ) + $running = Get-Process -Name $names -ErrorAction SilentlyContinue + while ($running) { + Write-Host 'Killing:' + $running + try { + $running | Stop-Process -Force + } catch { + } + Start-Sleep -Seconds 3 + $running = Get-Process -Name $names -ErrorAction SilentlyContinue + } + errorActionPreference: stop + failOnStderr: true + + - task: CopyFiles@2 + displayName: Copy TestData into binaries + condition: succeeded() + continueOnError: true + inputs: + SourceFolder: '${{ parameters.Drop }}/TestData' + Contents: '**' + TargetFolder: '${{ parameters.BinariesDirectory }}/TestData' + CleanTargetFolder: 'true' + OverWrite: 'false' + flattenFolders: 'false' + preserveTimestamp: 'false' + retryCount: '0' + + - task: CopyFiles@2 + displayName: Copy runsettings to binary folder + condition: succeeded() + inputs: + SourceFolder: '${{ parameters.BinariesDirectory }}/TestData' + Contents: 'ptvs.runsettings' + TargetFolder: '${{ parameters.BinariesDirectory }}' + CleanTargetFolder: 'false' + OverWrite: 'false' + flattenFolders: 'false' + preserveTimestamp: 'false' + retryCount: '0' + + - task: PowerShell@2 + displayName: Skip Verification + condition: succeeded() + inputs: + targetType: inline + script: | + reg import "${{ parameters.BinariesDirectory }}\TestData\EnableSkipVerification.reg" + errorActionPreference: stop + failOnStderr: false + + - task: VSTest@2 + displayName: '[MultiConfiguration] Run UI Test ${{ parameters.UITestNames }}' + condition: succeeded() + continueOnError: true + inputs: + testSelector: testAssemblies + testAssemblyVer2: '${{ parameters.UITestNames }}UITestsRunner.dll' + tcmTestRun: '$(test.RunId)' + searchFolder: '${{ parameters.BinariesDirectory }}' + resultsFolder: '$(Agent.TempDirectory)/TestResults' + testFiltercriteria: '${{ parameters.TestFilterCriteria }}' + runOnlyImpactedTests: false + runAllTestsAfterXBuilds: 50 + uiTests: true + vstestLocationMethod: version + vsTestVersion: latest + runSettingsFile: '${{ parameters.Drop }}\\ptvs.runsettings' + overrideTestrunParameters: '-TargetFrameworkVersion .NETFramework,Version=v4.7.2' + runInParallel: false + runTestsInIsolation: false + codeCoverageEnabled: true + distributionBatchType: basedOnExecutionTime + batchingBasedOnAgentsOption: autoBatchSize + customBatchSizeValue: 10 + batchingBasedOnExecutionTimeOption: customTimeBatchSize + customRunTimePerBatchValue: 300 + dontDistribute: false + testRunTitle: '${{ parameters.UITestNames }} UI Tests' + publishRunAttachments: true + failOnMinTestsNotRun: false + minimumExpectedTests: 1 + diagnosticsEnabled: true + collectDumpOn: onAbortOnly + rerunFailedTests: true + rerunType: basedOnTestFailurePercentage + rerunFailedThreshold: 50 + rerunFailedTestCasesMaxLimit: 5 + rerunMaxAttempts: 2 + + - task: PowerShell@2 + displayName: Cleanup + condition: succeeded() + timeoutInMinutes: 5 + inputs: + targetType: inline + script: | + $names = @( + '${{ parameters.CleanupProcesses }}' + -split ',' | + ForEach-Object { $_.Trim() } | + Where-Object { -not [string]::IsNullOrWhiteSpace($_) } + ) + $running = Get-Process -Name $names -ErrorAction SilentlyContinue + while ($running) { + Write-Host 'Killing:' + $running + try { + $running | Stop-Process -Force + } catch { + } + Start-Sleep -Seconds 3 + $running = Get-Process -Name $names -ErrorAction SilentlyContinue + } + errorActionPreference: stop + failOnStderr: true diff --git a/Build/debugpy-version.txt b/Build/debugpy-version.txt index e06e7a26c8..bbaa9e1622 100644 --- a/Build/debugpy-version.txt +++ b/Build/debugpy-version.txt @@ -1 +1 @@ -1.8.17 \ No newline at end of file +1.8.18 \ No newline at end of file diff --git a/Build/nuget.config b/Build/nuget.config index 5dd8ead95c..b441bb20ef 100644 --- a/Build/nuget.config +++ b/Build/nuget.config @@ -3,9 +3,10 @@ - + - + + diff --git a/Build/nuget.testdata.config b/Build/nuget.testdata.config new file mode 100644 index 0000000000..6ffb9ce36d --- /dev/null +++ b/Build/nuget.testdata.config @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + Microsoft;xunit;manuel.roemer;sharwell;jamesnk;aarnott;MarcoRossignoli;Thecentury;AndreyAkinshin;0xd4d;ericnewton76;jkeech;steve.dower + + + + + + + + diff --git a/Build/packages.testdata.config b/Build/packages.testdata.config new file mode 100644 index 0000000000..00494d7e05 --- /dev/null +++ b/Build/packages.testdata.config @@ -0,0 +1,4 @@ + + + + diff --git a/Build/templates/build.yml b/Build/templates/build.yml index 9d755e9134..94e05dd21b 100644 --- a/Build/templates/build.yml +++ b/Build/templates/build.yml @@ -2,6 +2,9 @@ parameters: - name: ptvsPackageVersion type: string default: $(Build.BuildNumber) +- name: skipSigning + type: boolean + default: false steps: @@ -57,4 +60,5 @@ steps: /p:BuildNumber=${{ parameters.ptvsPackageVersion }} /p:BUILD_BINARIESDIRECTORY=$(Build.BinariesDirectory) /p:BUILD_STAGINGDIRECTORY=$(Build.StagingDirectory) + /p:SkipSigning=${{ parameters.skipSigning }} /bl:$(Build.SourcesDirectory)\logs\BuildInstaller.binlog' diff --git a/Build/templates/publish_test_data.yml b/Build/templates/publish_test_data.yml index cdd38b4847..462009249c 100644 --- a/Build/templates/publish_test_data.yml +++ b/Build/templates/publish_test_data.yml @@ -1,5 +1,43 @@ steps: + - task: NuGetToolInstaller@1 + displayName: Install NuGet + + - task: NuGetCommand@2 + displayName: Restore runsettings build tasks + inputs: + command: restore + feedsToUse: config + restoreSolution: '$(Build.SourcesDirectory)/Build/packages.testdata.config' + restoreDirectory: '$(Build.SourcesDirectory)/packages' + nugetConfigPath: '$(Build.SourcesDirectory)/Build/nuget.testdata.config' + + # Generate a runsettings file that points at the correct Test Store drop. + - task: MSBuild@1 + displayName: 'Build PTVS.runsettingsproj' + inputs: + solution: '$(Build.SourcesDirectory)/Python/Tests/PTVS.runsettingsproj' + msbuildArguments: > + /p:PackagesPath=$(Build.SourcesDirectory)\packages + /p:TestStoreDropName=$(TestStoreDropName) + + - task: PowerShell@2 + displayName: 'Update default.runsettings from generated ptvs.runsettings' + inputs: + targetType: 'inline' + script: | + $ErrorActionPreference = 'Stop' + + $source = "$(Build.SourcesDirectory)\Python\Tests\bin\RunSettings\ptvs.runsettings" + $dest = "$(Build.SourcesDirectory)\Python\Tests\TestData\ptvs.runsettings" + + if (-not (Test-Path -LiteralPath $source)) { + throw "Expected generated runsettings file not found: $source" + } + + Copy-Item -LiteralPath $source -Destination $dest -Force + + # Compress just the test data # Used in this release task to run tests: https://devdiv.visualstudio.com/DevDiv/_taskgroup/a7b18468-aab5-4be7-b718-02f85b0828c4 - task: ArchiveFiles@2 @@ -20,6 +58,13 @@ steps: Contents: 'TestData.zip' TargetFolder: '$(Build.ArtifactStagingDirectory)/TestDataFolder' + - task: CopyFiles@2 + displayName: 'Copy ptvs.runsettings to subfolder' + inputs: + SourceFolder: '$(Build.SourcesDirectory)/Python/Tests/TestData' + Contents: 'ptvs.runsettings' + TargetFolder: '$(Build.ArtifactStagingDirectory)/TestDataFolder' + # The Task 'PublishBuildArtifacts@1' has been converted to an output named 'Publish build artifact: TestData' in the templateContext section. # The Task 'PublishBuildArtifacts@1' has been converted to an output named 'Publish build artifact: RunSettings' in the templateContext section. \ No newline at end of file diff --git a/Python/PythonTools.sln b/Python/PythonTools.sln index 26958ebab1..4b69ac133e 100644 --- a/Python/PythonTools.sln +++ b/Python/PythonTools.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.0.31211.46 +# Visual Studio Version 18 +VisualStudioVersion = 18.3.11227.31 main MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Product", "Product", "{C0C7AD6F-5E39-4D3F-A6B6-FD30713B0464}" EndProject @@ -16,6 +16,9 @@ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestUtilities.UI", "..\Common\Tests\Utilities.UI\TestUtilities.UI.csproj", "{E8150EBC-6B62-40BF-BF91-1DC60149B530}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{3D21C7AC-6F9D-448C-8356-44EAFB2D14FC}" + ProjectSection(SolutionItems) = preProject + Tests\PTVS.runsettingsproj = Tests\PTVS.runsettingsproj + EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Attacher", "Product\Attacher\Attacher.csproj", "{666A22BB-0CB5-4C08-A20F-E17450DA6573}" EndProject diff --git a/Python/Setup/signlayout.proj b/Python/Setup/signlayout.proj index 4f2f5ff6b6..23cf5cf63c 100644 --- a/Python/Setup/signlayout.proj +++ b/Python/Setup/signlayout.proj @@ -9,6 +9,10 @@ $(BinariesOutputPath) $(BinariesOutputPath) + + false + + None @@ -17,7 +21,7 @@ - + <_Languages Include="$(Languages)" /> + @@ -84,7 +88,7 @@ - + @@ -96,17 +100,17 @@ - + - + - + <_BinariesInLayout Include="$(LayoutOutputPath)**\*.exe;$(LayoutOutputPath)**\*.dll" /> <_BinariesWithSignedSource Include="$(BinariesOutputPath)%(_BinariesInLayout.Filename)%(_BinariesInLayout.Extension)"> @@ -116,7 +120,7 @@ - + <_FilesInLayout Include="$(LayoutOutputPath)\Microsoft.PythonTools.Core\pylance\**\*.js" /> @@ -127,10 +131,10 @@ - + AfterTargets="SignFiles" + Condition="'$(SkipSigning)'!='true'"> diff --git a/Python/Tests/Core.UI/TestExplorerTests.cs b/Python/Tests/Core.UI/TestExplorerTests.cs index a22c074950..4555d42885 100644 --- a/Python/Tests/Core.UI/TestExplorerTests.cs +++ b/Python/Tests/Core.UI/TestExplorerTests.cs @@ -65,7 +65,7 @@ public void RunAllUnittestProject(PythonVisualStudioApp app) { var sln = app.CopyProjectForTest(@"TestData\TestExplorerUnittest.sln"); app.OpenProject(sln); - RunAllTests(app, AllUnittests); + RunAllTests(app, AllUnittests, Path.GetFileNameWithoutExtension(sln)); } public void RunAllUnittestWorkspace(PythonVisualStudioApp app) { diff --git a/Python/Tests/PTVS.runsettingsproj b/Python/Tests/PTVS.runsettingsproj new file mode 100644 index 0000000000..ff15a13040 --- /dev/null +++ b/Python/Tests/PTVS.runsettingsproj @@ -0,0 +1,37 @@ + + + + v4.6.1 + ptvs + bin\RunSettings + .\TestResults + x86 + 1 + 3600000 + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Python/Tests/PythonToolsUITestsRunner/TestExplorerTests.cs b/Python/Tests/PythonToolsUITestsRunner/TestExplorerTests.cs index de5292aeee..565c573553 100644 --- a/Python/Tests/PythonToolsUITestsRunner/TestExplorerTests.cs +++ b/Python/Tests/PythonToolsUITestsRunner/TestExplorerTests.cs @@ -75,12 +75,14 @@ public void DebugPytestWorkspace() { _vs.RunTest(nameof(PythonToolsUITests.TestExplorerTests.DebugPytestWorkspace)); } + [Ignore] [TestMethod, Priority(UITestPriority.P0)] [TestCategory("Installed")] public void DebugUnittestProject() { _vs.RunTest(nameof(PythonToolsUITests.TestExplorerTests.DebugUnittestProject)); } + [Ignore] [TestMethod, Priority(UITestPriority.P0)] [TestCategory("Installed")] public void DebugUnittestWorkspace() { diff --git a/Python/Tests/Utilities.Python/PythonTestExplorer.cs b/Python/Tests/Utilities.Python/PythonTestExplorer.cs index b55e810a8c..e48c40c3fe 100644 --- a/Python/Tests/Utilities.Python/PythonTestExplorer.cs +++ b/Python/Tests/Utilities.Python/PythonTestExplorer.cs @@ -14,18 +14,21 @@ // See the Apache Version 2.0 License for specific language governing // permissions and limitations under the License. +using Microsoft.VisualStudio.TestTools.UnitTesting; using System; using System.Threading; using System.Windows.Automation; -using Microsoft.VisualStudio.TestTools.UnitTesting; -namespace TestUtilities.UI { - public class PythonTestExplorer : AutomationWrapper { +namespace TestUtilities.UI +{ + public class PythonTestExplorer : AutomationWrapper + { private readonly VisualStudioApp _app; private readonly AutomationWrapper _searchBar; private PythonTestExplorerGridView _tests; - private static class TestCommands { + private static class TestCommands + { public const string GroupBy = "TestExplorer.GroupBy"; public const string RunAllTests = "TestExplorer.RunAllTests"; public const string CopyDetails = "TestExplorer.CopyDetails"; @@ -33,14 +36,18 @@ private static class TestCommands { } public PythonTestExplorer(VisualStudioApp app, AutomationElement element, AutomationWrapper searchBarTextBox) - : base(element) { + : base(element) + { _app = app; _searchBar = searchBarTextBox ?? throw new ArgumentNullException(nameof(searchBarTextBox)); } - public PythonTestExplorerGridView Tests { - get { - if (_tests == null) { + public PythonTestExplorerGridView Tests + { + get + { + if (_tests == null) + { var el = this.Element.FindFirst( TreeScope.Descendants, new AndCondition( @@ -54,7 +61,8 @@ public PythonTestExplorerGridView Tests { ) ) ); - if (el != null) { + if (el != null) + { _tests = new PythonTestExplorerGridView(el); } } @@ -62,13 +70,15 @@ public PythonTestExplorerGridView Tests { } } - public string GetTestDetailSummary() { + public string GetTestDetailSummary() + { // Root is the Test Explorer tool window element you already have. var summaryControl = Element.FindFirst( TreeScope.Descendants, new PropertyCondition(AutomationElement.ClassNameProperty, "SummaryControl") ); - if (summaryControl == null) { + if (summaryControl == null) + { return string.Empty; } @@ -77,17 +87,20 @@ public string GetTestDetailSummary() { TreeScope.Descendants, new PropertyCondition(AutomationElement.ClassNameProperty, "WpfTextView") ); - if (textView == null) { + if (textView == null) + { return string.Empty; } // Try TextPattern. object p; - if (textView.TryGetCurrentPattern(TextPattern.Pattern, out p)) { + if (textView.TryGetCurrentPattern(TextPattern.Pattern, out p)) + { return ((TextPattern)p).DocumentRange.GetText(int.MaxValue); } // Fallback ValuePattern. - if (textView.TryGetCurrentPattern(ValuePattern.Pattern, out p)) { + if (textView.TryGetCurrentPattern(ValuePattern.Pattern, out p)) + { return ((ValuePattern)p).Current.Value; } @@ -95,16 +108,19 @@ public string GetTestDetailSummary() { return textView.Current.Name ?? string.Empty; } - public string GetDetailsWithRetry() { + public string GetDetailsWithRetry() + { string details = string.Empty; - for (int i = 0; i < 5; i++) { + for (int i = 0; i < 5; i++) + { var detailsTextBox = this.FindByName("Test Detail Summary"); AutomationWrapper.CheckNullElement(detailsTextBox, "Missing: Test Detail Summary"); // Copy to clipboard details = GetTestDetailSummary(); - if (details.Contains("Source:")) { + if (details.Contains("Source:")) + { return details; } @@ -117,65 +133,85 @@ public string GetDetailsWithRetry() { /// /// Set the grouping to namespace. /// - public void GroupByProjectNamespaceClass() { - // TODO: figure out how to programmatically change this - // it's now a popup window that appears on TestExplorer.GroupBy command - // well, at least when you click on it with the mouse - // It's not coming up when invoking the command programmatically - - //var groupCommand = _app.Dte.Commands.Item(TestCommands.GroupBy); - //Assert.IsNotNull(groupCommand, "GroupBy command not found"); - - - //if (!groupCommand.IsAvailable) { - // // Group command is not available when show hierarchy is on - // //_app.ExecuteCommand(TestCommands.ToggleShowTestHierarchy); - // _app.WaitForCommandAvailable(groupCommand, TimeSpan.FromSeconds(5)); - //} - - //_app.ExecuteCommand(TestCommands.GroupBy); // by class - - //Thread.Sleep(100); + public void GroupByProjectNamespaceClass() + { + // Try execute the GroupBy command to display grouping popup. + try + { + _app.Dte.ExecuteCommand(TestCommands.GroupBy); + } + catch + { + // Swallow if command not available; we'll still try to locate the option. + } - //var element = _app.Element.FindFirst(TreeScope.Descendants, new AndCondition( - // new PropertyCondition( - // AutomationElement.NameProperty, - // "Project, Namespace, Class" - // ), - // new PropertyCondition( - // AutomationElement.ClassNameProperty, - // "TextBlock" - // ) - //)); - //Assert.IsNotNull(element); + // Allow UI to render the popup + Thread.Sleep(200); + + // Attempt to find the "Project, Namespace, Class" option and invoke it. + AutomationElement element = null; + for (int i = 0; i < 5 && element == null; i++) + { + element = _app.Element.FindFirst( + TreeScope.Descendants, + new AndCondition( + new PropertyCondition(AutomationElement.NameProperty, "Project, Namespace, Class"), + new PropertyCondition(AutomationElement.ClassNameProperty, "TextBlock") + ) + ); + if (element == null) + { + Thread.Sleep(200); + } + } - //var menuItem = element.CachedParent; - //Assert.IsNotNull(menuItem); + if (element != null) + { + // Use TreeWalker to get parent; CachedParent may be null depending on cache policy + var menuItem = element.CachedParent; + if (menuItem == null) + { + var walker = TreeWalker.RawViewWalker; + menuItem = walker.GetParent(element); + } - //menuItem.GetInvokePattern().Invoke(); + if (menuItem != null) + { + var inv = menuItem.GetInvokePattern() ?? element.GetInvokePattern(); + if (inv != null) + { + inv.Invoke(); + } + } + } WaitForTestsGrid(); } - private void WaitForTestsGrid() { + private void WaitForTestsGrid() + { // Wait for the test list to be created int retry = 10; - while (Tests == null) { + while (Tests == null) + { Thread.Sleep(250); retry--; - if (retry == 0) { + if (retry == 0) + { break; } } Assert.IsNotNull(Tests, "Tests list is null"); } - public void ClearSearchBar() { + public void ClearSearchBar() + { _searchBar.SetValue(""); Thread.Sleep(1000); } - public AutomationElement WaitForItem(params string[] path) { + public AutomationElement WaitForItem(params string[] path) + { // WaitForItem doesn't work well with offscreen items // so we use the search bar to filter by function name to // limit the items on screen and then expand all tree items. @@ -183,7 +219,8 @@ public AutomationElement WaitForItem(params string[] path) { // it multiple times with delay as a work around. _searchBar.SetValue(path[path.Length - 1]); - for (int i = 0; i < path.Length + 2; i++) { + for (int i = 0; i < path.Length + 2; i++) + { Tests.ExpandAll(); } @@ -193,7 +230,8 @@ public AutomationElement WaitForItem(params string[] path) { /// /// Run all tests and wait for the command to be available again. /// - public void RunAll(TimeSpan timeout) { + public void RunAll(TimeSpan timeout) + { ClearSearchBar(); _app.Dte.ExecuteCommand(TestCommands.RunAllTests); Thread.Sleep(100); @@ -203,7 +241,8 @@ public void RunAll(TimeSpan timeout) { /// /// Debug all tests and wait for the command to be available again. /// - public void DebugAll() { + public void DebugAll() + { _app.Dte.ExecuteCommand(TestCommands.DebugAllTests); Thread.Sleep(100); } diff --git a/azure-pipelines-integration-tests.yml b/azure-pipelines-integration-tests.yml index e4c805d11a..4757a046e6 100644 --- a/azure-pipelines-integration-tests.yml +++ b/azure-pipelines-integration-tests.yml @@ -2,7 +2,8 @@ trigger: none pr: none -# For more info about how this resources section works, see https://docs.microsoft.com/en-us/azure/devops/pipelines/process/resources?view=azure-devops&tabs=schema +# The following steps describe how to create a DartLab pipeline that installs Visual Studio using a bootstrapper generated by the MicroBuild Build VS Bootstrapper task +# in the component repo's MicroBuild: https://dev.azure.com/devdiv/DevDiv/_wiki/wikis/DevDiv.wiki/45681/Component-Repository resources: pipelines: @@ -10,7 +11,8 @@ resources: # All PTVS build artifacts come from this pipeline and are referenced like this: # $(Pipeline.Workspace)\ComponentBuildUnderTest\\ - pipeline: ComponentBuildUnderTest - source: PTVS-Build-Dev17 + project: DevDiv + source: Python\PTVS\PTVS-Build branch: main # This is only used for manual/scheduled runs of this pipeline trigger: branches: @@ -32,44 +34,41 @@ resources: stages: -- template: stages/visual-studio/single-runsettings.yml@DartLabTemplates +- template: stages/cloudtest/visual-studio/single-runsettings.yml@DartLabTemplates parameters: displayName: Integration Tests - variables: - - name: VisualStudio.InstallationUnderTest.BootstrapperBranch - value: main - testLabPoolName: Azure-and-Web - testMachineTotalCount: 1 + owner: ptvs + testMachineLab: DDRITs-PR # This assumes the PTVS build has published a build artifact called "RunSettings" that contains the default.runsettings file - runSettingsURI: $(Pipeline.Workspace)\ComponentBuildUnderTest\RunSettings\default.runsettings + runSettingsURI: https://vsdrop.microsoft.com/file/v1/$(RunSettings.DropName);default.runsettings visualStudioBootstrapperURI: $(VisualStudio.InstallationUnderTest.BootstrapperURL) visualStudioSigning: Test - + testMachineConfigurationJobVariables: + - name: VisualStudio.InstallationUnderTest.BootstrapperBranch + value: main # These steps run on the machine that is creating the test machine configuration, which isn't the same # as the machine running the actual tests - preTestMachineConfigurationStepList: - + preTestMachineConfigurationSteps: + - download: ComponentBuildUnderTest artifact: MicroBuildOutputs patterns: '**\BootstrapperInfo.json' displayName: Download Bootstrapper Information - - - download: ComponentBuildUnderTest - artifact: RunSettings - patterns: '**\default.runsettings' - displayName: Download RunSettings - + - task: PowerShell@2 displayName: Set 'VisualStudio.InstallationUnderTest.BootstrapperURL' inputs: filePath: $(DartLab.Path)\Scripts\VisualStudio\Bootstrapper\Get-BootstrapperURL.ps1 - # This assumes the PTVS build has published a build artifact called "MicroBuildOutputs" that contains the generated BootstrapperInfo.json arguments: -BootstrapperInfoJsonURI '$(Pipeline.Workspace)\ComponentBuildUnderTest\MicroBuildOutputs\BootstrapperInfo.json' -VSBranch '$(VisualStudio.InstallationUnderTest.BootstrapperBranch)' -OutVariableName 'VisualStudio.InstallationUnderTest.BootstrapperURL' - - # These steps run on the machine that is running the tests - preDeployAndRunTestsStepList: - download: ComponentBuildUnderTest - artifact: RunSettings - patterns: '**\default.runsettings' - displayName: Download RunSettings + artifact: PTVS-TestData + patterns: '**\VSTSDrop.json' + displayName: Download drop Information + + - template: \steps\powershell\execute-script.yml@DartLabTemplates + parameters: + displayName: Set 'RunSettings.DropName' + filePath: $(DartLab.Path)\Scripts\AzureDevOps\Artifacts\Drop\Get-DropName.ps1 + arguments: -VSTSDropJsonURI '$(Pipeline.Workspace)\ComponentBuildUnderTest\PTVS-TestData\VSTSDrop.json' -OutVariableName 'RunSettings.DropName' + \ No newline at end of file diff --git a/azure-pipelines-integration-testsgate.yml b/azure-pipelines-integration-testsgate.yml new file mode 100644 index 0000000000..b6c17dc596 --- /dev/null +++ b/azure-pipelines-integration-testsgate.yml @@ -0,0 +1,211 @@ +# Don't trigger ci or pr builds +trigger: none +pr: none + +# The following steps describe how to create a DartLab pipeline that installs Visual Studio using a bootstrapper generated by the MicroBuild Build VS Bootstrapper task +# in the component repo's MicroBuild: https://dev.azure.com/devdiv/DevDiv/_wiki/wikis/DevDiv.wiki/45681/Component-Repository +resources: + + pipelines: + + # All PTVS build artifacts come from this pipeline and are referenced like this: + # $(Pipeline.Workspace)\ComponentBuildUnderTest\\ + - pipeline: ComponentBuildUnderTest + project: DevDiv + source: Python\PTVS\PTVS-Build + + trigger: + branches: + include: + - main + - release/* + + - pipeline: DartLab + project: DevDiv + source: DartLab + branch: main + + repositories: + + - repository: DartLabTemplates + type: git + name: DartLab.Templates + ref: refs/heads/main + +stages: + +- template: stages/cloudtest/visual-studio/single-runsettings.yml@DartLabTemplates + parameters: + displayName: Integration Tests + owner: ptvs + testMachineLab: DDRITs-PR + # This assumes the PTVS build has published a build artifact called "RunSettings" that contains the default.runsettings file + runSettingsURI: https://vsdrop.microsoft.com/file/v1/$(RunSettings.DropName);ptvs.runsettings + visualStudioBootstrapperURI: $(VisualStudio.InstallationUnderTest.BootstrapperURL) + visualStudioSigning: Test + testMachineConfigurationJobVariables: + - name: VisualStudio.InstallationUnderTest.BootstrapperBranch + value: main + # These steps run on the machine that is creating the test machine configuration, which isn't the same + # as the machine running the actual tests + preTestMachineConfigurationSteps: + + - download: ComponentBuildUnderTest + artifact: MicroBuildOutputs + patterns: '**\BootstrapperInfo.json' + displayName: Download Bootstrapper Information + + - task: PowerShell@2 + displayName: Set 'VisualStudio.InstallationUnderTest.BootstrapperURL' + inputs: + filePath: $(DartLab.Path)\Scripts\VisualStudio\Bootstrapper\Get-BootstrapperURL.ps1 + arguments: -BootstrapperInfoJsonURI '$(Pipeline.Workspace)\ComponentBuildUnderTest\MicroBuildOutputs\BootstrapperInfo.json' -VSBranch '$(VisualStudio.InstallationUnderTest.BootstrapperBranch)' -OutVariableName 'VisualStudio.InstallationUnderTest.BootstrapperURL' + + - download: ComponentBuildUnderTest + artifact: PTVS-TestData + patterns: '**\*' + displayName: Download drop Information + + - download: ComponentBuildUnderTest + artifact: TestDataFolder + patterns: '**\*' + displayName: Download TestDataFolder Information + + - download: ComponentBuildUnderTest + artifact: Binaries + patterns: '**\*' + displayName: Download Binaries + + - task: PowerShell@2 + displayName: List downloaded files before setting 'RunSettings.DropName' + inputs: + targetType: inline + script: | + Write-Host "Pipeline.Workspace: $(Pipeline.Workspace)" + Write-Host "System.DefaultWorkingDirectory: $(System.DefaultWorkingDirectory)" + + $componentRoot = Join-Path "$(Pipeline.Workspace)" "ComponentBuildUnderTest" + + function Write-RecursiveListing { + param( + [Parameter(Mandatory = $true)][string]$RootPath, + [Parameter(Mandatory = $true)][string]$Title + ) + + Write-Host "" + Write-Host "==== $Title ====" + Write-Host "Root: $RootPath" + + if (-not (Test-Path -LiteralPath $RootPath)) { + Write-Warning "Path not found: $RootPath" + return + } + + Write-Host "Top-level entries:" + Get-ChildItem -LiteralPath $RootPath -Force | + Select-Object Name, FullName, Mode, Length, LastWriteTime | + Sort-Object FullName | + Format-Table -AutoSize + + Write-Host "" + Write-Host "All files (recursive):" + $allFiles = Get-ChildItem -LiteralPath $RootPath -Recurse -Force -File -ErrorAction SilentlyContinue + if ($allFiles) { + $allFiles | + Select-Object FullName, Length, LastWriteTime | + Sort-Object FullName | + Format-Table -AutoSize + Write-Host "Total files: $($allFiles.Count)" + } else { + Write-Warning "No files found under: $RootPath" + } + + Write-Host "" + Write-Host "All directories (recursive):" + $allDirs = Get-ChildItem -LiteralPath $RootPath -Recurse -Force -Directory -ErrorAction SilentlyContinue + if ($allDirs) { + $allDirs | + Select-Object FullName, LastWriteTime | + Sort-Object FullName | + Format-Table -AutoSize + Write-Host "Total directories: $($allDirs.Count)" + } else { + Write-Warning "No directories found under: $RootPath" + } + } + + Write-RecursiveListing -RootPath $componentRoot -Title "Downloaded artifacts under ComponentBuildUnderTest" + + Write-Host "" + Write-Host "Searching for VSTSDrop.json under: $componentRoot" + if (Test-Path -LiteralPath $componentRoot) { + $matches = Get-ChildItem -LiteralPath $componentRoot -Recurse -Force -File -Filter "VSTSDrop.json" -ErrorAction SilentlyContinue + if ($matches) { + $matches | Select-Object FullName, Length, LastWriteTime | Sort-Object FullName | Format-Table -AutoSize + } else { + Write-Warning "No VSTSDrop.json found under: $componentRoot" + } + } else { + Write-Warning "Path not found: $componentRoot" + } + + - task: PowerShell@2 + displayName: Find VSTSDrop.json path + inputs: + targetType: inline + script: | + $componentRoot = Join-Path "$(Pipeline.Workspace)" "ComponentBuildUnderTest" + Write-Host "Searching for VSTSDrop.json under: $componentRoot" + if (-not (Test-Path -LiteralPath $componentRoot)) { + throw "ComponentBuildUnderTest root not found: $componentRoot" + } + + $matches = Get-ChildItem -LiteralPath $componentRoot -Recurse -Force -File -Filter "VSTSDrop.json" -ErrorAction SilentlyContinue + if (-not $matches) { + throw "No VSTSDrop.json found under: $componentRoot" + } + + if ($matches.Count -gt 1) { + Write-Warning "Multiple VSTSDrop.json files found; selecting the most recent." + $matches | Select-Object FullName, Length, LastWriteTime | Sort-Object LastWriteTime -Descending | Format-Table -AutoSize + } + + $selected = $matches | Sort-Object LastWriteTime -Descending | Select-Object -First 1 + Write-Host "Selected VSTSDrop.json: $($selected.FullName)" + Write-Host "##vso[task.setvariable variable=VSTSDropJsonURI]$($selected.FullName)" + + + - template: Build/azuredevops/test/uitest-integration-stage.yml + parameters: + BinariesDirectory: $(Pipeline.Workspace)\ComponentBuildUnderTest\Binaries + Drop: $(Pipeline.Workspace)\ComponentBuildUnderTest\TestDataFolder + UITestNames: PythonTools + + - template: \steps\powershell\execute-script.yml@DartLabTemplates + parameters: + displayName: Set 'RunSettings.DropName' + filePath: $(DartLab.Path)\Scripts\AzureDevOps\Artifacts\Drop\Get-DropName.ps1 + arguments: -VSTSDropJsonURI '$(VSTSDropJsonURI)' -OutVariableName 'RunSettings.DropName' + + - task: PowerShell@2 + displayName: Debug arguments for 'Set RunSettings.DropName' + inputs: + targetType: inline + script: | + Write-Host "Resolved arguments for Get-DropName.ps1:" + Write-Host " -VSTSDropJsonURI '$($("VSTSDropJsonURI"))'" + Write-Host " -OutVariableName 'RunSettings.DropName'" + Write-Host "" + Write-Host "Raw argument string (as authored in YAML):" + Write-Host " -VSTSDropJsonURI '$(VSTSDropJsonURI)' -OutVariableName 'RunSettings.DropName'" + Write-Host "" + $path = "$(VSTSDropJsonURI)" + Write-Host "VSTSDropJsonURI points to: $path" + if ([string]::IsNullOrWhiteSpace($path)) { + Write-Warning "VSTSDropJsonURI is empty." + } elseif (Test-Path -LiteralPath $path) { + Write-Host "VSTSDropJsonURI exists on disk." + } else { + Write-Warning "VSTSDropJsonURI does not exist on disk (it may be a URI or incorrect path)." + } + \ No newline at end of file diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 2d7b2e49aa..b48fdf8d0e 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -1,47 +1,51 @@ -# This pipeline is used to build the PTVS product and installer. +# This pipeline is used to build the PTVS product and installer. # A seperate release pipeline is used to create insertion PR's into Visual Studio. # The pipeline extends v1/1ES.Official.PipelineTemplate.yml@1ESPipelineTemplates from 1esPipelines repository defined in resources section. parameters: + - name: pylanceVersion + displayName: Pylance Version + type: string + default: latest + + - name: pylanceReleaseType + displayName: Pylance Release Type + type: string + default: stable + values: + - stable + - preview + + - name: debugpyVersion + displayName: Debugpy Version + type: string + default: latest -- name: pylanceVersion - displayName: Pylance Version - type: string - default: latest - -- name: pylanceReleaseType - displayName: Pylance Release Type - type: string - default: stable - values: - - stable - - preview - -- name: debugpyVersion - displayName: Debugpy Version - type: string - default: latest - -- name: PublishNugetPackageAsBuildArtifact - displayName: Publish Nuget Package As Build Artifact - type: boolean - default: false - -# This is the version that the PTVS package currently being built will have. -# If this value is set to 'currentBuildNumber' will default to $(Build.BuildNumber). -# But this parameter can be used to overwrite the version number if needed. -- name: ptvsPackageVersion - displayName: PTVS Package Version - type: string - default: currentBuildNumber - -- name: skipGlassCache - displayName: Skip Glass Cache - type: boolean - default: false - -# build number format + - name: PublishNugetPackageAsBuildArtifact + displayName: Publish Nuget Package As Build Artifact + type: boolean + default: false + + # This is the version that the PTVS package currently being built will have. + # If this value is set to 'currentBuildNumber' will default to $(Build.BuildNumber). + # But this parameter can be used to overwrite the version number if needed. + - name: ptvsPackageVersion + displayName: PTVS Package Version + type: string + default: currentBuildNumber + + - name: skipGlassCache + displayName: Skip Glass Cache + type: boolean + default: false + + - name: skipSigning + displayName: Skip Signing + type: boolean + default: true + +# build number format name: $(date:yy)$(DayOfYear)$(rev:.r) # Trigger ci builds for commits into master and any release branches @@ -53,7 +57,7 @@ trigger: - release/* paths: exclude: - - 'azure-pipelines-*.yml' + - "azure-pipelines-*.yml" # Trigger pr builds for commits into master and any release branches # Ignore changes to other yml files, since they are for different pipelines @@ -65,19 +69,19 @@ pr: - release/* paths: exclude: - - 'azure-pipelines-*.yml' + - "azure-pipelines-*.yml" drafts: false # Trigger builds on a nightly schedule # Always run, even if there are no PTVS changes, because we want the latest changes from all dependencies # such as pylance, debugpy, and the latest VS int-preview bits pulled into our bootstrapper. schedules: -- cron: "0 8 * * *" - displayName: Nightly build - branches: - include: - - main - always: true + - cron: "0 8 * * *" + displayName: Nightly build + branches: + include: + - main + always: true # Build variables # None of these are settable at build queue time. To do that, remove the variable from this list, @@ -98,7 +102,7 @@ variables: - name: TrackFileAccess value: false - name: Packaging.EnableSBOMSigning - value: false # disabled for now because of known issue + value: false # disabled for now because of known issue - name: SkipGlassCache value: ${{ parameters.skipGlassCache }} - name: PublishNugetPackageAsBuildArtifact @@ -110,7 +114,7 @@ variables: value: preview ${{ else }}: value: ${{ parameters.pylanceReleaseType }} - + # If the vs package version is not specified, use the build number - name: ptvsPackageVersionVar ${{ if eq(parameters.ptvsPackageVersion, 'currentBuildNumber') }}: @@ -118,6 +122,13 @@ variables: ${{ else }}: value: ${{ parameters.ptvsPackageVersion }} + # Skip signing for PR builds by default, use parameter override for manual builds + - name: skipSigningVar + ${{ if eq(variables['Build.Reason'], 'PullRequest') }}: + value: true + ${{ else }}: + value: ${{ parameters.skipSigning }} + # Import variables from PTVS-Dev18 variable group - group: PTVS-Dev17 @@ -125,144 +136,199 @@ variables: # The ref of the repository is set to release tag which is intended to be used by most pipelines. resources: repositories: - - repository: 1ESPipelineTemplates - type: git - name: 1ESPipelineTemplates/1ESPipelineTemplates - ref: refs/tags/release + - repository: 1ESPipelineTemplates + type: git + name: 1ESPipelineTemplates/1ESPipelineTemplates + ref: refs/tags/release extends: template: v1/1ES.Official.PipelineTemplate.yml@1ESPipelineTemplates parameters: - # The pool includes the name of your 1ES hosted pool and a VM image in that pool. Also, use os to - # specify the image type. Here are the allowed values: windows, linux, or macOS. The default value is windows. + # The pool includes the name of your 1ES hosted pool and a VM image in that pool. Also, use os to + # specify the image type. Here are the allowed values: windows, linux, or macOS. The default value is windows. # Hence, this property must be specified for linux and macOS. pool: - name: VSEngSS-MicroBuild2022-1ES - os: windows + name: AzurePipelines-EO + image: 1ESPT-Windows2022 settings: skipBuildTagsForGitHubPullRequests: true stages: - - stage: build - displayName: Build - jobs: - - job: build - # Set pipeline timeout to 2 hours (120 minutes) - timeoutInMinutes: 120 + - stage: build displayName: Build - # If the pipeline publishes artifacts, use `templateContext` to define the artifacts. - # This will enable 1ES PT to run SDL analysis tools on the artifacts and then upload them. - templateContext: - # Disable code signing validation because we don't ship ANY of the artifacts that we publish. - # The only released artifacts are uploaded via the 1ES.MicroBuildVstsDrop@1 below. - sdl: - codeSignValidation: - enabled: false - outputs: - - output: pipelineArtifact - displayName: 'Publish build artifact: binaries' - targetPath: '$(Build.BinariesDirectory)/raw/binaries' - artifactName: Binaries - - output: pipelineArtifact - displayName: 'Publish build artifact: raw' - condition: failed() - targetPath: '$(Build.BinariesDirectory)\raw' - artifactName: raw - - output: pipelineArtifact - displayName: 'Publish build artifact: logs' - condition: succeededOrFailed() - targetPath: '$(Build.SourcesDirectory)\logs' - artifactName: Logs - - output: pipelineArtifact - displayName: 'Publish build artifact: TestData' - targetPath: '$(Build.ArtifactStagingDirectory)/TestDataFolder/TestData.zip' - sbomBuildDropPath: '$(Build.ArtifactStagingDirectory)/TestDataFolder' - artifactName: 'TestData' - - output: pipelineArtifact - displayName: 'Publish build artifact: RunSettings' - targetPath: '$(Build.SourcesDirectory)/Python/Tests/TestData/default.runsettings' - sbomBuildDropPath: '$(Build.SourcesDirectory)/Python/Tests/TestData' - artifactName: 'RunSettings' - - ${{ if notin(variables['Build.Reason'], 'PullRequest') }}: - - output: pipelineArtifact - displayName: 'Publish build artifact: BoM' - targetPath: '$(Build.BinariesDirectory)\layout' - artifactName: SBOM - - ${{ if or(notin(variables['Build.Reason'], 'PullRequest'), eq(variables['PublishNugetPackageAsBuildArtifact'], true)) }}: - - output: pipelineArtifact - displayName: 'Publish build artifact: NuGet Package' - targetPath: '$(Build.ArtifactStagingDirectory)\pkg' - artifactName: pkg - - steps: - - # check out code clean from source control - - checkout: self - clean: true - - # Non-PR steps - - ${{ if notin(variables['Build.Reason'], 'PullRequest') }}: - - # add VSTarget build tag - - powershell: 'Write-Host "##vso[build.addbuildtag]$env:VSTarget"' - displayName: 'Add vstarget build tag' - - # install microbuild plugins used for swixproj/vsmanproj, signing, and localization - - template: /Build/templates/install_microbuild_plugins.yml@self - - # Restore packages and install dependencies (pylance, debugpy) - - template: /Build/templates/restore_packages.yml@self - parameters: - pylanceVersion: ${{ parameters.pylanceVersion }} - pylanceReleaseType: ${{ variables.pylanceReleaseTypeVar }} - debugpyVersion: ${{ parameters.debugpyVersion }} - - # Build and publish logs - - template: /Build/templates/build.yml@self - parameters: - ptvsPackageVersion: ${{ variables.ptvsPackageVersionVar }} - - # Non-PR steps - - ${{ if notin(variables['Build.Reason'], 'PullRequest') }}: - - # Create VS bootstrapper for testing - - template: Build/templates/create_vs_bootstrapper.yml@self - - # Upload vsts drop used by Visual Studio insertions - # For more info, see https://eng.ms/docs/cloud-ai-platform/devdiv/one-engineering-system-1es/1es-docs/1es-pipeline-templates/features/outputs/microbuild-vsts-drop - - task: 1ES.MicroBuildVstsDrop@1 - displayName: 'Upload vsts drop' - inputs: - dropFolder: '$(Build.StagingDirectory)\release' - dropServiceUri: 'https://devdiv.artifacts.visualstudio.com/DefaultCollection' - vsDropServiceUri: 'https://vsdrop.corp.microsoft.com/file/v1' - accessToken: '$(System.AccessToken)' - dropRetentionDays: 183 - - # publish symbols - - template: /Build/templates/publish_symbols.yml@self - - # Build and publish nuget package used by VS - - template: /Build/templates/build_nuget_package.yml@self - parameters: - ptvsPackageVersion: ${{ variables.ptvsPackageVersionVar }} - - # MicroBuild cleanup - - task: MicroBuildCleanup@1 - displayName: 'Execute cleanup tasks' - condition: succeededOrFailed() - - # Publish test data - - template: /Build/templates/publish_test_data.yml@self - - # Run tests on mixed mode debugger but only for PR builds - # - ${{ if or(eq(variables['Build.Reason'], 'PullRequest'), eq(variables['SkipGlassCache'], true)) }}: - # - job: test - # displayName: Test - # steps: - # - template: /Build/templates/run_tests.yml@self - # parameters: - # skipGlassCache: ${{ parameters.skipGlassCache }} - - - - + jobs: + - job: build + # Set pipeline timeout to 2 hours (120 minutes) + timeoutInMinutes: 120 + displayName: Build + variables: + BootloaderDropName: "Bootloader/$(System.TeamProject)/$(Build.BuildNumber)/$(Build.BuildId)" + # If the pipeline publishes artifacts, use `templateContext` to define the artifacts. + # This will enable 1ES PT to run SDL analysis tools on the artifacts and then upload them. + templateContext: + isProduction: false + # Disable code signing validation because we don't ship ANY of the artifacts that we publish. + # The only released artifacts are uploaded via the 1ES.MicroBuildVstsDrop@1 below. + sdl: + codeql: + # disable if not commit in main or release + ${{ if or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), startsWith(variables['Build.SourceBranch'], 'refs/heads/release/')) }}: + enabled: true + ${{ else }}: + enabled: false + codeSignValidation: + enabled: false + sbom: + enabled: false # Disable global SBOM generation; we'll enable selectively per artifact output + outputs: + # - output: artifactsDrop # upload to artifact drop service for azure_pipelines_integration_tests.yml pipeline + # displayName: 'Upload MicroBuild to Artifact Services' + # sourcePath: $(Build.ArtifactStagingDirectory)\MicroBuild\Output + # dropServiceURI: https://devdiv.artifacts.visualstudio.com/DefaultCollection/ + # dropMetadataContainerName: MicroBuildOutputs + # buildNumber: '$(BootloaderDropName)' + - output: pipelineArtifact + displayName: 📢 Publish MicroBuildOutputs + targetPath: $(Build.ArtifactStagingDirectory)\MicroBuild\Output + artifactName: MicroBuildOutputs + - output: pipelineArtifact + displayName: "Publish build artifact: binaries" + targetPath: "$(Build.BinariesDirectory)/raw/binaries" + artifactName: Binaries + - output: pipelineArtifact + displayName: "Publish build artifact: raw" + condition: failed() + targetPath: '$(Build.BinariesDirectory)\raw' + artifactName: raw + - output: pipelineArtifact + displayName: "Publish build artifact: logs" + condition: succeededOrFailed() + targetPath: '$(Build.SourcesDirectory)\logs' + artifactName: Logs + - ${{ if notin(variables['Build.Reason'], 'PullRequest') }}: + - output: pipelineArtifact + displayName: "Publish build artifact: BoM" + targetPath: '$(Build.BinariesDirectory)\layout' + artifactName: SBOM + - ${{ if or(notin(variables['Build.Reason'], 'PullRequest'), eq(variables['PublishNugetPackageAsBuildArtifact'], true)) }}: + - output: pipelineArtifact + displayName: "Publish build artifact: NuGet Package" + targetPath: '$(Build.ArtifactStagingDirectory)\pkg' + artifactName: pkg + + steps: + # check out code clean from source control + - checkout: self + clean: true + fetchDepth: 1 + persistCredentials: true + + # Non-PR steps + - ${{ if notin(variables['Build.Reason'], 'PullRequest') }}: + # add VSTarget build tag + - powershell: 'Write-Host "##vso[build.addbuildtag]$env:VSTarget"' + displayName: "Add vstarget build tag" + + # install microbuild plugins used for swixproj/vsmanproj, signing, and localization + - template: /Build/templates/install_microbuild_plugins.yml@self + + # Restore packages and install dependencies (pylance, debugpy) + - template: /Build/templates/restore_packages.yml@self + parameters: + pylanceVersion: ${{ parameters.pylanceVersion }} + pylanceReleaseType: ${{ variables.pylanceReleaseTypeVar }} + debugpyVersion: ${{ parameters.debugpyVersion }} + + # Build and publish logs + - template: /Build/templates/build.yml@self + parameters: + ptvsPackageVersion: ${{ variables.ptvsPackageVersionVar }} + skipSigning: ${{ variables.skipSigningVar }} + + # Non-PR steps + # - ${{ if notin(variables['Build.Reason'], 'PullRequest') }}: + # Create VS bootstrapper for testing + - template: Build/templates/create_vs_bootstrapper.yml@self + + # Upload vsts drop used by Visual Studio insertions + # For more info, see https://eng.ms/docs/cloud-ai-platform/devdiv/one-engineering-system-1es/1es-docs/1es-pipeline-templates/features/outputs/microbuild-vsts-drop + - task: 1ES.MicroBuildVstsDrop@1 + displayName: "Upload vsts drop" + inputs: + dropFolder: '$(Build.StagingDirectory)\release' + dropServiceUri: "https://devdiv.artifacts.visualstudio.com/DefaultCollection" + vsDropServiceUri: "https://vsdrop.corp.microsoft.com/file/v1" + accessToken: "$(System.AccessToken)" + dropRetentionDays: 183 + + # publish symbols + - template: /Build/templates/publish_symbols.yml@self + + # Build and publish nuget package used by VS + - template: /Build/templates/build_nuget_package.yml@self + parameters: + ptvsPackageVersion: ${{ variables.ptvsPackageVersionVar }} + + # MicroBuild cleanup + - task: MicroBuildCleanup@1 + displayName: "Execute cleanup tasks" + condition: succeededOrFailed() + + # Separate job for TestData generation - runs in parallel with build job + - job: testdata + displayName: Publish TestData + variables: + TestDataDropName: "devdiv/ptvs/tests/$(Build.BuildNumber)/$(Build.BuildId)" + TestStoreDropName: "$(TestDataDropName)" + templateContext: + isProduction: false + sdl: + codeSignValidation: + enabled: false + sbom: + enabled: false + outputs: + - output: pipelineArtifact + displayName: 📢 Publish PTVS-TestData + targetPath: $(Build.ArtifactStagingDirectory)/TestDataFolder/ + artifactName: TestDataFolder + - output: artifactsDrop # upload to artifact drop service for azure_pipelines_integration_tests.yml pipeline + displayName: "Upload Test Data to Artifact Services" + sourcePath: $(Build.ArtifactStagingDirectory)/TestDataFolder + dropServiceURI: https://devdiv.artifacts.visualstudio.com/DefaultCollection/ + buildNumber: "$(TestDataDropName)" + dropMetadataContainerName: PTVS-TestData + - output: pipelineArtifact + displayName: "Publish build artifact: TestData" + targetPath: "$(Build.ArtifactStagingDirectory)/TestDataFolder/TestData.zip" + artifactName: "TestData" + # - output: pipelineArtifact + # displayName: "Publish build artifact: RunSettings" + # targetPath: "$(Build.SourcesDirectory)/Python/Tests/TestData/default.runsettings" + # artifactName: "RunSettings" + + steps: + # check out code clean from source control + - checkout: self + clean: true + fetchDepth: 1 + persistCredentials: true + + # Publish test data + - template: /Build/templates/publish_test_data.yml@self + + # Copy runsettings to TestDataFolder for azure_pipelines_integration_tests.yml pipeline + # - task: CopyFiles@2 + # displayName: "Copy runsettings to TestDataFolder" + # inputs: + # SourceFolder: "$(Build.SourcesDirectory)/Python/Tests/TestData" + # Contents: "DDRITs.runsettings" + # TargetFolder: "$(Build.ArtifactStagingDirectory)/TestDataFolder" + + # Run tests on mixed mode debugger but only for PR builds + # - ${{ if or(eq(variables['Build.Reason'], 'PullRequest'), eq(variables['SkipGlassCache'], true)) }}: + # - job: test + # displayName: Test + # steps: + # - template: /Build/templates/run_tests.yml@self + # parameters: + # skipGlassCache: ${{ parameters.skipGlassCache }} diff --git a/package.json b/package.json index befda4439b..30b28f16c4 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,6 @@ "name": "ptvs", "private": true, "devDependencies": { - "@pylance/pylance": "2025.9.1" + "@pylance/pylance": "2025.10.4" } }