This is an automated email from the ASF dual-hosted git repository. nightowl888 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/lucenenet.git
commit 9f3fb72eb8678cd5e41326e4f26b6c83a928bc59 Author: Shad Storhaug <[email protected]> AuthorDate: Sun Jul 14 02:12:20 2019 +0700 Created azure-pipelines.yml for Azure DevOps --- Directory.Build.props | 10 + Directory.Build.targets | 27 ++ Lucene.Net.sln | 10 +- azure-pipelines.yml | 377 +++++++++++++++++++++ build/Dependencies.props | 20 ++ build/TestReferences.Common.targets | 20 ++ build/azure-templates/publish-nuget-packages.yml | 64 ++++ .../publish-test-results-for-target-frameworks.yml | 67 ++++ .../publish-test-results-for-test-projects.yml | 282 +++++++++++++++ build/azure-templates/publish-test-results.yml | 81 +++++ build/azure-templates/run-tests-on-os.yml | 211 ++++++++++++ .../show-all-environment-variables.yml | 28 ++ build/azure-templates/show-all-files.yml | 26 ++ build/build.ps1 | 314 ++++++++++++----- .../Analysis/Th/TestThaiAnalyzer.cs | 42 +++ 15 files changed, 1496 insertions(+), 83 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 31f0f94..16f9c18 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -37,6 +37,9 @@ <PropertyGroup Label="NuGet Package Defaults"> <IsPackable>false</IsPackable> + <IncludeSymbols>true</IncludeSymbols> + <!-- This is the new symbols format (the only one currently supported at NuGet.org) --> + <SymbolPackageFormat>snupkg</SymbolPackageFormat> </PropertyGroup> <PropertyGroup Label="Copyright Info"> @@ -48,4 +51,11 @@ <CopyrightYearRange Condition=" '$(BeginCopyrightYear)' == '$(CurrentYear)' ">$(CurrentYear)</CopyrightYearRange> <Copyright>Copyright © $(CopyrightYearRange) $(Company)</Copyright> </PropertyGroup> + + <!-- Settings to override the above Version of Builds. These can be used to + "freeze" the build number for a release, so whether building within + an IDE or from the commmand line, the version is always what is + in Version.props, if it exists and the PrepareForBuild argument + passed into build.ps1 is 'false'. --> + <Import Project="Version.props" Condition="Exists('Version.props')" /> </Project> \ No newline at end of file diff --git a/Directory.Build.targets b/Directory.Build.targets new file mode 100644 index 0000000..04e1c76 --- /dev/null +++ b/Directory.Build.targets @@ -0,0 +1,27 @@ +<!-- + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + +--> +<Project> + <PropertyGroup> + <!-- NuGet.org only supports portable debug symbol format: + https://docs.microsoft.com/en-us/nuget/create-packages/symbol-packages-snupkg#nugetorg-symbol-package-constraints --> + <DebugType Condition=" '$(PortableDebugTypeOnly)' == 'true' ">portable</DebugType> + </PropertyGroup> +</Project> \ No newline at end of file diff --git a/Lucene.Net.sln b/Lucene.Net.sln index 904843e..bde08f5 100644 --- a/Lucene.Net.sln +++ b/Lucene.Net.sln @@ -1,4 +1,3 @@ - Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 @@ -30,6 +29,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "azure-templates", "azure-te build\azure-templates\run-tests-on-os.yml = build\azure-templates\run-tests-on-os.yml build\azure-templates\show-all-environment-variables.yml = build\azure-templates\show-all-environment-variables.yml build\azure-templates\show-all-files.yml = build\azure-templates\show-all-files.yml + build\azure-templates\publish-test-results.yml = build\azure-templates\publish-test-results.yml + build\azure-templates\publish-test-results-for-target-frameworks.yml = build\azure-templates\publish-test-results-for-target-frameworks.yml + build\azure-templates\publish-test-results-for-test-projects.yml = build\azure-templates\publish-test-results-for-test-projects.yml + build\azure-templates\run-tests-on-os.yml = build\azure-templates\run-tests-on-os.yml + build\azure-templates\show-all-environment-variables.yml = build\azure-templates\show-all-environment-variables.yml + build\azure-templates\show-all-files.yml = build\azure-templates\show-all-files.yml EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dotnet", "dotnet", "{8CA61D33-3590-4024-A304-7B1F75B50653}" @@ -39,6 +44,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dotnet", "dotnet", "{8CA61D EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{4016BDAB-6C33-4D1E-9439-57B416EA45D5}" ProjectSection(SolutionItems) = preProject + azure-pipelines.yml = azure-pipelines.yml build.bat = build.bat build\build.ps1 = build\build.ps1 build\Dependencies.props = build\Dependencies.props @@ -64,6 +70,7 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{4DF0A2A1-B9C7-4EE5-BAF0-BEEF53E34220}" ProjectSection(SolutionItems) = preProject Directory.Build.props = Directory.Build.props + Directory.Build.targets = Directory.Build.targets EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lucene.Net", "src\Lucene.Net\Lucene.Net.csproj", "{3A0AA37E-2B7B-4416-B528-DA4E0E6A6706}" @@ -401,6 +408,7 @@ Global HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution + {05CE3A39-40D4-452D-AFE0-E57E536A08C6} = {4016BDAB-6C33-4D1E-9439-57B416EA45D5} {4DF7EACE-2B25-43F6-B558-8520BF20BD76} = {8CA61D33-3590-4024-A304-7B1F75B50653} {EFB2E31A-5917-49D5-A808-FE5061A550B4} = {8CA61D33-3590-4024-A304-7B1F75B50653} {119BBACD-D4DB-4E3B-922F-3DA83E0B29E2} = {4DF7EACE-2B25-43F6-B558-8520BF20BD76} diff --git a/azure-pipelines.yml b/azure-pipelines.yml new file mode 100644 index 0000000..48ddfaf --- /dev/null +++ b/azure-pipelines.yml @@ -0,0 +1,377 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +name: 'vNext$(rev:.r)' # Format for build number (will be overridden) + +# DevOps Setup: Define the following pipeline level variables in Azure DevOps build pipeline +# +# ArtifactFeedID: (Optional - set to your Azure DevOps Artifact (NuGet) feed. If not provided, publish job will be skipped.) +# BuildConfiguration: (Optional. Defaults to 'Release') +# BuildPlatform: (Optional. Defaults to 'Any CPU') +# IsRelease: (Optional. By default the Release job is disabled, setting this to 'true' will enable it) +# RunTests: 'true' (Optional - set to 'false' to disable test jobs - useful for debugging. If not provided, tests will be run.) + +# Versioning Variables + +# BuildCounterSeed: (Optional - Set in conjunction with VersionSuffix, will cause the build counter to begin at this value. Note that it is set once, to reset is an API call.) +# PackageVersion: (Optional - This can be used to explicitly set the whole version number to a specific version, i.e. 4.8.0-beta00005. It overrides all other version settings.) +# PreReleaseCounterPattern: (Optional. Set to '0000000000' in ci pipeline or '00000' in release pipeline. The default is '0000000000'. This setting has no effect if VersionSuffix is ''.) +# VersionSuffix: (Optional. Defaults to 'ci'. Set to 'beta' or 'rc' or '' in production pipeline.) + +variables: +- name: BuildCounter + value: $[counter(variables['VersionSuffix'],coalesce(variables['BuildCounterSeed'], 1250))] +- name: BinaryArtifactName + value: 'testbinaries' +- name: NuGetArtifactName + value: 'nuget' +- name: ReleaseArtifactName + value: 'release' +- name: TestResultsArtifactName + value: 'testresults' +- name: VersionArtifactName + value: 'version' +- name: BuildNumberFileName + value: 'buildNumber.txt' +- name: PackageVersionFileName + value: 'packageVersion.txt' +- name: FileVersionFileName + value: 'fileVersion.txt' +- name: BuildDirectory # Where the build scripts and configs are + value: '$(System.DefaultWorkingDirectory)/build' +- name: PublishDirectory # Test binaries directory + value: '$(Build.ArtifactStagingDirectory)/$(BinaryArtifactName)' +- name: NuGetArtifactDirectory # NuGet binaries directory + value: '$(Build.ArtifactStagingDirectory)/$(NuGetArtifactName)' +- name: PublishedArtifactZipFileName + value: 'published.zip' + +stages: +- stage: Build_Stage + displayName: 'Build Stage:' + jobs: + + - job: Build + pool: + vmImage: 'windows-2019' + + variables: + PublishTempDirectory: '$(Build.BinariesDirectory)/publish' + + steps: + - powershell: | + $configuration = if ($env:BUILDCONFIGURATION) { $env:BUILDCONFIGURATION } else { "Release" } + Write-Host "##vso[task.setvariable variable=BuildConfiguration;]$configuration" + displayName: 'Setup Default Variable Values' + + - task: DotNetCoreInstaller@0 + displayName: 'Use .NET Core sdk 2.2.300' + inputs: + version: 2.2.300 + + - powershell: | + Import-Module "$(BuildDirectory)/psake.psm1" + $generateBuildBat = if ($Env:ISRELEASE -eq 'true') { 'true' } else { 'false' } + $parameters = @{} + $properties = @{ + backup_files='false'; + publish_directory='$(PublishTempDirectory)'; + nuget_package_directory='$(NuGetArtifactDirectory)' + # Lock the build.bat so it only builds this version in the release distribution + generateBuildBat=$generateBuildBat + } + [string[]]$tasks = 'Pack' + if ($Env:RunTests -ne 'false') { + [string[]]$tasks = 'Pack','Publish' + } + Invoke-psake $(BuildDirectory)/build.ps1 -Task $tasks -properties $properties -parameters $parameters + exit !($psake.build_success) + displayName: 'PSake Build, Pack, and Publish' + + - template: 'build/azure-templates/show-all-environment-variables.yml' + + - task: ArchiveFiles@2 + displayName: 'Zip $(PublishTempDirectory)' + inputs: + rootFolderOrFile: '$(PublishTempDirectory)' + includeRootFolder: false + archiveFile: '$(PublishDirectory)/$(PublishedArtifactZipFileName)' + condition: and(succeeded(), ne(variables['RunTests'], 'false')) + + - powershell: | + $dir = '$(Build.ArtifactStagingDirectory)/$(VersionArtifactName)' + if (!(Test-Path $dir)) { New-Item -ItemType Directory -Path "$dir" -Force } + '$(PackageVersion)' | Out-File -FilePath "$dir/$(PackageVersionFileName)" -Force + '$(FileVersion)' | Out-File -FilePath "$dir/$(FileVersionFileName)" -Force + '$(Build.BuildNumber)' | Out-File -FilePath "$dir/$(BuildNumberFileName)" -Force + displayName: 'Write Versions to Files' + + # If this is a release pipeline, copy the build.bat and Version.props files as version artifacts, which will + # overwrite the build.bat and Version.props files of the release. + - task: CopyFiles@2 + displayName: 'Copy build.bat and Version.props Files to: /$(VersionArtifactName)' + inputs: + SourceFolder: '$(System.DefaultWorkingDirectory)' + Contents: | + build.bat + Version.props + TargetFolder: '$(Build.ArtifactStagingDirectory)/$(VersionArtifactName)' + condition: and(succeeded(), eq(variables['IsRelease'], 'true')) + + - task: PublishBuildArtifacts@1 + displayName: 'Publish Artifact: $(VersionArtifactName)' + inputs: + PathtoPublish: '$(Build.ArtifactStagingDirectory)/$(VersionArtifactName)' + ArtifactName: '$(VersionArtifactName)' + + # Copy the .pdb files as build artifacts, which will + # later be used to push to the Azure Artifacts symbol server. + - task: CopyFiles@2 + displayName: 'Copy .pdb Files to: /$(NuGetArtifactName)' + inputs: + SourceFolder: '$(System.DefaultWorkingDirectory)' + Contents: '**/bin/$(BuildConfiguration)/**/*.pdb' + TargetFolder: '$(Build.ArtifactStagingDirectory)/$(NuGetArtifactName)' + + - task: PublishBuildArtifacts@1 + displayName: 'Publish Artifact: $(BinaryArtifactName)' + inputs: + PathtoPublish: '$(Build.ArtifactStagingDirectory)/$(BinaryArtifactName)' + ArtifactName: '$(BinaryArtifactName)' + condition: and(succeeded(), ne(variables['RunTests'], 'false')) + + - task: PublishBuildArtifacts@1 + displayName: 'Publish Artifact: $(NuGetArtifactName)' + inputs: + PathtoPublish: '$(Build.ArtifactStagingDirectory)/$(NuGetArtifactName)' + ArtifactName: '$(NuGetArtifactName)' + + +- stage: Test_Stage + displayName: 'Test Stage:' + jobs: + - job: Test_netcoreapp2_1 + condition: and(succeeded(), ne(variables['RunTests'], 'false')) + strategy: + matrix: + Windows: + osName: 'Windows' + imageName: 'windows-2019' + maximumAllowedFailures: 4 # Maximum allowed failures for a successful build + Linux: + osName: 'Linux' + imageName: 'ubuntu-16.04' + maximumAllowedFailures: 30 # Maximum allowed failures for a successful build + macOS: + osName: 'macOS' + imageName: 'macOS-10.14' + maximumAllowedFailures: 30 # Maximum allowed failures for a successful build + displayName: 'Test netcoreapp2.1 on' + pool: + vmImage: $(imageName) + steps: + - template: 'build/azure-templates/run-tests-on-os.yml' + parameters: + osName: $(osName) + testTargetFrameworks: 'netcoreapp2.1' + testResultsArtifactName: '$(TestResultsArtifactName)' + publishedArtifactZipFileName: '$(PublishedArtifactZipFileName)' + maximumParallelJobs: 8 + maximumAllowedFailures: $(maximumAllowedFailures) + + - job: Test_netcoreapp1_0 + condition: and(succeeded(), ne(variables['RunTests'], 'false')) + strategy: + matrix: + Windows: + osName: 'Windows' + imageName: 'windows-2019' + maximumAllowedFailures: 4 # Maximum allowed failures for a successful build + Linux: + osName: 'Linux' + imageName: 'ubuntu-16.04' + maximumAllowedFailures: 30 # Maximum allowed failures for a successful build + macOS: + osName: 'macOS' + imageName: 'macOS-10.14' + maximumAllowedFailures: 30 # Maximum allowed failures for a successful build + displayName: 'Test netcoreapp1.0 on' + pool: + vmImage: $(imageName) + steps: + - template: 'build/azure-templates/run-tests-on-os.yml' + parameters: + osName: $(osName) + testTargetFrameworks: 'netcoreapp1.0' + testResultsArtifactName: '$(TestResultsArtifactName)' + publishedArtifactZipFileName: '$(PublishedArtifactZipFileName)' + maximumParallelJobs: 8 + maximumAllowedFailures: $(maximumAllowedFailures) + + - job: Test_net451 + condition: and(succeeded(), ne(variables['RunTests'], 'false')) + displayName: 'Test net451 on Windows' + pool: + vmImage: 'windows-2019' + steps: + - template: 'build/azure-templates/run-tests-on-os.yml' + parameters: + osName: 'Windows' + testTargetFrameworks: 'net451' + testResultsArtifactName: '$(TestResultsArtifactName)' + publishedArtifactZipFileName: '$(PublishedArtifactZipFileName)' + maximumParallelJobs: 8 + maximumAllowedFailures: 4 # Maximum allowed failures for a successful build + + +- stage: Publish_Stage + displayName: 'Publish Stage:' + jobs: + + # Optional job to push to Azure Artifact feed. Just pass in + # the GUID of the artifact feed as ArtifactFeedID to enable. + - job: Publish_Azure_Artifacts + condition: and(succeeded(), ne(variables['ArtifactFeedID'], '')) + pool: + vmImage: 'windows-2019' + + steps: + - template: 'build/azure-templates/show-all-environment-variables.yml' + + - task: DownloadBuildArtifacts@0 + displayName: 'Download Build Artifacts: $(VersionArtifactName)' + inputs: + artifactName: '$(VersionArtifactName)' + downloadPath: '$(Build.ArtifactStagingDirectory)' + + # NOTE: We are setting Build.BuildNumber here to the NuGet package version to work around the limitation that + # the version cannot be passed to the Index Sources & Publish Symbols task. + - powershell: | + $version = Get-Content '$(Build.ArtifactStagingDirectory)/$(VersionArtifactName)/$(PackageVersionFileName)' -Raw + Write-Host "##vso[task.setvariable variable=PackageVersion;]$version" + Write-Host "##vso[task.setvariable variable=Build.BuildNumber;]$version" + displayName: 'Read PackageVersion from File to Build.BuildNumber' + + - template: 'build/azure-templates/show-all-environment-variables.yml' + + - template: 'build/azure-templates/publish-nuget-packages.yml' + parameters: + artifactFeedID: '$(ArtifactFeedID)' + nugetArtifactName: '$(NuGetArtifactName)' + + +- stage: Release_Stage + displayName: 'Release Stage:' + jobs: + - job: Release + condition: and(succeeded(), eq(variables['IsRelease'], 'true')) + displayName: 'Build Release Artifacts for [VOTE]' + pool: + vmImage: 'windows-2019' + + steps: + - template: 'build/azure-templates/show-all-environment-variables.yml' + + - task: DownloadBuildArtifacts@0 + displayName: 'Download Build Artifacts: $(NuGetArtifactName)' + inputs: + artifactName: '$(NuGetArtifactName)' + downloadPath: '$(Build.ArtifactStagingDirectory)' + + - task: DownloadBuildArtifacts@0 + displayName: 'Download Build Artifacts: $(VersionArtifactName)' + inputs: + artifactName: '$(VersionArtifactName)' + downloadPath: '$(Build.ArtifactStagingDirectory)' + + - template: 'build/azure-templates/show-all-files.yml' # Uncomment for debugging + + # NOTE: We are setting Build.BuildNumber here to the NuGet package version to work around the limitation that + # the version cannot be passed to the Index Sources & Publish Symbols task. + - powershell: | + $version = Get-Content '$(Build.ArtifactStagingDirectory)/$(VersionArtifactName)/$(PackageVersionFileName)' -Raw + $vcsLabel = 'Lucene.Net_' + $version.Replace('.', '_').Replace('-', '_') + Write-Host "##vso[task.setvariable variable=VCSLabel;]$vcsLabel" + Write-Host "##vso[task.setvariable variable=PackageVersion;]$version" + Write-Host "##vso[task.setvariable variable=Build.BuildNumber;]$version" + displayName: 'Build VCS Label and Rehydrate Version Variables' + + - powershell: | + $files = 'build.bat','Version.props' + foreach ($file in $files) { + Copy-Item -Path "$(Build.ArtifactStagingDirectory)/$(VersionArtifactName)/$file" -Destination "$(Build.SourcesDirectory)/$file" -Force -ErrorAction Continue + } + displayName: 'Update build.bat and Version.props to build only version $(PackageVersion)' + + - template: 'build/azure-templates/show-all-environment-variables.yml' + + - task: CopyFiles@2 + displayName: 'Copy Source Code Files to: $(Build.ArtifactStagingDirectory)/srctemp' + inputs: + SourceFolder: '$(Build.SourcesDirectory)' + Contents: | + ** + !.git/**/* + !branding/**/* + !release/**/* + !src/**/bin/**/* + !src/**/obj/**/* + TargetFolder: '$(Build.ArtifactStagingDirectory)/srctemp' + + - task: ArchiveFiles@2 + displayName: 'Archive Source Code Files' + inputs: + rootFolderOrFile: '$(Build.ArtifactStagingDirectory)/srctemp' + includeRootFolder: false + archiveFile: '$(Build.ArtifactStagingDirectory)/$(ReleaseArtifactName)/Apache-Lucene.Net-$(PackageVersion).src.zip' + + - task: CopyFiles@2 + displayName: 'Copy License/Notice Files to: $(Build.ArtifactStagingDirectory)/$(NuGetArtifactName)' + inputs: + SourceFolder: '$(Build.SourcesDirectory)' + Contents: | + LICENSE.txt + NOTICE.txt + TargetFolder: '$(Build.ArtifactStagingDirectory)/$(NuGetArtifactName)' + + - task: ArchiveFiles@2 + displayName: 'Archive Binary Files' + inputs: + rootFolderOrFile: '$(Build.ArtifactStagingDirectory)/$(NuGetArtifactName)' + includeRootFolder: false + archiveFile: '$(Build.ArtifactStagingDirectory)/$(ReleaseArtifactName)/Apache-Lucene.Net-$(PackageVersion).bin.zip' + + - powershell: | + $dir = '$(Build.ArtifactStagingDirectory)/$(ReleaseArtifactName)' + if (!(Test-Path $dir)) { New-Item -ItemType Directory -Path "$dir" -Force } + $nl = [Environment]::NewLine + "TODO: Review: http://www.apache.org/legal/release-policy.html" + $nl + ` + "TODO: Tag Repository" + $nl + ` + " commit: $(Build.SourceVersion)" + $nl + ` + " tag: $(VCSLabel)" + $nl + ` + "TODO: Sign release artifacts (see https://www.apache.org/dev/release-signing.html)" + $nl + ` + "TODO: Push release artifacts to dev (https://dist.apache.org/repos/dist/dev/lucenenet/)" + $nl + ` + "TODO: Start release [VOTE] (see https://www.apache.org/foundation/voting.html)" + $nl | Out-File -FilePath "$dir/RELEASE-TODO.txt" -Force + displayName: 'Write RELEASE-TODO.txt' + + - task: PublishBuildArtifacts@1 + displayName: 'Publish Artifact: $(ReleaseArtifactName)' + inputs: + PathtoPublish: '$(Build.ArtifactStagingDirectory)/$(ReleaseArtifactName)' + ArtifactName: '$(ReleaseArtifactName)' + +# LUCENENET TODO: Write VCS Label (git tag) automatically \ No newline at end of file diff --git a/build/Dependencies.props b/build/Dependencies.props index 4e20f0b..b46153b 100644 --- a/build/Dependencies.props +++ b/build/Dependencies.props @@ -1,3 +1,23 @@ +<!-- + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + +--> <Project> <PropertyGroup Label="NuGet Package Reference Versions"> <Antlr3RuntimePackageVersion>3.5.1</Antlr3RuntimePackageVersion> diff --git a/build/TestReferences.Common.targets b/build/TestReferences.Common.targets index b2986a6..6411a7b 100644 --- a/build/TestReferences.Common.targets +++ b/build/TestReferences.Common.targets @@ -1,3 +1,23 @@ +<!-- + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + +--> <Project> <ItemGroup Label="Test Project Common References"> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(MicrosoftNETTestSdkPackageVersion)" /> diff --git a/build/azure-templates/publish-nuget-packages.yml b/build/azure-templates/publish-nuget-packages.yml new file mode 100644 index 0000000..7d5ab61 --- /dev/null +++ b/build/azure-templates/publish-nuget-packages.yml @@ -0,0 +1,64 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# Downloads an artifact with the specified nugetArtifactName, +# pushes any .nupkg files to the specified artifactFeedID, +# and pushes any debugging symbols (.pdb files) in the artifact +# (except for those named *.Tests.pdb) to TeamServices. + +parameters: + nugetArtifactName: 'nuget' # The name of the artifact where the NuGet assets (.nupkg and .pdb files) can be downloaded + artifactFeedID: '' # The GUID of the Azure Artifacts NuGet feed + testSymbolFilesConvention: '**/*.Tests*.pdb' # The glob pattern (within the nugetArtifact) where to look for test project symbols (.pdb) files, so they can be distinguished from other project file types. + +steps: +- powershell: | + function EnsureNotNullOrEmpty([string]$param, [string]$nameOfParam) { + if ([string]::IsNullOrEmpty($param)) { + Write-Host "##vso[task.logissue type=error;]Missing template parameter \"$nameOfParam\"" + Write-Host "##vso[task.complete result=Failed;]" + } + } + EnsureNotNullOrEmpty('${{ parameters.nugetArtifactName }}', 'nugetArtifactName') + EnsureNotNullOrEmpty('${{ parameters.artifactFeedID }}', 'artifactFeedID') + EnsureNotNullOrEmpty('${{ parameters.testSymbolFilesConvention }}', 'testSymbolFilesConvention') + displayName: 'Validate Template Parameters' + +- task: DownloadBuildArtifacts@0 + displayName: 'Download Build Artifacts: ${{ parameters.nugetArtifactName }}' + inputs: + artifactName: ${{ parameters.nugetArtifactName }} + downloadPath: '$(Build.ArtifactStagingDirectory)' + +- task: NuGetCommand@2 + displayName: 'NuGet push' + inputs: + command: push + packagesToPush: '$(Build.ArtifactStagingDirectory)/${{ parameters.nugetArtifactName }}/**/*.nupkg;!$(Build.ArtifactStagingDirectory)/${{ parameters.nugetArtifactName }}/**/*.symbols.nupkg' + publishVstsFeed: '/${{ parameters.artifactFeedID }}' + allowPackageConflicts: true + +- task: PublishSymbols@2 + displayName: 'Publish symbols path' + inputs: + SymbolsFolder: '$(Build.ArtifactStagingDirectory)/${{ parameters.nugetArtifactName }}' + SearchPattern: | + **/bin/**/*.pdb + !${{ parameters.testSymbolFilesConvention }} + IndexSources: true + PublishSymbols: true + SymbolServerType: TeamServices \ No newline at end of file diff --git a/build/azure-templates/publish-test-results-for-target-frameworks.yml b/build/azure-templates/publish-test-results-for-target-frameworks.yml new file mode 100644 index 0000000..cc3af4f --- /dev/null +++ b/build/azure-templates/publish-test-results-for-target-frameworks.yml @@ -0,0 +1,67 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# Runs Publish Test Results task for a specific framework + +parameters: + testProjectName: '' # The name of the test project + osName: '' # The name of the operating system for display purposes. + testResultsFormat: VSTest # Specify the format of the results files you want to publish. The following formats are supported: JUnit, NUnit, VSTest, XUnit, CTest + testResultsArtifactName: 'testresults' # The name of the Azure DevOps build artifact where the test results will be published. Default 'testresults'. + testResultsFileName: 'TestResults.trx' # The name of the file (not path) of the test results. Default 'TestResults.trx'. + +steps: +- powershell: | + function EnsureNotNullOrEmpty([string]$param, [string]$nameOfParam) { + if ([string]::IsNullOrEmpty($param)) { + Write-Host "##vso[task.logissue type=error;]Missing template parameter \"$nameOfParam\"" + Write-Host "##vso[task.complete result=Failed;]" + } + } + EnsureNotNullOrEmpty('${{ parameters.testProjectName }}', 'testProjectName') + EnsureNotNullOrEmpty('${{ parameters.osName }}', 'osName') + EnsureNotNullOrEmpty('${{ parameters.testResultsFormat }}', 'testResultsFormat') + EnsureNotNullOrEmpty('${{ parameters.testResultsArtifactName }}', 'testResultsArtifactName') + EnsureNotNullOrEmpty('${{ parameters.testResultsFileName }}', 'testResultsFileName') + displayName: 'Validate Template Parameters' + +- template: publish-test-results.yml + parameters: + framework: 'netcoreapp2.1' + testProjectName: '${{ parameters.testProjectName }}' + osName: '${{ parameters.osName }}' + testResultsFormat: '${{ parameters.testResultsFormat }}' + testResultsArtifactName: '${{ parameters.testResultsArtifactName }}' + testResultsFileName: '${{ parameters.testResultsFileName }}' + +- template: publish-test-results.yml + parameters: + framework: 'netcoreapp1.0' + testProjectName: '${{ parameters.testProjectName }}' + osName: '${{ parameters.osName }}' + testResultsFormat: '${{ parameters.testResultsFormat }}' + testResultsArtifactName: '${{ parameters.testResultsArtifactName }}' + testResultsFileName: '${{ parameters.testResultsFileName }}' + +- template: publish-test-results.yml + parameters: + framework: 'net451' + testProjectName: '${{ parameters.testProjectName }}' + osName: '${{ parameters.osName }}' + testResultsFormat: '${{ parameters.testResultsFormat }}' + testResultsArtifactName: '${{ parameters.testResultsArtifactName }}' + testResultsFileName: '${{ parameters.testResultsFileName }}' \ No newline at end of file diff --git a/build/azure-templates/publish-test-results-for-test-projects.yml b/build/azure-templates/publish-test-results-for-test-projects.yml new file mode 100644 index 0000000..62db26f --- /dev/null +++ b/build/azure-templates/publish-test-results-for-test-projects.yml @@ -0,0 +1,282 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing,-with-title +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# Runs Publish Test Results task for all Lucene.Net test projects + +# The tasks can be easily re-generated (except for any special cases) using the following powershell script + +#$source_directory = "F:/Projects/lucenenet" # Change to your repo location +# +#$testProjects = Get-ChildItem -Path "$source_directory/**/*.csproj" -Recurse | ? { $_.Directory.Name.Contains(".Tests") } | Sort-Object -Property FullName +# +#[string]$output = '' +# +#foreach ($testProject in $testProjects) { +# $projectName = [System.IO.Path]::GetFileNameWithoutExtension($testProject) +# +# $block = ` +# "- template: publish-test-results-for-target-frameworks.yml`n" + ` +# " parameters:`n" + ` +# " testProjectName: '$projectName'`n" + ` +# " osName: '$`{`{ parameters.osName `}`}'`n" + ` +# " testResultsFormat: '$`{`{ parameters.testResultsFormat `}`}'`n" + ` +# " testResultsArtifactName: '$`{`{ parameters.testResultsArtifactName `}`}'`n" + ` +# " testResultsFileName: '$`{`{ parameters.testResultsFileName `}`}'`n" + ` +# "`n" +# +# $output = "$output$block" +#} +# +#Set-Clipboard -Value $output + +parameters: + osName: '' # The name of the operating system for display purposes. + testResultsFormat: VSTest # Specify the format of the results files you want to publish. The following formats are supported: JUnit, NUnit, VSTest, XUnit, CTest + testResultsArtifactName: 'testresults' # The name of the Azure DevOps build artifact where the test results will be published. Default 'testresults'. + testResultsFileName: 'TestResults.trx' # The name of the file (not path) of the test results. Default 'TestResults.trx'. + +steps: +- powershell: | + function EnsureNotNullOrEmpty([string]$param, [string]$nameOfParam) { + if ([string]::IsNullOrEmpty($param)) { + Write-Host "##vso[task.logissue type=error;]Missing template parameter \"$nameOfParam\"" + Write-Host "##vso[task.complete result=Failed;]" + } + } + EnsureNotNullOrEmpty('${{ parameters.osName }}', 'osName') + EnsureNotNullOrEmpty('${{ parameters.testResultsFormat }}', 'testResultsFormat') + EnsureNotNullOrEmpty('${{ parameters.testResultsArtifactName }}', 'testResultsArtifactName') + EnsureNotNullOrEmpty('${{ parameters.testResultsFileName }}', 'testResultsFileName') + displayName: 'Validate Template Parameters' + +- template: publish-test-results-for-target-frameworks.yml + parameters: + testProjectName: 'Lucene.Net.Tests.ICU' + osName: '${{ parameters.osName }}' + testResultsFormat: '${{ parameters.testResultsFormat }}' + testResultsArtifactName: '${{ parameters.testResultsArtifactName }}' + testResultsFileName: '${{ parameters.testResultsFileName }}' + +# Special case: Only supports .netcoreapp2.1 +- template: publish-test-results.yml + parameters: + framework: 'netcoreapp2.1' + testProjectName: 'Lucene.Net.Tests.Cli' + osName: '${{ parameters.osName }}' + testResultsFormat: '${{ parameters.testResultsFormat }}' + testResultsArtifactName: '${{ parameters.testResultsArtifactName }}' + testResultsFileName: '${{ parameters.testResultsFileName }}' + +- template: publish-test-results-for-target-frameworks.yml + parameters: + testProjectName: 'Lucene.Net.Tests._A-I' + osName: '${{ parameters.osName }}' + testResultsFormat: '${{ parameters.testResultsFormat }}' + testResultsArtifactName: '${{ parameters.testResultsArtifactName }}' + testResultsFileName: '${{ parameters.testResultsFileName }}' + +- template: publish-test-results-for-target-frameworks.yml + parameters: + testProjectName: 'Lucene.Net.Tests._J-U' + osName: '${{ parameters.osName }}' + testResultsFormat: '${{ parameters.testResultsFormat }}' + testResultsArtifactName: '${{ parameters.testResultsArtifactName }}' + testResultsFileName: '${{ parameters.testResultsFileName }}' + +- template: publish-test-results-for-target-frameworks.yml + parameters: + testProjectName: 'Lucene.Net.Tests._U-Z' + osName: '${{ parameters.osName }}' + testResultsFormat: '${{ parameters.testResultsFormat }}' + testResultsArtifactName: '${{ parameters.testResultsArtifactName }}' + testResultsFileName: '${{ parameters.testResultsFileName }}' + +- template: publish-test-results-for-target-frameworks.yml + parameters: + testProjectName: 'Lucene.Net.Tests.Analysis.Common' + osName: '${{ parameters.osName }}' + testResultsFormat: '${{ parameters.testResultsFormat }}' + testResultsArtifactName: '${{ parameters.testResultsArtifactName }}' + testResultsFileName: '${{ parameters.testResultsFileName }}' + +- template: publish-test-results-for-target-frameworks.yml + parameters: + testProjectName: 'Lucene.Net.Tests.Analysis.Kuromoji' + osName: '${{ parameters.osName }}' + testResultsFormat: '${{ parameters.testResultsFormat }}' + testResultsArtifactName: '${{ parameters.testResultsArtifactName }}' + testResultsFileName: '${{ parameters.testResultsFileName }}' + +- template: publish-test-results-for-target-frameworks.yml + parameters: + testProjectName: 'Lucene.Net.Tests.Analysis.Phonetic' + osName: '${{ parameters.osName }}' + testResultsFormat: '${{ parameters.testResultsFormat }}' + testResultsArtifactName: '${{ parameters.testResultsArtifactName }}' + testResultsFileName: '${{ parameters.testResultsFileName }}' + +- template: publish-test-results-for-target-frameworks.yml + parameters: + testProjectName: 'Lucene.Net.Tests.Analysis.SmartCn' + osName: '${{ parameters.osName }}' + testResultsFormat: '${{ parameters.testResultsFormat }}' + testResultsArtifactName: '${{ parameters.testResultsArtifactName }}' + testResultsFileName: '${{ parameters.testResultsFileName }}' + +- template: publish-test-results-for-target-frameworks.yml + parameters: + testProjectName: 'Lucene.Net.Tests.Analysis.Stempel' + osName: '${{ parameters.osName }}' + testResultsFormat: '${{ parameters.testResultsFormat }}' + testResultsArtifactName: '${{ parameters.testResultsArtifactName }}' + testResultsFileName: '${{ parameters.testResultsFileName }}' + +- template: publish-test-results-for-target-frameworks.yml + parameters: + testProjectName: 'Lucene.Net.Tests.Benchmark' + osName: '${{ parameters.osName }}' + testResultsFormat: '${{ parameters.testResultsFormat }}' + testResultsArtifactName: '${{ parameters.testResultsArtifactName }}' + testResultsFileName: '${{ parameters.testResultsFileName }}' + +- template: publish-test-results-for-target-frameworks.yml + parameters: + testProjectName: 'Lucene.Net.Tests.Classification' + osName: '${{ parameters.osName }}' + testResultsFormat: '${{ parameters.testResultsFormat }}' + testResultsArtifactName: '${{ parameters.testResultsArtifactName }}' + testResultsFileName: '${{ parameters.testResultsFileName }}' + +- template: publish-test-results-for-target-frameworks.yml + parameters: + testProjectName: 'Lucene.Net.Tests.Codecs' + osName: '${{ parameters.osName }}' + testResultsFormat: '${{ parameters.testResultsFormat }}' + testResultsArtifactName: '${{ parameters.testResultsArtifactName }}' + testResultsFileName: '${{ parameters.testResultsFileName }}' + +- template: publish-test-results-for-target-frameworks.yml + parameters: + testProjectName: 'Lucene.Net.Tests.Demo' + osName: '${{ parameters.osName }}' + testResultsFormat: '${{ parameters.testResultsFormat }}' + testResultsArtifactName: '${{ parameters.testResultsArtifactName }}' + testResultsFileName: '${{ parameters.testResultsFileName }}' + +- template: publish-test-results-for-target-frameworks.yml + parameters: + testProjectName: 'Lucene.Net.Tests.Expressions' + osName: '${{ parameters.osName }}' + testResultsFormat: '${{ parameters.testResultsFormat }}' + testResultsArtifactName: '${{ parameters.testResultsArtifactName }}' + testResultsFileName: '${{ parameters.testResultsFileName }}' + +- template: publish-test-results-for-target-frameworks.yml + parameters: + testProjectName: 'Lucene.Net.Tests.Facet' + osName: '${{ parameters.osName }}' + testResultsFormat: '${{ parameters.testResultsFormat }}' + testResultsArtifactName: '${{ parameters.testResultsArtifactName }}' + testResultsFileName: '${{ parameters.testResultsFileName }}' + +- template: publish-test-results-for-target-frameworks.yml + parameters: + testProjectName: 'Lucene.Net.Tests.Grouping' + osName: '${{ parameters.osName }}' + testResultsFormat: '${{ parameters.testResultsFormat }}' + testResultsArtifactName: '${{ parameters.testResultsArtifactName }}' + testResultsFileName: '${{ parameters.testResultsFileName }}' + +- template: publish-test-results-for-target-frameworks.yml + parameters: + testProjectName: 'Lucene.Net.Tests.Highlighter' + osName: '${{ parameters.osName }}' + testResultsFormat: '${{ parameters.testResultsFormat }}' + testResultsArtifactName: '${{ parameters.testResultsArtifactName }}' + testResultsFileName: '${{ parameters.testResultsFileName }}' + +- template: publish-test-results-for-target-frameworks.yml + parameters: + testProjectName: 'Lucene.Net.Tests.Join' + osName: '${{ parameters.osName }}' + testResultsFormat: '${{ parameters.testResultsFormat }}' + testResultsArtifactName: '${{ parameters.testResultsArtifactName }}' + testResultsFileName: '${{ parameters.testResultsFileName }}' + +- template: publish-test-results-for-target-frameworks.yml + parameters: + testProjectName: 'Lucene.Net.Tests.Memory' + osName: '${{ parameters.osName }}' + testResultsFormat: '${{ parameters.testResultsFormat }}' + testResultsArtifactName: '${{ parameters.testResultsArtifactName }}' + testResultsFileName: '${{ parameters.testResultsFileName }}' + +- template: publish-test-results-for-target-frameworks.yml + parameters: + testProjectName: 'Lucene.Net.Tests.Misc' + osName: '${{ parameters.osName }}' + testResultsFormat: '${{ parameters.testResultsFormat }}' + testResultsArtifactName: '${{ parameters.testResultsArtifactName }}' + testResultsFileName: '${{ parameters.testResultsFileName }}' + +- template: publish-test-results-for-target-frameworks.yml + parameters: + testProjectName: 'Lucene.Net.Tests.Queries' + osName: '${{ parameters.osName }}' + testResultsFormat: '${{ parameters.testResultsFormat }}' + testResultsArtifactName: '${{ parameters.testResultsArtifactName }}' + testResultsFileName: '${{ parameters.testResultsFileName }}' + +- template: publish-test-results-for-target-frameworks.yml + parameters: + testProjectName: 'Lucene.Net.Tests.QueryParser' + osName: '${{ parameters.osName }}' + testResultsFormat: '${{ parameters.testResultsFormat }}' + testResultsArtifactName: '${{ parameters.testResultsArtifactName }}' + testResultsFileName: '${{ parameters.testResultsFileName }}' + +- template: publish-test-results-for-target-frameworks.yml + parameters: + testProjectName: 'Lucene.Net.Tests.Replicator' + osName: '${{ parameters.osName }}' + testResultsFormat: '${{ parameters.testResultsFormat }}' + testResultsArtifactName: '${{ parameters.testResultsArtifactName }}' + testResultsFileName: '${{ parameters.testResultsFileName }}' + +- template: publish-test-results-for-target-frameworks.yml + parameters: + testProjectName: 'Lucene.Net.Tests.Sandbox' + osName: '${{ parameters.osName }}' + testResultsFormat: '${{ parameters.testResultsFormat }}' + testResultsArtifactName: '${{ parameters.testResultsArtifactName }}' + testResultsFileName: '${{ parameters.testResultsFileName }}' + +- template: publish-test-results-for-target-frameworks.yml + parameters: + testProjectName: 'Lucene.Net.Tests.Spatial' + osName: '${{ parameters.osName }}' + testResultsFormat: '${{ parameters.testResultsFormat }}' + testResultsArtifactName: '${{ parameters.testResultsArtifactName }}' + testResultsFileName: '${{ parameters.testResultsFileName }}' + +- template: publish-test-results-for-target-frameworks.yml + parameters: + testProjectName: 'Lucene.Net.Tests.Suggest' + osName: '${{ parameters.osName }}' + testResultsFormat: '${{ parameters.testResultsFormat }}' + testResultsArtifactName: '${{ parameters.testResultsArtifactName }}' + testResultsFileName: '${{ parameters.testResultsFileName }}' \ No newline at end of file diff --git a/build/azure-templates/publish-test-results.yml b/build/azure-templates/publish-test-results.yml new file mode 100644 index 0000000..b7c9d0a --- /dev/null +++ b/build/azure-templates/publish-test-results.yml @@ -0,0 +1,81 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# Runs Publish Test Results task for a specific framework + +parameters: + testProjectName: '' # The name of the test project + framework: '' # The target framework for display purposes. + osName: '' # The name of the operating system for display purposes. + testResultsFormat: VSTest # Specify the format of the results files you want to publish. The following formats are supported: JUnit, NUnit, VSTest, XUnit, CTest + testResultsArtifactName: 'testresults' # The name of the Azure DevOps build artifact where the test results will be published. Default 'testresults'. + testResultsFileName: 'TestResults.trx' # The name of the file (not path) of the test results. Default 'TestResults.trx'. + +steps: +- powershell: | + function EnsureNotNullOrEmpty([string]$param, [string]$nameOfParam) { + if ([string]::IsNullOrEmpty($param)) { + Write-Host "##vso[task.logissue type=error;]Missing template parameter \"$nameOfParam\"" + Write-Host "##vso[task.complete result=Failed;]" + } + } + EnsureNotNullOrEmpty('${{ parameters.testProjectName }}', 'testProjectName') + EnsureNotNullOrEmpty('${{ parameters.framework }}', 'framework') + EnsureNotNullOrEmpty('${{ parameters.osName }}', 'osName') + EnsureNotNullOrEmpty('${{ parameters.testResultsFormat }}', 'testResultsFormat') + EnsureNotNullOrEmpty('${{ parameters.testResultsArtifactName }}', 'testResultsArtifactName') + EnsureNotNullOrEmpty('${{ parameters.testResultsFileName }}', 'testResultsFileName') + displayName: 'Validate Template Parameters' + +#- template: 'show-all-files.yml' # Uncomment for debugging + +- powershell: | + $testResultsFileName = "$(Build.ArtifactStagingDirectory)/${{ parameters.testResultsArtifactName }}/${{ parameters.osName }}/${{ parameters.framework }}/${{ parameters.testProjectName }}/${{ parameters.testResultsFileName }}" + $testResultsFileExists = Test-Path $testResultsFileName + if ($testResultsFileExists) { + + $reader = [System.Xml.XmlReader]::Create($testResultsFileName) + try { + while ($reader.Read()) { + if ($reader.NodeType -eq [System.Xml.XmlNodeType]::Element -and $reader.Name -eq 'Counters') { + $failed = $reader.GetAttribute('failed') + $passed = $reader.GetAttribute('passed') + $ignored = (([int]$reader.GetAttribute('total')) - ([int]$reader.GetAttribute('executed'))).ToString() + $testResults = "Tests failed: $failed, passed: $passed, ignored: $ignored" + Write-Host "##vso[task.setvariable variable=TestResults;]$testResults" + # Report a running total of failures + $totalFailures = ([int]$Env:TOTALFAILURES + [int]$failed).ToString() + Write-Host "##vso[task.setvariable variable=TotalFailures;]$totalFailures" + break; + } + } + } finally { + $reader.Dispose() + } + } else { + Write-Host "WARNING: File not found: $testResultsFileName" + } + Write-Host "##vso[task.setvariable variable=TestResultsFileExists;]$testResultsFileExists" + displayName: 'Parse Test Results File' + +- task: PublishTestResults@2 + displayName: 'Publish Test Results ${{ parameters.testProjectName }},${{ parameters.framework }}' + inputs: + testResultsFormat: ${{ parameters.testResultsFormat }} + testResultsFiles: '$(Build.ArtifactStagingDirectory)/${{ parameters.testResultsArtifactName }}/${{ parameters.osName }}/${{ parameters.framework }}/${{ parameters.testProjectName }}/${{ parameters.testResultsFileName }}' + testRunTitle: '${{ parameters.testProjectName }} - ${{ parameters.framework }} - ${{ parameters.osName }} | $(TestResults)' + condition: and(succeeded(), eq(variables['TestResultsFileExists'], 'true')) \ No newline at end of file diff --git a/build/azure-templates/run-tests-on-os.yml b/build/azure-templates/run-tests-on-os.yml new file mode 100644 index 0000000..e9e605e --- /dev/null +++ b/build/azure-templates/run-tests-on-os.yml @@ -0,0 +1,211 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# Downloads test binaries and executes tests using dotnet vstest, +# runs the tests for each project on a background job in parallel, +# then uploads the results to Azure DevOps pipelines + +parameters: + osName: 'Windows' # The name of the operating system for display purposes. + testTargetFrameworks: '' # A semicolon separated list of target frameworks indicating which frameworks tests will be run on. See: https://docs.microsoft.com/en-us/dotnet/standard/frameworks. + binaryArtifactName: 'testbinaries' # The name of the Azure DevOps build artifact where the test assemblies will be downloaded from. Default 'testbinaries'. + testResultsArtifactName: 'testresults' # The name of the Azure DevOps build artifact where the test results will be published. Default 'testresults'. + vsTestPlatform: 'x64' # Target platform architecture used for test execution. Valid values are x86, x64, and ARM. + testBinaryFilesPattern: '\.*\.Tests\.?[^\\/]*?\.?[^\\/]*?.dll$' # The regex pattern (within $(System.DefaultWorkingDirectory)/**/<TargetFramework>/) where to look for test .dll files, so they can be distinguished from other .dll file types. + testResultsFileName: 'TestResults.trx' # The name of the file (not path) of the test results. Default 'TestResults.trx'. + publishedArtifactZipFileName: 'published.zip' # The name of the zip file (within the Azure DevOps build artifact binaryArtifactName) where the published test binaries can be extracted from. Default 'published.zip'. + maximumParallelJobs: 8 + maximumAllowedFailures: 0 + +steps: +- powershell: | + function EnsureNotNullOrEmpty([string]$param, [string]$nameOfParam) { + if ([string]::IsNullOrEmpty($param)) { + Write-Host "##vso[task.logissue type=error;]Missing template parameter \"$nameOfParam\"" + Write-Host "##vso[task.complete result=Failed;]" + } + } + EnsureNotNullOrEmpty('${{ parameters.osName }}', 'osName') + EnsureNotNullOrEmpty('${{ parameters.testTargetFrameworks }}', 'testTargetFrameworks') + EnsureNotNullOrEmpty('${{ parameters.binaryArtifactName }}', 'binaryArtifactName') + EnsureNotNullOrEmpty('${{ parameters.testResultsArtifactName }}', 'testResultsArtifactName') + EnsureNotNullOrEmpty('${{ parameters.vsTestPlatform }}', 'vsTestPlatform') + EnsureNotNullOrEmpty('${{ parameters.testBinaryFilesPattern }}', 'testBinaryFilesPattern') + EnsureNotNullOrEmpty('${{ parameters.testResultsFileName }}', 'testResultsFileName') + EnsureNotNullOrEmpty('${{ parameters.publishedArtifactZipFileName }}', 'publishedArtifactZipFileName') + EnsureNotNullOrEmpty('${{ parameters.maximumParallelJobs }}', 'maximumParallelJobs') + EnsureNotNullOrEmpty('${{ parameters.maximumAllowedFailures }}', 'maximumAllowedFailures') + displayName: 'Validate Template Parameters' + +- task: DownloadBuildArtifacts@0 + displayName: 'Download Build Artifacts: ${{ parameters.binaryArtifactName }}' + inputs: + artifactName: ${{ parameters.binaryArtifactName }} + downloadPath: '$(System.DefaultWorkingDirectory)' + +#- template: 'show-all-files.yml' # Uncomment for debugging + +- task: ExtractFiles@1 + displayName: 'Extract files from ${{ parameters.publishedArtifactZipFileName }}' + inputs: + archiveFilePatterns: '${{ parameters.binaryArtifactName }}/${{ parameters.publishedArtifactZipFileName }}' + destinationFolder: '$(System.DefaultWorkingDirectory)/${{ parameters.binaryArtifactName }}' + cleanDestinationFolder: false + +- powershell: | + $testTargetFrameworksString = '${{ parameters.testTargetFrameworks }}' + $testBinaryRootDirectory = "$(System.DefaultWorkingDirectory)" + $testResultsArtifactDirectory = "${{ format('$(Build.ArtifactStagingDirectory)/{0}',parameters.testResultsArtifactName) }}" + $testPlatform = '${{ parameters.vsTestPlatform }}' + $testOSName = '${{ parameters.osName }}' + $testBinaryFilesPattern = '${{ parameters.testBinaryFilesPattern }}' + $testResultsFileName = '${{ parameters.testResultsFileName }}' + $maximumParalellJobs = '${{ parameters.maximumParallelJobs }}' + $testTargetFrameworks = $testTargetFrameworksString.Split([char]',',[char]';') + + function SeparateVersionDigits([string]$digits) { + return (&{ for ($i = 0;$i -lt $digits.Length;$i++) { $digits.Substring($i,1) }}) -join '.' + } + + # Convert $framework (i.e. net461) into format for dotnet vstest (i.e. .NETFramework,Version=4.6.1) + function ConvertFrameworkName([string]$framework) { + $match = [regex]::Match($framework, '^net(\d+)$') # .NET Framework + if ($match.Success) { + $ver = SeparateVersionDigits($match.Groups[1].Value) + return ".NETFramework,Version=v$($ver)" + } + $match = [regex]::Match($framework, '^netcoreapp(\d+\.\d+(?:\.\d+)?)$') # .NET Core + if ($match.Success) { + $ver = $match.Groups[1].Value + return ".NETCoreApp,Version=v$($ver)" + } + $match = [regex]::Match($framework, '^uap(\d+\.\d+)?$') # Universal Windows Platform + if ($match.Success) { + $ver = $match.Groups[1].Value + $ver = if ([string]::IsNullOrEmpty($ver)) { '10' } else { $ver.Replace('.0','').Replace('.','') } + return "FrameworkUap$($ver)" + } + return $framework + } + + function IsSupportedFramework([string]$framework) { + if ($IsWindows -eq $null) { + $IsWindows = $env:OS.StartsWith('Win') + } + if (!$IsWindows -and !$framework.StartsWith('netcoreapp')) { + return $false + } + return $true + } + + function RunTests([string]$framework, [string]$fileRegexPattern) { + if (!(IsSupportedFramework($framework))) { continue } + + $testBinaries = Get-ChildItem -Path "$testBinaryRootDirectory" -File -Recurse | Where-Object {$_.FullName -match "$framework"} | Where-Object {$_.FullName -match "$fileRegexPattern"} | Sort-Object -Property FullName + Write-Host $testBinaries + foreach ($testBinary in $testBinaries) { + $testName = [System.IO.Path]::GetFileNameWithoutExtension($testBinary.FullName) + $testDirectory = $testBinary.Directory.Name + + # Safety check - only run tests for the DLL that matches the directory name so we don't run the same one twice + if (!($testName -eq $testDirectory)) { continue } + + if ($maximumParalellJobs -gt 1) { + # Pause if we have queued too many parallel jobs + $running = @(Get-Job | Where-Object { $_.State -eq 'Running' }) + if ($running.Count -ge $maximumParalellJobs) { + Write-Host "" + Write-Host " Running tests in parallel on $($running.Count) projects." -ForegroundColor Cyan + Write-Host " Next in queue is $testName on $framework. This will take a bit, please wait..." -ForegroundColor Cyan + $running | Wait-Job -Any | Out-Null + } + } + + $fwork = ConvertFrameworkName($framework) + $testResultDirectory = "$testResultsArtifactDirectory/$testOSName/$framework/$testName" + if (!(Test-Path "$testResultDirectory")) { + New-Item "$testResultDirectory" -ItemType Directory -Force + } + + $testExpression = "dotnet vstest ""$($testBinary.FullName)"" --Framework:""$fwork"" --Platform:""$testPlatform""" + ` + " --logger:""console;verbosity=normal"" --logger:""trx;LogFileName=$testResultsFileName""" + ` + " --ResultsDirectory:""$testResultDirectory"" --Blame" + + Write-Host "Testing '$($testBinary.FullName)' on framework '$fwork' and outputting test results to '$testResultDirectory/$testResultsFileName'..." + Write-Host $testExpression -ForegroundColor Magenta + if ($maximumParalellJobs -le 1) { + Invoke-Expression $testExpression # For running in the foreground + } else { + + $testExpression += " > ""$testResultDirectory/dotnet-vstest.log"" 2> ""$testResultDirectory/dotnet-vstest-error.log""" + $scriptBlock = { + param([string]$testExpression) + Invoke-Expression $testExpression + } + + # Execute the jobs in parallel + Start-Job $scriptBlock -ArgumentList $testExpression + } + } + } + + foreach ($framework in $testTargetFrameworks) { + RunTests -Framework "$framework" -FileRegexPattern "$testBinaryFilesPattern" + } + + if ($maximumParalellJobs -gt 1) { + # Wait for it all to complete + do { + $running = @(Get-Job | Where-Object { $_.State -eq 'Running' }) + if ($running.Count -gt 0) { + Write-Host "" + Write-Host " Almost finished, only $($running.Count) projects left..." -ForegroundColor Cyan + $running | Wait-Job -Any + } + } until ($running.Count -eq 0) + } + + $global:LASTEXITCODE = 0 # Force the script to continue on error + displayName: 'dotnet vstest ${{ parameters.testTargetFrameworks }}' + ignoreLASTEXITCODE: true + +#- template: 'show-all-files.yml' # Uncomment for debugging + +- task: PublishBuildArtifacts@1 + displayName: 'Publish Artifact: ${{ parameters.testResultsArtifactName }}' + inputs: + PathtoPublish: '$(Build.ArtifactStagingDirectory)/${{ parameters.testResultsArtifactName }}' + ArtifactName: '${{ parameters.testResultsArtifactName }}' + condition: succeededOrFailed() + +# Due to the fact that it is not possible to loop a task and +# it would be a ton of work to make a replacement for the +# Publish Test Results task or the (deprecated) TfsPublisher +# our only other option is to make a task for every supported +# platform and project and update it whenever a new platform +# is targeted or test project is created in Lucene.Net. + +- template: 'publish-test-results-for-test-projects.yml' + parameters: + osName: '${{ parameters.osName }}' + +- pwsh: | + $maximumAllowedFailures = '${{ parameters.maximumAllowedFailures }}' + if ([int]$Env:TOTALFAILURES -gt [int]$maximumAllowedFailures) { + Write-Host "##vso[task.logissue type=error;]Test run failed due to too many failed tests. Maximum failures allowed: $maximumAllowedFailures, total failures: $($Env:TOTALFAILURES)." + Write-Host "##vso[task.complete result=Failed;]" + } \ No newline at end of file diff --git a/build/azure-templates/show-all-environment-variables.yml b/build/azure-templates/show-all-environment-variables.yml new file mode 100644 index 0000000..1815e62 --- /dev/null +++ b/build/azure-templates/show-all-environment-variables.yml @@ -0,0 +1,28 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# Writes all environment variables to the host (helpful for debugging) + +steps: +- powershell: | + $environmentVars = Get-ChildItem -path env:* | sort Name + foreach($var in $environmentVars) { + $keyname = $var.Key + $keyvalue = $var.Value + Write-Output "${keyname}: $keyvalue" + } + displayName: 'Show all Environment Variables' \ No newline at end of file diff --git a/build/azure-templates/show-all-files.yml b/build/azure-templates/show-all-files.yml new file mode 100644 index 0000000..9591775 --- /dev/null +++ b/build/azure-templates/show-all-files.yml @@ -0,0 +1,26 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# Downloads test binaries and executes tests using dotnet vstest, +# runs the tests for each project on a background job in parallel, +# then uploads the results to Azure DevOps pipelines + +# Writes all file names (from the parent directory) to the host (helpful for debugging) + +steps: +- powershell: cd ..;dir -r | Where-Object {$_.PsIsContainer -eq $false} | % { $_.FullName } + displayName: 'Show all Files' \ No newline at end of file diff --git a/build/build.ps1 b/build/build.ps1 index 6ba4106..a29d765 100644 --- a/build/build.ps1 +++ b/build/build.ps1 @@ -29,22 +29,23 @@ properties { [string]$sdkPath = "$env:programfiles/dotnet/sdk" [string]$sdkVersion = "2.2.300" [string]$globalJsonFile = "$base_directory/global.json" + [string]$versionPropsFile = "$base_directory/Version.props" + [string]$build_bat = "$base_directory/build.bat" [string]$buildCounter = $(if ($buildCounter) { $buildCounter } else { $env:BuildCounter }) #NOTE: Pass in as a parameter (not a property) or environment variable to override - [string]$preReleaseCounterPattern = $(if ($preReleaseCounterPattern) { $preReleaseCounterPattern } else { if ($env:PreReleaseCounterPattern) { $env:PreReleaseCounterPattern } else { "00000" } }) #NOTE: Pass in as a parameter (not a property) or environment variable to override - [string]$versionSuffix = $(if ($versionSuffix) { $versionSuffix } else { $env:VersionSuffix }) #NOTE: Pass in as a parameter (not a property) or environment variable to override + [string]$preReleaseCounterPattern = $(if ($preReleaseCounterPattern) { $preReleaseCounterPattern } else { if ($env:PreReleaseCounterPattern) { $env:PreReleaseCounterPattern } else { "0000000000" } }) #NOTE: Pass in as a parameter (not a property) or environment variable to override + [string]$versionSuffix = $(if ($versionSuffix -ne $null) { $versionSuffix } else { if ($env:VersionSuffix -ne $null) { $env:VersionSuffix } else { 'ci' }}) #NOTE: Pass in as a parameter (not a property) or environment variable to override [string]$packageVersion = Get-Package-Version #NOTE: Pass in as a parameter (not a property) or environment variable to override [string]$version = Get-Version - [string]$configuration = "Release" + [string]$configuration = $(if ($configuration) { $configuration } else { if ($env:BuildConfiguration) { $env:BuildConfiguration } else { "Release" } }) #NOTE: Pass in as a parameter (not a property) or environment variable to override + [string]$platform = $(if ($platform) { $platform } else { if ($env:BuildPlatform) { $env:BuildPlatform } else { "Any CPU" } }) #NOTE: Pass in as a parameter (not a property) or environment variable to override [bool]$backup_files = $true [bool]$prepareForBuild = $true [bool]$generateBuildBat = $false + [bool]$zipPublishedArtifacts = $false + [string]$publishedArtifactZipFileName = "artifact.zip" - [string]$build_bat = "$base_directory/build.bat" - [string]$copyright_year = [DateTime]::Today.Year.ToString() #Get the current year from the system - [string]$copyright = "Copyright " + $([char]0x00A9) + " 2006 - $copyright_year The Apache Software Foundation" - [string]$company_name = "The Apache Software Foundation" - [string]$product_name = "Lucene.Net" + [int]$maximumParalellJobs = 8 #test paramters [string]$frameworks_to_test = "netcoreapp2.1,netcoreapp1.0,net451" @@ -56,11 +57,11 @@ if ($IsWindows -eq $null) { $IsWindows = $Env:OS.StartsWith('Windows') } - task default -depends Pack task Clean -description "This task cleans up the build directory" { Write-Host "##teamcity[progressMessage 'Cleaning']" + Write-Host "##vso[task.setprogress]'Cleaning'" Remove-Item $release_directory -Force -Recurse -ErrorAction SilentlyContinue Get-ChildItem $base_directory -Include *.bak -Recurse | foreach ($_) {Remove-Item $_.FullName} } @@ -74,6 +75,7 @@ task UpdateLocalSDKVersion -description "Backs up the project.json file and pins task InstallSDK -description "This task makes sure the correct SDK version is installed to build" -ContinueOnError { Write-Host "##teamcity[progressMessage 'Installing SDK $sdkVersion']" + Write-Host "##vso[task.setprogress]'Installing SDK $sdkVersion'" $installed = Is-Sdk-Version-Installed $sdkVersion if (!$installed) { Write-Host "Requires SDK version $sdkVersion, installing..." -ForegroundColor Red @@ -89,9 +91,11 @@ task InstallSDK -description "This task makes sure the correct SDK version is in } task Init -depends InstallSDK, UpdateLocalSDKVersion -description "This task makes sure the build environment is correctly setup" { - #Update TeamCity or MyGet with packageVersion + #Update TeamCity, MyGet, or Azure Pipelines with packageVersion Write-Output "##teamcity[buildNumber '$packageVersion']" Write-Output "##myget[buildNumber '$packageVersion']" + Write-Host "##vso[task.setvariable variable=Build.BuildNumber;]$packageVersion" + Write-Host "##vso[build.updatebuildnumber]$packageVersion" & dotnet.exe --version & dotnet.exe --info @@ -106,12 +110,14 @@ task Init -depends InstallSDK, UpdateLocalSDKVersion -description "This task mak Write-Host "Package Version: $packageVersion" Write-Host "Version: $version" Write-Host "Configuration: $configuration" + Write-Host "Platform: $platform" Ensure-Directory-Exists "$release_directory" } task Restore -description "This task restores the dependencies" { Write-Host "##teamcity[progressMessage 'Restoring']" + Write-Host "##vso[task.setprogress]'Restoring'" Exec { & dotnet.exe restore $solutionFile --no-dependencies /p:TestFrameworks=true } @@ -119,42 +125,25 @@ task Restore -description "This task restores the dependencies" { task Compile -depends Clean, Init, Restore -description "This task compiles the solution" { Write-Host "##teamcity[progressMessage 'Compiling']" + Write-Host "##vso[task.setprogress]'Compiling'" try { if ($prepareForBuild -eq $true) { Prepare-For-Build } - #Use only the major version as the assembly version. - #This ensures binary compatibility unless the major version changes. - $version-match "(^\d+)" - $assemblyVersion = $Matches[0] - $assemblyVersion = "$assemblyVersion.0.0" - - Write-Host "Assembly version set to: $assemblyVersion" -ForegroundColor Green - - $pv = $packageVersion - #check for presense of Git - & where.exe git.exe - if ($LASTEXITCODE -eq 0) { - $gitCommit = ((git rev-parse --verify --short=10 head) | Out-String).Trim() - $pv = "$packageVersion commit:[$gitCommit]" - } - - Write-Host "Assembly informational version set to: $pv" -ForegroundColor Green - - $testFrameworks = $frameworks_to_test.Replace(',', ';') + $testFrameworks = [string]::Join(';', (Get-FrameworksToTest)) Write-Host "TestFrameworks set to: $testFrameworks" -ForegroundColor Green Exec { + # NOTE: Version information is not passed in at the command line, + # instead it is output to the Version.props file. This file is then + # used during a release to "freeze" the build at a specific version + # so it is always a constant in release distributions. & dotnet.exe msbuild $solutionFile /t:Build ` /p:Configuration=$configuration ` - /p:AssemblyVersion=$assemblyVersion ` - /p:FileVersion=$version ` - /p:InformationalVersion=$pv ` - /p:Product=$product_name ` - /p:Company=$company_name ` - /p:Copyright=$copyright ` + /p:Platform=$platform ` + /p:PortableDebugTypeOnly=true ` /p:TestFrameworks=true # workaround for parsing issue: https://github.com/Microsoft/msbuild/issues/471#issuecomment-181963350 } @@ -168,18 +157,27 @@ task Compile -depends Clean, Init, Restore -description "This task compiles the task Pack -depends Compile -description "This task creates the NuGet packages" { Write-Host "##teamcity[progressMessage 'Packing']" + Write-Host "##vso[task.setprogress]'Packing'" #create the nuget package output directory Ensure-Directory-Exists "$nuget_package_directory" try { Exec { - & dotnet.exe pack $solutionFile --configuration $Configuration --output $nuget_package_directory --no-build --include-symbols /p:PackageVersion=$packageVersion + # NOTE: Package version information is not passed in at the command line, + # instead it is output to the Version.props file. This file is then + # used during a release to "freeze" the build at a specific version + # so it is always a constant in release distributions. + & dotnet.exe pack $solutionFile --configuration $configuration --output $nuget_package_directory --no-build } $success = $true } finally { #if ($success -ne $true) { Restore-Files $backedUpFiles + #Remove Version.props, as we don't want it to be committed to the repository + if ($backup_files -eq $true -and (Test-Path -Path "$versionPropsFile") -eq $true) { + Remove-Item -Path "$versionPropsFile" -Force + } #} } } @@ -192,11 +190,23 @@ task Publish -depends Compile -description "This task uses dotnet publish to pac Write-Host "##vso[task.setprogress]'Publishing'" try { - $frameworksToTest = $frameworks_to_test -split "\s*?,\s*?" + $frameworksToTest = Get-FrameworksToTest + + if ($zipPublishedArtifacts) { + $outDirectory = New-TemporaryDirectory + } else { + $outDirectory = $publish_directory + } foreach ($framework in $frameworksToTest) { - $testProjects = Get-ChildItem -Path "$source_directory/**/*.csproj" -Recurse | ? { $_.Directory.Name.Contains(".Tests") } | ForEach-Object { $_.FullName } + $testProjects = Get-ChildItem -Path "$source_directory/**/*.csproj" -Recurse | ? { $_.Directory.Name.Contains(".Tests") } | Select -ExpandProperty FullName foreach ($testProject in $testProjects) { + # Pause if we have queued too many parallel jobs + $running = @(Get-Job | Where-Object { $_.State -eq 'Running' }) + if ($running.Count -ge $maximumParalellJobs) { + $running | Wait-Job -Any | Out-Null + } + $projectName = [System.IO.Path]::GetFileNameWithoutExtension($testProject) # Special case - our CLI tool only supports .NET Core 2.1 @@ -204,36 +214,43 @@ task Publish -depends Compile -description "This task uses dotnet publish to pac continue } + $logPath = "$outDirectory/$framework" + $outputPath = "$logPath/$projectName" + # Do this first so there is no conflict - $outputPath = "$publish_directory/$framework/$projectName" Ensure-Directory-Exists $outputPath $scriptBlock = { - param([string]$testProject, [string]$publish_directory, [string]$framework, [string]$configuration, [string]$projectName) - $logPath = "$publish_directory/$framework" - $outputPath = "$logPath/$projectName" + param([string]$testProject, [string]$outputPath, [string]$logPath, [string]$framework, [string]$configuration, [string]$projectName) Write-Host "Publishing '$testProject' on '$framework' to '$outputPath'..." # Note: Cannot use Psake Exec in background - dotnet publish "$testProject" --output "$outputPath" --framework "$framework" --configuration "$configuration" --no-build --verbosity Detailed /p:TestFrameworks=true > "$logPath/$projectName-dotnet-publish.log" 2> "$logPath/$projectName-dotnet-publish-error.log" + dotnet publish "$testProject" --output "$outputPath" --framework "$framework" --configuration "$configuration" --no-build --verbosity Detailed /p:TestFrameworks=true /p:Platform="$platform" > "$logPath/$projectName-dotnet-publish.log" 2> "$logPath/$projectName-dotnet-publish-error.log" } # Execute the jobs in parallel - Start-Job $scriptBlock -ArgumentList $testProject,$publish_directory,$framework,$configuration,$projectName + Start-Job $scriptBlock -ArgumentList $testProject,$outputPath,$logPath,$framework,$configuration,$projectName } } - Write-Host "Executing dotnet publish of all projects in parallel. This will take a bit, please wait..." - - Get-Job - # Wait for it all to complete - While (Get-Job -State "Running") { - Start-Sleep 10 - } + do { + $running = @(Get-Job | Where-Object { $_.State -eq 'Running' }) + if ($running.Count -gt 0) { + Write-Host "" + Write-Host " Almost finished, only $($running.Count) projects left to publish..." -ForegroundColor Cyan + $running | Wait-Job -Any | Out-Null + } + } until ($running.Count -eq 0) # Getting the information back from the jobs (time consuming) #Get-Job | Receive-Job + if ($zipPublishedArtifacts) { + Ensure-Directory-Exists $publish_directory + Add-Type -assembly "System.IO.Compression.Filesystem" + [System.IO.Compression.ZipFile]::CreateFromDirectory($outDirectory, "$publish_directory/$publishedArtifactZipFileName") + } + $success = $true } finally { #if ($success -ne $true) { @@ -244,27 +261,48 @@ task Publish -depends Compile -description "This task uses dotnet publish to pac task Test -depends InstallSDK, UpdateLocalSDKVersion, Restore -description "This task runs the tests" { Write-Host "##teamcity[progressMessage 'Testing']" + Write-Host "##vso[task.setprogress]'Testing'" Write-Host "Running tests..." -ForegroundColor DarkCyan pushd $base_directory $testProjects = Get-ChildItem -Path "$source_directory/**/*.csproj" -Recurse | ? { $_.Directory.Name.Contains(".Tests") } popd - Write-Host "frameworks_to_test: $frameworks_to_test" -ForegroundColor Yellow + $testProjects = $testProjects | Sort-Object -Property FullName - $frameworksToTest = $frameworks_to_test -split "\s*?,\s*?" + $frameworksToTest = Get-FrameworksToTest + + Write-Host "frameworksToTest: $frameworksToTest" -ForegroundColor Yellow + + [int]$totalProjects = $testProjects.Length * $frameworksToTest.Length + [int]$remainingProjects = $totalProjects - foreach ($framework in $frameworksToTest) { - Write-Host "Framework: $framework" -ForegroundColor Blue + Ensure-Directory-Exists $test_results_directory - foreach ($testProject in $testProjects) { + foreach ($testProject in $testProjects) { + + foreach ($framework in $frameworksToTest) { $testName = $testProject.Directory.Name # Special case - our CLI tool only supports .NET Core 2.1 if ($testName.Contains("Tests.Cli") -and (!$framework.StartsWith("netcoreapp2."))) { + $totalProjects-- + $remainingProjects-- continue } + Write-Host " Next Project in Queue: $testName, Framework: $framework" -ForegroundColor Yellow + + # Pause if we have queued too many parallel jobs + $running = @(Get-Job | Where-Object { $_.State -eq 'Running' }) + if ($running.Count -ge $maximumParalellJobs) { + Write-Host "" + Write-Host " Running tests in parallel on $($running.Count) projects out of approximately $totalProjects total." -ForegroundColor Cyan + Write-Host " $remainingProjects projects are waiting in the queue to run. This will take a bit, please wait..." -ForegroundColor Cyan + $running | Wait-Job -Any | Out-Null + } + $remainingProjects -= 1 + $testResultDirectory = "$test_results_directory/$framework/$testName" Ensure-Directory-Exists $testResultDirectory @@ -290,15 +328,33 @@ task Test -depends InstallSDK, UpdateLocalSDKVersion, Restore -description "This Write-Host $testExpression -ForegroundColor Magenta - Invoke-Expression $testExpression - # fail the build on negative exit codes (NUnit errors - if positive it is a test count or, if 1, it could be a dotnet error) - if ($LASTEXITCODE -lt 0) { - throw "Test execution failed" + $scriptBlock = { + param([string]$testExpression, [string]$testResultDirectory) + $testExpression = "$testExpression > '$testResultDirectory/dotnet-test.log' 2> '$testResultDirectory/dotnet-test-error.log'" + Invoke-Expression $testExpression } + + # Execute the jobs in parallel + Start-Job $scriptBlock -ArgumentList $testExpression,$testResultDirectory + + #Invoke-Expression $testExpression + ## fail the build on negative exit codes (NUnit errors - if positive it is a test count or, if 1, it could be a dotnet error) + #if ($LASTEXITCODE -lt 0) { + # throw "Test execution failed" + #} } } - Summarize-Test-Results + do { + $running = @(Get-Job | Where-Object { $_.State -eq 'Running' }) + if ($running.Count -gt 0) { + Write-Host "" + Write-Host " Almost finished, only $($running.Count) test projects left..." -ForegroundColor Cyan + $running | Wait-Job -Any + } + } until ($running.Count -eq 0) + + Summarize-Test-Results -FrameworksToTest $frameworksToTest } function Get-Package-Version() { @@ -345,6 +401,19 @@ function Get-Version() { return $version } +function Get-FrameworksToTest() { + $frameworksToTest = New-Object Collections.Generic.List[string] + $frameworks = $frameworks_to_test -split "\s*?,\s*?" + foreach ($framework in $frameworks) { + if ($IsWindows) { + $frameworksToTest.Add($framework) + } elseif ($framework.StartsWith('netcore')) { + $frameworksToTest.Add($framework) + } + } + return [System.Linq.Enumerable]::ToArray($frameworksToTest) +} + function Is-Sdk-Version-Installed([string]$sdkVersion) { & where.exe dotnet.exe | Out-Null if ($LASTEXITCODE -eq 0) { @@ -375,6 +444,35 @@ function Is-Sdk-Version-Installed([string]$sdkVersion) { } function Prepare-For-Build() { + #Use only the major version as the assembly version. + #This ensures binary compatibility unless the major version changes. + $version -match "(^\d+)" + $assemblyVersion = $Matches[0] + $assemblyVersion = "$assemblyVersion.0.0" + + Write-Host "Assembly version set to: $assemblyVersion" -ForegroundColor Green + + $informationalVersion = $packageVersion + #check for presense of Git + & where.exe git.exe + if ($LASTEXITCODE -eq 0) { + $gitCommit = ((git rev-parse --verify --short=10 head) | Out-String).Trim() + $informationalVersion = "$packageVersion commit:[$gitCommit]" + } + + Write-Host "##vso[task.setvariable variable=AssemblyVersion;]$assemblyVersion" + Write-Host "##vso[task.setvariable variable=FileVersion;]$version" + Write-Host "##vso[task.setvariable variable=InformationalVersion;]$informationalVersion" + Write-Host "##vso[task.setvariable variable=PackageVersion;]$packageVersion" + + Write-Host "Assembly informational version set to: $informationalVersion" -ForegroundColor Green + + Generate-Version-Props ` + -AssemblyVersion $assemblyVersion ` + -FileVersion $version ` + -InformationalVersion $informationalVersion ` + -PackageVersion $packageVersion ` + -File $versionPropsFile Update-Constants-Version $packageVersion if ($generateBuildBat -eq $true) { @@ -411,6 +509,50 @@ $fileText = "{ Out-File -filePath $file -encoding UTF8 -inputObject $fileText } +function Generate-Version-Props { +param( + [string]$assemblyVersion, + [string]$fileVersion, + [string]$informationalVersion, + [string]$packageVersion, + [string]$file = $(throw "file is a required parameter.") +) + +$fileText = "<!-- + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + ""License""); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + ""AS IS"" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + +--> +<Project> + <PropertyGroup Label=""Version Override Properties""> + <AssemblyVersion>$assemblyVersion</AssemblyVersion> + <FileVersion>$fileVersion</FileVersion> + <InformationalVersion>$informationalVersion</InformationalVersion> + <PackageVersion>$packageVersion</PackageVersion> + </PropertyGroup> +</Project>" + $dir = [System.IO.Path]::GetDirectoryName($file) + Ensure-Directory-Exists $dir + + Write-Host "Generating Version.props file: $file" + Out-File -filePath $file -encoding UTF8 -inputObject $fileText +} + function Generate-Build-Bat { param( [string]$file = $(throw "file is a required parameter.") @@ -494,9 +636,7 @@ function New-CountersObject ([string]$project, [string]$outcome, [int]$total, [i return $counters } -function Summarize-Test-Results() { - Write-Host "frameworks_to_test: $frameworks_to_test" -ForegroundColor Gray - $frameworksToTest = $frameworks_to_test -split "\s*?,\s*?" +function Summarize-Test-Results([string[]]$frameworksToTest) { foreach ($framework in $frameworksToTest) { pushd $base_directory @@ -517,11 +657,11 @@ function Summarize-Test-Results() { Write-Host "" Write-Host "" - Write-Host "************************************************************************************************************" -ForegroundColor Yellow - Write-Host "* *" -ForegroundColor Yellow - Write-Host "* Test Summary For $framework" -ForegroundColor Yellow - Write-Host "* *" -ForegroundColor Yellow - Write-Host "************************************************************************************************************" -ForegroundColor Yellow + Write-Host "**********************************************************************" -ForegroundColor Yellow + Write-Host "* *" -ForegroundColor Yellow + Write-Host "* Test Summary For $framework" -ForegroundColor Yellow + Write-Host "* *" -ForegroundColor Yellow + Write-Host "**********************************************************************" -ForegroundColor Yellow foreach ($testReport in $testReports) { $testName = [System.IO.Path]::GetFileName([System.IO.Path]::GetDirectoryName($testReport)) @@ -555,15 +695,17 @@ function Summarize-Test-Results() { $skippedCountForFramework += $counters.Skipped $format = @{Expression={$_.Project};Label='Project';Width=35}, - @{Expression={$_.Outcome};Label='Outcome';Width=9}, - @{Expression={$_.Total};Label='Total';Width=8}, - @{Expression={$_.Executed};Label='Executed';Width=10}, - @{Expression={$_.Passed};Label='Passed';Width=8}, - @{Expression={$_.Failed};Label='Failed';Width=8}, - @{Expression={$_.Warning};Label='Warning';Width=9}, + @{Expression={$_.Outcome};Label='Outcome';Width=7}, + @{Expression={$_.Total};Label='Total';Width=6}, + @{Expression={$_.Executed};Label='Executed';Width=8}, + @{Expression={$_.Passed};Label='Passed';Width=6}, + @{Expression={$_.Failed};Label='Failed';Width=6}, + @{Expression={$_.Warning};Label='Warning';Width=7}, @{Expression={$_.Inconclusive};Label='Inconclusive';Width=14} - $Counters | Format-Table $format + if ($counters.Failed -gt 0) { + $Counters | Format-Table $format + } } } @@ -575,12 +717,12 @@ function Summarize-Test-Results() { # FOOTER FOR FRAMEWORK - Write-Host "************************************************************************************************************" -ForegroundColor Magenta - Write-Host "* *" -ForegroundColor Magenta - Write-Host "* Totals For $framework" -ForegroundColor Magenta - Write-Host "* *" -ForegroundColor Magenta - Write-Host "************************************************************************************************************" -ForegroundColor Magenta - Write-Host "" + #Write-Host "**********************************************************************" -ForegroundColor Magenta + #Write-Host "* *" -ForegroundColor Magenta + #Write-Host "* Totals For $framework" -ForegroundColor Magenta + #Write-Host "* *" -ForegroundColor Magenta + #Write-Host "**********************************************************************" -ForegroundColor Magenta + #Write-Host "" $foreground = if ($outcomeForFramework -eq 'Failed') { 'Red' } else { 'Green' } Write-Host "Result: " -NoNewline; Write-Host "$outcomeForFramework" -ForegroundColor $foreground Write-Host "" @@ -594,6 +736,8 @@ function Summarize-Test-Results() { Write-Host "Warning: " -NoNewline; Write-Host "$warningCountForFramework" -ForegroundColor $foreground $foreground = if ($failedCountForFramework -gt 0) { 'Cyan' } else { (Get-Host).UI.RawUI.ForegroundColor } Write-Host "Inconclusive: " -NoNewline; Write-Host "$inconclusiveCountForFramework" -ForegroundColor $foreground + Write-Host "" + Write-Host "See the .trx logs in $test_results_directory/$framework for more details." -ForegroundColor DarkCyan } } @@ -631,4 +775,10 @@ function Ensure-Directory-Exists([string] $path) { if (!(Test-Path $path)) { New-Item $path -ItemType Directory } +} + +function New-TemporaryDirectory { + $parent = [System.IO.Path]::GetTempPath() + [string] $name = [System.Guid]::NewGuid() + New-Item -ItemType Directory -Path (Join-Path $parent $name) } \ No newline at end of file diff --git a/src/Lucene.Net.Tests.Analysis.Common/Analysis/Th/TestThaiAnalyzer.cs b/src/Lucene.Net.Tests.Analysis.Common/Analysis/Th/TestThaiAnalyzer.cs index c208618..4dc1c2a 100644 --- a/src/Lucene.Net.Tests.Analysis.Common/Analysis/Th/TestThaiAnalyzer.cs +++ b/src/Lucene.Net.Tests.Analysis.Common/Analysis/Th/TestThaiAnalyzer.cs @@ -92,6 +92,48 @@ namespace Lucene.Net.Analysis.Th AssertAnalyzesTo(analyzer, "ประโยคว่า The quick brown fox jumped over the lazy dogs", new string[] { "ประโยค", "ว่า", "quick", "brown", "fox", "jumped", "over", "lazy", "dogs" }); } + // Ellision character + private static readonly char THAI_PAIYANNOI = (char)0x0E2F; + // Repeat character + private static readonly char THAI_MAIYAMOK = (char)0x0E46; + + [Test] + [LuceneNetSpecific] + public virtual void TestThaiBreakEngineInitializerCode() + { + // Initialize UnicodeSets + var fThaiWordSet = new ICU4N.Text.UnicodeSet(); + var fMarkSet = new ICU4N.Text.UnicodeSet(); + var fBeginWordSet = new ICU4N.Text.UnicodeSet(); + var fSuffixSet = new ICU4N.Text.UnicodeSet(); + + fThaiWordSet.ApplyPattern("[[:Thai:]&[:LineBreak=SA:]]"); + fThaiWordSet.Compact(); + + fMarkSet.ApplyPattern("[[:Thai:]&[:LineBreak=SA:]&[:M:]]"); + fMarkSet.Add(0x0020); + var fEndWordSet = new ICU4N.Text.UnicodeSet(fThaiWordSet); + fEndWordSet.Remove(0x0E31); // MAI HAN-AKAT + fEndWordSet.Remove(0x0E40, 0x0E44); // SARA E through SARA AI MAIMALAI + fBeginWordSet.Add(0x0E01, 0x0E2E); //KO KAI through HO NOKHUK + fBeginWordSet.Add(0x0E40, 0x0E44); // SARA E through SARA AI MAIMALAI + fSuffixSet.Add(THAI_PAIYANNOI); + fSuffixSet.Add(THAI_MAIYAMOK); + + // Compact for caching + fMarkSet.Compact(); + fEndWordSet.Compact(); + fBeginWordSet.Compact(); + fSuffixSet.Compact(); + + // Freeze the static UnicodeSet + fThaiWordSet.Freeze(); + fMarkSet.Freeze(); + fEndWordSet.Freeze(); + fBeginWordSet.Freeze(); + fSuffixSet.Freeze(); + } + /* * Test that position increments are adjusted correctly for stopwords. */
