name: $(Date:yyyyMMdd)$(Rev:.r) variables: - name: TestProjects value: 'tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj' - name: RestoreBuildProjects value: 'Jellyfin.Server/Jellyfin.Server.csproj' pr: autoCancel: true trigger: batch: true jobs: - job: main_build displayName: Main Build pool: vmImage: ubuntu-latest strategy: matrix: release: BuildConfiguration: Release debug: BuildConfiguration: Debug maxParallel: 2 steps: - checkout: self clean: true submodules: true persistCredentials: true - task: CmdLine@2 displayName: "Check out web" condition: and(succeeded(), or(contains(variables['Build.SourceBranch'], 'release'), contains(variables['Build.SourceBranch'], 'master')) ,eq(variables['BuildConfiguration'], 'Release'), in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI', 'BuildCompletion')) inputs: script: 'git clone --single-branch --branch $(Build.SourceBranchName) --depth=1 https://github.com/jellyfin/jellyfin-web.git $(Agent.TempDirectory)/jellyfin-web' - task: CmdLine@2 displayName: "Check out web (PR)" condition: and(succeeded(), or(contains(variables['System.PullRequest.TargetBranch'], 'release'), contains(variables['System.PullRequest.TargetBranch'], 'master')) ,eq(variables['BuildConfiguration'], 'Release'), in(variables['Build.Reason'], 'PullRequest')) inputs: script: 'git clone --single-branch --branch $(System.PullRequest.TargetBranch) --depth 1 https://github.com/jellyfin/jellyfin-web.git $(Agent.TempDirectory)/jellyfin-web' - task: NodeTool@0 displayName: 'Install Node.js' condition: and(succeeded(), or(contains(variables['System.PullRequest.TargetBranch'], 'release'), contains(variables['System.PullRequest.TargetBranch'], 'master'), contains(variables['Build.SourceBranch'], 'release'), contains(variables['Build.SourceBranch'], 'master')) ,eq(variables['BuildConfiguration'], 'Release'), in(variables['Build.Reason'], 'PullRequest', 'IndividualCI', 'BatchedCI', 'BuildCompletion')) inputs: versionSpec: '10.x' - task: CmdLine@2 displayName: "Build Web UI" condition: and(succeeded(), or(contains(variables['System.PullRequest.TargetBranch'], 'release'), contains(variables['System.PullRequest.TargetBranch'], 'master'), contains(variables['Build.SourceBranch'], 'release'), contains(variables['Build.SourceBranch'], 'master')) ,eq(variables['BuildConfiguration'], 'Release'), in(variables['Build.Reason'], 'PullRequest', 'IndividualCI', 'BatchedCI', 'BuildCompletion')) inputs: script: yarn install workingDirectory: $(Agent.TempDirectory)/jellyfin-web - task: CopyFiles@2 displayName: Copy the web UI condition: and(succeeded(), or(contains(variables['System.PullRequest.TargetBranch'], 'release'), contains(variables['System.PullRequest.TargetBranch'], 'master'), contains(variables['Build.SourceBranch'], 'release'), contains(variables['Build.SourceBranch'], 'master')) ,eq(variables['BuildConfiguration'], 'Release'), in(variables['Build.Reason'], 'PullRequest', 'IndividualCI', 'BatchedCI', 'BuildCompletion')) inputs: sourceFolder: $(Agent.TempDirectory)/jellyfin-web/dist # Optional contents: '**' targetFolder: $(Build.SourcesDirectory)/MediaBrowser.WebDashboard/jellyfin-web cleanTargetFolder: true # Optional overWrite: true # Optional flattenFolders: false # Optional - task: DotNetCoreCLI@2 displayName: Publish inputs: command: publish publishWebProjects: false projects: '$(RestoreBuildProjects)' arguments: '--configuration $(BuildConfiguration) --output $(build.artifactstagingdirectory)' zipAfterPublish: false - task: PublishPipelineArtifact@0 displayName: 'Publish Artifact Naming' condition: and(eq(variables['BuildConfiguration'], 'Release'), succeeded()) inputs: targetPath: '$(build.artifactstagingdirectory)/Jellyfin.Server/Emby.Naming.dll' artifactName: 'Jellyfin.Naming' - task: PublishPipelineArtifact@0 displayName: 'Publish Artifact Controller' condition: and(eq(variables['BuildConfiguration'], 'Release'), succeeded()) inputs: targetPath: '$(build.artifactstagingdirectory)/Jellyfin.Server/MediaBrowser.Controller.dll' artifactName: 'Jellyfin.Controller' - task: PublishPipelineArtifact@0 displayName: 'Publish Artifact Model' condition: and(eq(variables['BuildConfiguration'], 'Release'), succeeded()) inputs: targetPath: '$(build.artifactstagingdirectory)/Jellyfin.Server/MediaBrowser.Model.dll' artifactName: 'Jellyfin.Model' - task: PublishPipelineArtifact@0 displayName: 'Publish Artifact Common' condition: and(eq(variables['BuildConfiguration'], 'Release'), succeeded()) inputs: targetPath: '$(build.artifactstagingdirectory)/Jellyfin.Server/MediaBrowser.Common.dll' artifactName: 'Jellyfin.Common' - job: main_test displayName: Main Test pool: vmImage: windows-latest steps: - checkout: self clean: true submodules: true persistCredentials: false - task: DotNetCoreCLI@2 displayName: Build inputs: command: build publishWebProjects: false projects: '$(TestProjects)' arguments: '--configuration $(BuildConfiguration)' zipAfterPublish: false - task: VisualStudioTestPlatformInstaller@1 inputs: packageFeedSelector: 'nugetOrg' # Options: nugetOrg, customFeed, netShare versionSelector: 'latestPreRelease' # Required when packageFeedSelector == NugetOrg || PackageFeedSelector == CustomFeed# Options: latestPreRelease, latestStable, specificVersion - task: VSTest@2 inputs: testSelector: 'testAssemblies' # Options: testAssemblies, testPlan, testRun testAssemblyVer2: | # Required when testSelector == TestAssemblies **\bin\$(BuildConfiguration)\**\*test*.dll !**\obj\** !**\xunit.runner.visualstudio.testadapter.dll !**\xunit.runner.visualstudio.dotnetcore.testadapter.dll #testPlan: # Required when testSelector == TestPlan #testSuite: # Required when testSelector == TestPlan #testConfiguration: # Required when testSelector == TestPlan #tcmTestRun: '$(test.RunId)' # Optional searchFolder: '$(System.DefaultWorkingDirectory)' #testFiltercriteria: # Optional #runOnlyImpactedTests: False # Optional #runAllTestsAfterXBuilds: '50' # Optional #uiTests: false # Optional #vstestLocationMethod: 'version' # Optional. Options: version, location #vsTestVersion: 'latest' # Optional. Options: latest, 16.0, 15.0, 14.0, toolsInstaller #vstestLocation: # Optional #runSettingsFile: # Optional #overrideTestrunParameters: # Optional #pathtoCustomTestAdapters: # Optional runInParallel: True # Optional runTestsInIsolation: True # Optional codeCoverageEnabled: True # Optional #otherConsoleOptions: # Optional #distributionBatchType: 'basedOnTestCases' # Optional. Options: basedOnTestCases, basedOnExecutionTime, basedOnAssembly #batchingBasedOnAgentsOption: 'autoBatchSize' # Optional. Options: autoBatchSize, customBatchSize #customBatchSizeValue: '10' # Required when distributionBatchType == BasedOnTestCases && BatchingBasedOnAgentsOption == CustomBatchSize #batchingBasedOnExecutionTimeOption: 'autoBatchSize' # Optional. Options: autoBatchSize, customTimeBatchSize #customRunTimePerBatchValue: '60' # Required when distributionBatchType == BasedOnExecutionTime && BatchingBasedOnExecutionTimeOption == CustomTimeBatchSize #dontDistribute: False # Optional #testRunTitle: # Optional #platform: # Optional configuration: 'Debug' # Optional publishRunAttachments: true # Optional #diagnosticsEnabled: false # Optional #collectDumpOn: 'onAbortOnly' # Optional. Options: onAbortOnly, always, never #rerunFailedTests: False # Optional #rerunType: 'basedOnTestFailurePercentage' # Optional. Options: basedOnTestFailurePercentage, basedOnTestFailureCount #rerunFailedThreshold: '30' # Optional #rerunFailedTestCasesMaxLimit: '5' # Optional #rerunMaxAttempts: '3' # Optional # - task: PublishTestResults@2 # inputs: # testResultsFormat: 'VSTest' # Options: JUnit, NUnit, VSTest, xUnit, cTest # testResultsFiles: '**/*.trx' # #searchFolder: '$(System.DefaultWorkingDirectory)' # Optional # mergeTestResults: true # Optional # #failTaskOnFailedTests: false # Optional # #testRunTitle: # Optional # #buildPlatform: # Optional # #buildConfiguration: # Optional # #publishRunAttachments: true # Optional - job: main_build_win displayName: Main Build Windows pool: vmImage: windows-latest strategy: matrix: release: BuildConfiguration: Release maxParallel: 2 steps: - checkout: self clean: true submodules: true persistCredentials: true - task: CmdLine@2 displayName: "Check out web" condition: and(succeeded(), or(contains(variables['Build.SourceBranch'], 'release'), contains(variables['Build.SourceBranch'], 'master')) ,eq(variables['BuildConfiguration'], 'Release'), in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI', 'BuildCompletion')) inputs: script: 'git clone --single-branch --branch $(Build.SourceBranchName) --depth=1 https://github.com/jellyfin/jellyfin-web.git $(Agent.TempDirectory)/jellyfin-web' - task: CmdLine@2 displayName: "Check out web (PR)" condition: and(succeeded(), or(contains(variables['System.PullRequest.TargetBranch'], 'release'), contains(variables['System.PullRequest.TargetBranch'], 'master')) ,eq(variables['BuildConfiguration'], 'Release'), in(variables['Build.Reason'], 'PullRequest')) inputs: script: 'git clone --single-branch --branch $(System.PullRequest.TargetBranch) --depth 1 https://github.com/jellyfin/jellyfin-web.git $(Agent.TempDirectory)/jellyfin-web' - task: NodeTool@0 displayName: 'Install Node.js' condition: and(succeeded(), or(contains(variables['System.PullRequest.TargetBranch'], 'release'), contains(variables['System.PullRequest.TargetBranch'], 'master'), contains(variables['Build.SourceBranch'], 'release'), contains(variables['Build.SourceBranch'], 'master')) ,eq(variables['BuildConfiguration'], 'Release'), in(variables['Build.Reason'], 'PullRequest', 'IndividualCI', 'BatchedCI', 'BuildCompletion')) inputs: versionSpec: '10.x' - task: CmdLine@2 displayName: "Build Web UI" condition: and(succeeded(), or(contains(variables['System.PullRequest.TargetBranch'], 'release'), contains(variables['System.PullRequest.TargetBranch'], 'master'), contains(variables['Build.SourceBranch'], 'release'), contains(variables['Build.SourceBranch'], 'master')) ,eq(variables['BuildConfiguration'], 'Release'), in(variables['Build.Reason'], 'PullRequest', 'IndividualCI', 'BatchedCI', 'BuildCompletion')) inputs: script: yarn install workingDirectory: $(Agent.TempDirectory)/jellyfin-web - task: CopyFiles@2 displayName: Copy the web UI condition: and(succeeded(), or(contains(variables['System.PullRequest.TargetBranch'], 'release'), contains(variables['System.PullRequest.TargetBranch'], 'master'), contains(variables['Build.SourceBranch'], 'release'), contains(variables['Build.SourceBranch'], 'master')) ,eq(variables['BuildConfiguration'], 'Release'), in(variables['Build.Reason'], 'PullRequest', 'IndividualCI', 'BatchedCI', 'BuildCompletion')) inputs: sourceFolder: $(Agent.TempDirectory)/jellyfin-web/dist # Optional contents: '**' targetFolder: $(Build.SourcesDirectory)/MediaBrowser.WebDashboard/jellyfin-web cleanTargetFolder: true # Optional overWrite: true # Optional flattenFolders: false # Optional - task: CmdLine@2 displayName: Clone the UX repository inputs: script: git clone --depth=1 https://github.com/jellyfin/jellyfin-ux $(Agent.TempDirectory)\jellyfin-ux - task: PowerShell@2 displayName: Build the NSIS Installer inputs: targetType: 'filePath' # Optional. Options: filePath, inline filePath: ./deployment/windows/build-jellyfin.ps1 # Required when targetType == FilePath arguments: -InstallFFMPEG -InstallNSSM -MakeNSIS -UXLocation $(Agent.TempDirectory)\jellyfin-ux -InstallLocation $(build.artifactstagingdirectory) #script: '# Write your PowerShell commands here.Write-Host Hello World' # Required when targetType == Inline errorActionPreference: 'stop' # Optional. Options: stop, continue, silentlyContinue #failOnStderr: false # Optional #ignoreLASTEXITCODE: false # Optional #pwsh: false # Optional workingDirectory: $(Build.SourcesDirectory) # Optional - task: CopyFiles@2 displayName: Copy the NSIS Installer to the artifact directory inputs: sourceFolder: $(Build.SourcesDirectory)/deployment/windows/ # Optional contents: 'jellyfin*.exe' targetFolder: $(System.ArtifactsDirectory)/setup cleanTargetFolder: true # Optional overWrite: true # Optional flattenFolders: true # Optional - task: PublishPipelineArtifact@0 displayName: 'Publish Setup Artifact' condition: and(eq(variables['BuildConfiguration'], 'Release'), succeeded()) inputs: targetPath: '$(build.artifactstagingdirectory)/setup' artifactName: 'Jellyfin Server Setup' - job: dotnet_compat displayName: Compatibility Check pool: vmImage: ubuntu-latest dependsOn: main_build condition: and(succeeded(), variables['System.PullRequest.PullRequestNumber']) # Only execute if the pullrequest numer is defined. (So not for normal CI builds) strategy: matrix: Naming: NugetPackageName: Jellyfin.Naming AssemblyFileName: Emby.Naming.dll Controller: NugetPackageName: Jellyfin.Controller AssemblyFileName: MediaBrowser.Controller.dll Model: NugetPackageName: Jellyfin.Model AssemblyFileName: MediaBrowser.Model.dll Common: NugetPackageName: Jellyfin.Common AssemblyFileName: MediaBrowser.Common.dll maxParallel: 2 steps: - checkout: none - task: DownloadPipelineArtifact@2 displayName: Download the New Assembly Build Artifact inputs: source: 'current' # Options: current, specific #preferTriggeringPipeline: false # Optional #tags: # Optional artifact: '$(NugetPackageName)' # Optional #patterns: '**' # Optional path: '$(System.ArtifactsDirectory)/new-artifacts' #project: # Required when source == Specific #pipeline: # Required when source == Specific runVersion: 'latest' # Required when source == Specific. Options: latest, latestFromBranch, specific #runBranch: 'refs/heads/master' # Required when source == Specific && runVersion == LatestFromBranch #runId: # Required when source == Specific && runVersion == Specific - task: CopyFiles@2 displayName: Copy New Assembly to new-release folder inputs: sourceFolder: $(System.ArtifactsDirectory)/new-artifacts # Optional contents: '**/*.dll' targetFolder: $(System.ArtifactsDirectory)/new-release cleanTargetFolder: true # Optional overWrite: true # Optional flattenFolders: true # Optional - task: DownloadPipelineArtifact@2 displayName: Download the Reference Assembly Build Artifact inputs: source: 'specific' # Options: current, specific #preferTriggeringPipeline: false # Optional #tags: # Optional artifact: '$(NugetPackageName)' # Optional #patterns: '**' # Optional path: '$(System.ArtifactsDirectory)/current-artifacts' project: '$(System.TeamProjectId)' # Required when source == Specific pipeline: '$(System.DefinitionId)' # Required when source == Specific runVersion: 'latestFromBranch' # Required when source == Specific. Options: latest, latestFromBranch, specific runBranch: 'refs/heads/$(System.PullRequest.TargetBranch)' # Required when source == Specific && runVersion == LatestFromBranch #runId: # Required when source == Specific && runVersion == Specific - task: CopyFiles@2 displayName: Copy Reference Assembly to current-release folder inputs: sourceFolder: $(System.ArtifactsDirectory)/current-artifacts # Optional contents: '**/*.dll' targetFolder: $(System.ArtifactsDirectory)/current-release cleanTargetFolder: true # Optional overWrite: true # Optional flattenFolders: true # Optional - task: DownloadGitHubRelease@0 displayName: Download ABI compatibility check tool from GitHub inputs: connection: Jellyfin Release Download userRepository: EraYaN/dotnet-compatibility defaultVersionType: 'latest' # Options: latest, specificVersion, specificTag #version: # Required when defaultVersionType != Latest itemPattern: '**-ci.zip' # Optional downloadPath: '$(System.ArtifactsDirectory)' - task: ExtractFiles@1 displayName: Extract ABI compatibility check tool inputs: archiveFilePatterns: '$(System.ArtifactsDirectory)/*-ci.zip' destinationFolder: $(System.ArtifactsDirectory)/tools cleanDestinationFolder: true - task: CmdLine@2 displayName: Execute ABI compatibility check tool inputs: script: 'dotnet tools/CompatibilityCheckerCoreCLI.dll current-release/$(AssemblyFileName) new-release/$(AssemblyFileName) --azure-pipelines' workingDirectory: $(System.ArtifactsDirectory) # Optional #failOnStderr: false # Optional