# Starter pipeline # Start with a minimal pipeline that you can customize to build and deploy your code. # Add steps that build, run tests, deploy, and more: # https://aka.ms/yaml variables: outputFolder: './_output' artifactsFolder: './_artifacts' testsFolder: './_tests' majorVersion: '0.7.2' minorVersion: $[counter('minorVersion', 1076)] lidarrVersion: '$(majorVersion).$(minorVersion)' buildName: '$(Build.SourceBranchName).$(lidarrVersion)' sentryOrg: 'radarr' dotnetVersion: '3.1.101' trigger: branches: include: - develop - master pr: - develop stages: - stage: Build_Backend displayName: Build Backend jobs: - job: Backend strategy: matrix: Linux: osName: 'Linux' imageName: 'ubuntu-18.04' Mac: osName: 'Mac' imageName: 'macos-10.14' Windows: osName: 'Windows' imageName: 'windows-2019' pool: vmImage: $(imageName) steps: # Set the build name properly. The 'name' property won't recursively expand so hack here: - powershell: Write-Host "##vso[build.updatebuildnumber]$($env:LIDARRVERSION)" displayName: Set Build Name - checkout: self submodules: true fetchDepth: 1 - task: UseDotNet@2 displayName: 'Install .net core' inputs: version: $(dotnetVersion) - bash: ./build.sh --backend displayName: Build Lidarr Backend - bash: | find ${OUTPUTFOLDER} -type f ! -path "*/publish/*" -exec rm -rf {} \; find ${OUTPUTFOLDER} -depth -empty -type d -exec rm -r "{}" \; find ${TESTSFOLDER} -type f ! -path "*/publish/*" -exec rm -rf {} \; find ${TESTSFOLDER} -depth -empty -type d -exec rm -r "{}" \; displayName: Clean up intermediate output condition: and(succeeded(), ne(variables['osName'], 'Windows')) - publish: $(outputFolder) artifact: '$(osName)Backend' displayName: Publish Backend condition: and(succeeded(), eq(variables['osName'], 'Windows')) - publish: '$(testsFolder)/netcoreapp3.1/win-x64/publish' artifact: WindowsCoreTests displayName: Publish Windows Test Package condition: and(succeeded(), eq(variables['osName'], 'Windows')) - publish: '$(testsFolder)/net462/linux-x64/publish' artifact: LinuxTests displayName: Publish Linux Test Package condition: and(succeeded(), eq(variables['osName'], 'Windows')) - publish: '$(testsFolder)/netcoreapp3.1/linux-x64/publish' artifact: LinuxCoreTests displayName: Publish Linux Test Package condition: and(succeeded(), eq(variables['osName'], 'Windows')) - publish: '$(testsFolder)/netcoreapp3.1/osx-x64/publish' artifact: MacCoreTests displayName: Publish MacOS Test Package condition: and(succeeded(), eq(variables['osName'], 'Windows')) - stage: Build_Frontend displayName: Frontend dependsOn: [] jobs: - job: Build strategy: matrix: Linux: osName: 'Linux' imageName: 'ubuntu-18.04' Mac: osName: 'Mac' imageName: 'macos-10.14' Windows: osName: 'Windows' imageName: 'windows-2019' pool: vmImage: $(imageName) steps: - task: NodeTool@0 displayName: Set Node.js version inputs: versionSpec: '10.x' - checkout: self submodules: true fetchDepth: 1 - bash: ./build.sh --frontend displayName: Build Lidarr Frontend env: FORCE_COLOR: 0 - publish: $(outputFolder) artifact: '$(osName)Frontend' displayName: Publish Frontend condition: and(succeeded(), eq(variables['osName'], 'Windows')) - stage: Installer dependsOn: - Build_Backend - Build_Frontend jobs: - job: Windows_Installer displayName: Create Installer pool: vmImage: 'windows-2019' steps: - checkout: self fetchDepth: 1 - task: DownloadPipelineArtifact@2 inputs: buildType: 'current' artifactName: WindowsBackend targetPath: _output displayName: Fetch Backend - task: DownloadPipelineArtifact@2 inputs: buildType: 'current' artifactName: WindowsFrontend targetPath: _output displayName: Fetch Frontend - bash: ./build.sh --packages displayName: Create Packages - bash: | setup/inno/ISCC.exe setup/lidarr.iss //DFramework=netcoreapp3.1 cp setup/output/Lidarr.*windows.netcoreapp3.1.exe ${BUILD_ARTIFACTSTAGINGDIRECTORY}/Lidarr.${BUILDNAME}.windows-core-x64-installer.exe displayName: Create .NET Core Windows installer - publish: $(Build.ArtifactStagingDirectory) artifact: 'WindowsInstaller' displayName: Publish Installer - stage: Packages dependsOn: - Build_Backend - Build_Frontend jobs: - job: Other_Packages displayName: Create Standard Packages pool: vmImage: 'ubuntu-18.04' steps: - checkout: self fetchDepth: 1 - task: DownloadPipelineArtifact@2 inputs: buildType: 'current' artifactName: WindowsBackend targetPath: _output displayName: Fetch Backend - task: DownloadPipelineArtifact@2 inputs: buildType: 'current' artifactName: WindowsFrontend targetPath: _output displayName: Fetch Frontend - bash: ./build.sh --packages displayName: Create Packages - bash: | find . -name "fpcalc" -exec chmod a+x {} \; find . -name "Lidarr" -exec chmod a+x {} \; find . -name "Lidarr.Update" -exec chmod a+x {} \; displayName: Set executable bits - task: ArchiveFiles@2 displayName: Create Windows Core zip inputs: archiveFile: '$(Build.ArtifactStagingDirectory)/Lidarr.$(buildName).windows-core-x64.zip' archiveType: 'zip' includeRootFolder: false rootFolderOrFile: $(artifactsFolder)/windows/netcoreapp3.1 - task: ArchiveFiles@2 displayName: Create MacOS Core app inputs: archiveFile: '$(Build.ArtifactStagingDirectory)/Lidarr.$(buildName).osx-app-core-x64.zip' archiveType: 'zip' includeRootFolder: false rootFolderOrFile: $(artifactsFolder)/macos-app/netcoreapp3.1 - task: ArchiveFiles@2 displayName: Create MacOS Core tar inputs: archiveFile: '$(Build.ArtifactStagingDirectory)/Lidarr.$(buildName).osx-core-x64.tar.gz' archiveType: 'tar' tarCompression: 'gz' includeRootFolder: false rootFolderOrFile: $(artifactsFolder)/macos/netcoreapp3.1 - task: ArchiveFiles@2 displayName: Create Linux Mono tar inputs: archiveFile: '$(Build.ArtifactStagingDirectory)/Lidarr.$(buildName).linux.tar.gz' archiveType: 'tar' tarCompression: 'gz' includeRootFolder: false rootFolderOrFile: $(artifactsFolder)/linux-x64/net462 - task: ArchiveFiles@2 displayName: Create Linux Core tar inputs: archiveFile: '$(Build.ArtifactStagingDirectory)/Lidarr.$(buildName).linux-core-x64.tar.gz' archiveType: 'tar' tarCompression: 'gz' includeRootFolder: false rootFolderOrFile: $(artifactsFolder)/linux-x64/netcoreapp3.1 - task: ArchiveFiles@2 displayName: Create ARM32 Core tar inputs: archiveFile: '$(Build.ArtifactStagingDirectory)/Lidarr.$(buildName).linux-core-arm.tar.gz' archiveType: 'tar' tarCompression: 'gz' includeRootFolder: false rootFolderOrFile: $(artifactsFolder)/linux-arm/netcoreapp3.1 - task: ArchiveFiles@2 displayName: Create Linux Core tar inputs: archiveFile: '$(Build.ArtifactStagingDirectory)/Lidarr.$(buildName).linux-core-arm64.tar.gz' archiveType: 'tar' tarCompression: 'gz' includeRootFolder: false rootFolderOrFile: $(artifactsFolder)/linux-arm64/netcoreapp3.1 - publish: $(Build.ArtifactStagingDirectory) artifact: 'Packages' displayName: Publish Packages - bash: | echo "Uploading source maps to sentry" curl -sL https://sentry.io/get-cli/ | bash RELEASENAME="${LIDARRVERSION}-${BUILD_SOURCEBRANCHNAME}" sentry-cli releases new --finalize -p lidarr -p lidarr-ui -p lidarr-update "${RELEASENAME}" sentry-cli releases -p lidarr-ui files "${RELEASENAME}" upload-sourcemaps _output/UI/ --rewrite sentry-cli releases set-commits --auto "${RELEASENAME}" if [[ ${BUILD_SOURCEBRANCH} == "refs/heads/develop" ]]; then sentry-cli releases deploys "${RELEASENAME}" new -e nightly else sentry-cli releases deploys "${RELEASENAME}" new -e production fi displayName: Publish Sentry Source Maps condition: | or ( and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/develop')), and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master')) ) env: SENTRY_AUTH_TOKEN: $(sentryAuthTokenSelfHosted) SENTRY_ORG: $(sentryOrg) SENTRY_URL: https://sentry.radarr.video - stage: Unit_Test displayName: Unit Tests dependsOn: Build_Backend condition: succeeded() jobs: - job: Unit displayName: Unit Native strategy: matrix: MacCore: osName: 'Mac' testName: 'MacCore' imageName: 'macos-10.14' WindowsCore: osName: 'Windows' testName: 'WindowsCore' imageName: 'windows-2019' LinuxCore: osName: 'Linux' testName: 'LinuxCore' imageName: 'ubuntu-18.04' pattern: 'Lidarr.**.linux-core-x64.tar.gz' pool: vmImage: $(imageName) steps: - checkout: none - task: UseDotNet@2 displayName: 'Install .net core' inputs: version: $(dotnetVersion) - task: DownloadPipelineArtifact@2 displayName: Download Test Artifact inputs: buildType: 'current' artifactName: '$(testName)Tests' targetPath: $(testsFolder) - powershell: Set-Service SCardSvr -StartupType Manual displayName: Enable Windows Test Service condition: and(succeeded(), eq(variables['osName'], 'Windows')) - bash: | wget https://github.com/acoustid/chromaprint/releases/download/v1.4.3/chromaprint-fpcalc-1.4.3-linux-x86_64.tar.gz sudo tar xf chromaprint-fpcalc-1.4.3-linux-x86_64.tar.gz --strip-components=1 --directory /usr/bin chmod a+x _tests/fpcalc displayName: Install fpcalc condition: and(succeeded(), eq(variables['osName'], 'Linux')) - bash: | SYMLINK=6_6_0 MONOPREFIX=/Library/Frameworks/Mono.framework/Versions/$SYMLINK echo "##vso[task.setvariable variable=MONOPREFIX;]$MONOPREFIX" echo "##vso[task.setvariable variable=PKG_CONFIG_PATH;]$MONOPREFIX/lib/pkgconfig:$MONOPREFIX/share/pkgconfig:$PKG_CONFIG_PATH" echo "##vso[task.setvariable variable=PATH;]$MONOPREFIX/bin:$PATH" chmod a+x _tests/fpcalc displayName: Set Mono Version and make fpcalc Executable condition: and(succeeded(), eq(variables['osName'], 'Mac')) - bash: find ${TESTSFOLDER} -name "Lidarr.Test.Dummy" -exec chmod a+x {} \; displayName: Make Test Dummy Executable condition: and(succeeded(), ne(variables['osName'], 'Windows')) - task: Bash@3 displayName: Run Tests env: TEST_DIR: $(Build.SourcesDirectory)/_tests inputs: targetType: 'filePath' filePath: '$(testsFolder)/test.sh' arguments: '$(osName) Unit Test' - task: PublishTestResults@2 displayName: Publish Test Results inputs: testResultsFormat: 'NUnit' testResultsFiles: '**/TestResult.xml' testRunTitle: '$(testName) Unit Tests' failTaskOnFailedTests: true - job: Unit_Docker displayName: Unit Docker strategy: matrix: mono508: testName: 'Mono 5.8' containerImage: lidarr/testimages:mono-5.8 mono520: testName: 'Mono 5.20' containerImage: lidarr/testimages:mono-5.20 mono608: testName: 'Mono 6.8' containerImage: lidarr/testimages:mono-6.8 mono610: testName: 'Mono 6.10' containerImage: lidarr/testimages:mono-6.10 pool: vmImage: 'ubuntu-18.04' container: $[ variables['containerImage'] ] timeoutInMinutes: 10 steps: - bash: mono --version displayName: Check Mono version - task: UseDotNet@2 displayName: 'Install .net core' inputs: version: $(dotnetVersion) - checkout: none - task: DownloadPipelineArtifact@2 displayName: Download Test Artifact inputs: buildType: 'current' artifactName: LinuxTests targetPath: $(testsFolder) - task: Bash@3 displayName: Run Tests inputs: targetType: 'filePath' filePath: '$(testsFolder)/test.sh' arguments: 'Linux Unit Test' - task: PublishTestResults@2 displayName: Publish Test Results inputs: testResultsFormat: 'NUnit' testResultsFiles: '**/TestResult.xml' testRunTitle: '$(testName) Unit Tests' failTaskOnFailedTests: true - stage: Integration displayName: Integration dependsOn: Packages jobs: - job: Integration_Native displayName: Integration Native strategy: matrix: MacCore: osName: 'Mac' testName: 'MacCore' imageName: 'macos-10.14' pattern: 'Lidarr.**.osx-core-x64.tar.gz' WindowsCore: osName: 'Windows' testName: 'WindowsCore' imageName: 'windows-2019' pattern: 'Lidarr.**.windows-core-x64.zip' LinuxCore: osName: 'Linux' testName: 'LinuxCore' imageName: 'ubuntu-18.04' pattern: 'Lidarr.**.linux-core-x64.tar.gz' pool: vmImage: $(imageName) steps: - bash: | SYMLINK=6_6_0 MONOPREFIX=/Library/Frameworks/Mono.framework/Versions/$SYMLINK echo "##vso[task.setvariable variable=MONOPREFIX;]$MONOPREFIX" echo "##vso[task.setvariable variable=PKG_CONFIG_PATH;]$MONOPREFIX/lib/pkgconfig:$MONOPREFIX/share/pkgconfig:$PKG_CONFIG_PATH" echo "##vso[task.setvariable variable=PATH;]$MONOPREFIX/bin:$PATH" displayName: Set Mono Version condition: and(succeeded(), eq(variables['osName'], 'Mac')) - task: UseDotNet@2 displayName: 'Install .net core' inputs: version: $(dotnetVersion) - checkout: none - task: DownloadPipelineArtifact@2 displayName: Download Test Artifact inputs: buildType: 'current' artifactName: '$(testName)Tests' targetPath: $(testsFolder) - task: DownloadPipelineArtifact@2 displayName: Download Build Artifact inputs: buildType: 'current' artifactName: Packages itemPattern: '**/$(pattern)' targetPath: $(Build.ArtifactStagingDirectory) - task: ExtractFiles@1 inputs: archiveFilePatterns: '$(Build.ArtifactStagingDirectory)/**/$(pattern)' destinationFolder: '$(Build.ArtifactStagingDirectory)/bin' displayName: Extract Package - bash: | mkdir -p ./bin/ cp -r -v ${BUILD_ARTIFACTSTAGINGDIRECTORY}/bin/Lidarr/. ./bin/ displayName: Move Package Contents - task: Bash@3 displayName: Run Integration Tests inputs: targetType: 'filePath' filePath: '$(testsFolder)/test.sh' arguments: $(osName) Integration Test - task: PublishTestResults@2 inputs: testResultsFormat: 'NUnit' testResultsFiles: '**/TestResult.xml' testRunTitle: '$(testName) Integration Tests' failTaskOnFailedTests: true displayName: Publish Test Results - job: Integration_Docker displayName: Integration Docker strategy: matrix: mono508: testName: 'Mono 5.8' containerImage: lidarr/testimages:mono-5.8 mono520: testName: 'Mono 5.20' containerImage: lidarr/testimages:mono-5.20 mono608: testName: 'Mono 6.8' containerImage: lidarr/testimages:mono-6.8 mono610: testName: 'Mono 6.10' containerImage: lidarr/testimages:mono-6.10 variables: pattern: 'Lidarr.**.linux.tar.gz' pool: vmImage: 'ubuntu-18.04' container: $[ variables['containerImage'] ] timeoutInMinutes: 15 steps: - bash: mono --version displayName: Check Mono version - task: UseDotNet@2 displayName: 'Install .net core' inputs: version: $(dotnetVersion) - checkout: none - task: DownloadPipelineArtifact@2 displayName: Download Test Artifact inputs: buildType: 'current' artifactName: LinuxTests targetPath: $(testsFolder) - task: DownloadPipelineArtifact@2 displayName: Download Build Artifact inputs: buildType: 'current' artifactName: Packages itemPattern: '**/$(pattern)' targetPath: $(Build.ArtifactStagingDirectory) - task: ExtractFiles@1 inputs: archiveFilePatterns: '$(Build.ArtifactStagingDirectory)/**/$(pattern)' destinationFolder: '$(Build.ArtifactStagingDirectory)/bin' displayName: Extract Package - bash: | mkdir -p ./bin/ cp -r -v ${BUILD_ARTIFACTSTAGINGDIRECTORY}/bin/Lidarr/. ./bin/ displayName: Move Package Contents - task: Bash@3 displayName: Run Integration Tests inputs: targetType: 'filePath' filePath: '$(testsFolder)/test.sh' arguments: Linux Integration Test - task: PublishTestResults@2 inputs: testResultsFormat: 'NUnit' testResultsFiles: '**/TestResult.xml' testRunTitle: '$(testName) Integration Tests' failTaskOnFailedTests: true displayName: Publish Test Results - stage: Automation displayName: Automation dependsOn: Packages jobs: - job: Automation strategy: matrix: Linux: osName: 'Linux' imageName: 'ubuntu-18.04' pattern: 'Lidarr.**.linux-core-x64.tar.gz' failBuild: true Mac: osName: 'Mac' imageName: 'macos-10.14' # Fails due to firefox not being installed on image pattern: 'Lidarr.**.osx-core-x64.tar.gz' failBuild: false Windows: osName: 'Windows' imageName: 'windows-2019' pattern: 'Lidarr.**.windows-core-x64.zip' failBuild: true pool: vmImage: $(imageName) steps: - task: UseDotNet@2 displayName: 'Install .net core' inputs: version: $(dotnetVersion) - checkout: none - task: DownloadPipelineArtifact@2 displayName: Download Test Artifact inputs: buildType: 'current' artifactName: '$(osName)CoreTests' targetPath: $(testsFolder) - task: DownloadPipelineArtifact@2 displayName: Download Build Artifact inputs: buildType: 'current' artifactName: Packages itemPattern: '**/$(pattern)' targetPath: $(Build.ArtifactStagingDirectory) - task: ExtractFiles@1 inputs: archiveFilePatterns: '$(Build.ArtifactStagingDirectory)/**/$(pattern)' destinationFolder: '$(Build.ArtifactStagingDirectory)/bin' displayName: Extract Package - bash: | mkdir -p ./bin/ cp -r -v ${BUILD_ARTIFACTSTAGINGDIRECTORY}/bin/Lidarr/. ./bin/ displayName: Move Package Contents - bash: | if [[ $OSNAME == "Mac" ]]; then url=https://github.com/mozilla/geckodriver/releases/download/v0.26.0/geckodriver-v0.26.0-macos.tar.gz elif [[ $OSNAME == "Linux" ]]; then url=https://github.com/mozilla/geckodriver/releases/download/v0.26.0/geckodriver-v0.26.0-linux64.tar.gz else echo "Unhandled OS" exit 1 fi curl -s -L "$url" | tar -xz chmod +x geckodriver mv geckodriver _tests displayName: Install Gecko Driver condition: and(succeeded(), ne(variables['osName'], 'Windows')) - task: Bash@3 displayName: Run Automation Tests inputs: targetType: 'filePath' filePath: '$(testsFolder)/test.sh' arguments: $(osName) Automation Test - task: PublishTestResults@2 inputs: testResultsFormat: 'NUnit' testResultsFiles: '**/TestResult.xml' testRunTitle: '$(osName) Automation Tests' failTaskOnFailedTests: $(failBuild) displayName: Publish Test Results - stage: Analyze dependsOn: [] displayName: Analyze condition: eq(variables['system.pullrequest.isfork'], false) jobs: - job: Lint_Frontend displayName: Lint Frontend strategy: matrix: Linux: osName: 'Linux' imageName: 'ubuntu-18.04' Windows: osName: 'Windows' imageName: 'windows-2019' pool: vmImage: $(imageName) steps: - task: NodeTool@0 displayName: Set Node.js version inputs: versionSpec: '10.x' - checkout: self submodules: true fetchDepth: 1 - bash: ./build.sh --lint displayName: Lint Lidarr Frontend env: FORCE_COLOR: 0 - job: Analyze_Frontend displayName: Frontend pool: vmImage: windows-2019 steps: - checkout: self # Need history for Sonar analysis - task: SonarCloudPrepare@1 env: SONAR_SCANNER_OPTS: '' inputs: SonarCloud: 'SonarCloud' organization: 'lidarr' scannerMode: 'CLI' configMode: 'manual' cliProjectKey: 'lidarr_Lidarr.UI' cliProjectName: 'LidarrUI' cliProjectVersion: '$(lidarrVersion)' cliSources: './frontend' - task: SonarCloudAnalyze@1 - job: Analyze_Backend displayName: Backend pool: vmImage: windows-2019 variables: disable.coverage.autogenerate: 'true' steps: - task: UseDotNet@2 displayName: 'Install .net core' inputs: version: $(dotnetVersion) - checkout: self # Need history for Sonar analysis submodules: true - powershell: Set-Service SCardSvr -StartupType Manual displayName: Enable Windows Test Service - task: SonarCloudPrepare@1 inputs: SonarCloud: 'SonarCloud' organization: 'lidarr' scannerMode: 'MSBuild' projectKey: 'lidarr_Lidarr' projectName: 'Lidarr' projectVersion: '$(lidarrVersion)' extraProperties: | sonar.exclusions=**/obj/**,**/*.dll,**/NzbDrone.Core.Test/Files/**/*,./frontend/**,**/ExternalModules/**,./src/Libraries/** sonar.coverage.exclusions=**/Lidarr.Api.V1/**/*,**/MonoTorrent/**/*,**/Marr.Data/**/* sonar.cs.opencover.reportsPaths=$(Build.SourcesDirectory)/CoverageResults/**/coverage.opencover.xml sonar.cs.nunit.reportsPaths=$(Build.SourcesDirectory)/TestResult.xml - bash: | ./build.sh --backend -f netcoreapp3.1 -r win-x64 TEST_DIR=_tests/netcoreapp3.1/win-x64/publish/ ./test.sh Windows Unit Coverage displayName: Coverage Unit Tests - task: SonarCloudAnalyze@1 displayName: Publish SonarCloud Results - task: reportgenerator@4 displayName: Generate Coverage Report inputs: reports: '$(Build.SourcesDirectory)/CoverageResults/**/coverage.opencover.xml' targetdir: '$(Build.SourcesDirectory)/CoverageResults/combined' reporttypes: 'HtmlInline_AzurePipelines;Cobertura;Badges' - task: PublishCodeCoverageResults@1 displayName: Publish Coverage Report inputs: codeCoverageTool: 'cobertura' summaryFileLocation: './CoverageResults/combined/Cobertura.xml' reportDirectory: './CoverageResults/combined/'