Git在具有多个项目的解决方案中检测更改的.csproj

时间:2019-06-11 18:07:35

标签: .net git continuous-integration nuget-package gitlab-ci

我们有一个包含12个.net standard项目的解决方案。这些项目中的每一个都以nuget package的形式发布。现在我们正在尝试使CI/CD流程自动化,因此我们需要一种方法(git command)来查找已更改的项目文件(.csproj),因此我们只能pack该特定项目(已更改)将发布到nuget repo,而不是解决方案中的所有项目。

1 个答案:

答案 0 :(得分:0)

我们用于解决此问题的Azure DevOps构建管道(YAML)是(仅相关部分):

# Definition of tags which trigger this pipeline.
# Asterisk is for version number, so the real tag is for example "proj1-v1.1.0".
trigger:
  tags:
    include: [ 'proj1-v*', 'proj2-v*', 'proj3-v*' ]

... # Other not relevant config.


# Among standard variables such as "buildConfiguration" and others, we have these.
# The values of "project.ProjX" variables are basically real project names without ".csproj" extension.
# These are not so important, we just want to use variables later in the build steps.
variables:
  - name: project.Proj1
    value: 'Company.Proj1'
  - name: project.Proj2
    value: 'Company.Proj2'
  - name: project.Proj3
    value: 'Company.Proj3.Extensions'

# This is variable for holding project for which the build was triggered - the one which will be pushed to NuGet.
  - name: 'project.Current' 
    value: ''

# This is special variable. Some of the projects does not have unit tests,
# but test step is failing if it does not find any assembly with tests.
# So we count relevant assemblies and run test step only if there is some.
  - name: 'project.TestProjectsCount'
    value:  0


steps:
# These steps sets "project.Current" variable to the project name based on the tag which triggerd the build.
# Based on condition, only one of these steps is executed.
  - powershell: echo '##vso[task.setvariable variable=project.Current]$(project.Proj1)'
    displayName: 'Set project: $(project.Proj1)'
    condition: startsWith(variables['Build.SourceBranch'], 'refs/tags/proj1-v')

  - powershell: echo '##vso[task.setvariable variable=project.Current]$(project.Proj2)'
    displayName: 'Set project: $(project.Proj2)'
    condition: startsWith(variables['Build.SourceBranch'], 'refs/tags/proj2-v')

  - powershell: echo '##vso[task.setvariable variable=project.Current]$(project.Proj3)'
    displayName: 'Set project: $(project.Proj3)'
    condition: startsWith(variables['Build.SourceBranch'], 'refs/tags/proj3-v')


# This should not happen, but this step is executed when the pipeline is started with incorrect tag name: variable "project.Current" is empty.
# We print info what happened and the pipeline is stopped (exit 1).
  - script: |
      echo No project was specified.
      echo Build must be triggered with correct tag and based on the tag name, the project is selected.
      echo Available tag names and their projects:
      echo   - proj1-v* - Company.Proj1
      echo   - proj2-v* - Company.Proj2
      echo   - proj3-v* - Company.Proj3.Extensions
      exit 1
    displayName: 'Check project name'
    condition: eq(variables['project.Current'], '')


... # General steps: nuget restore, build ...


# This step counts test assemblies relevant for current project (we do not want to run tests for other projects).
# Number of relevant test projects is set into "project.TestProjectsCount" variable.
  - powershell: |
      $count = 0
      Get-ChildItem -Path "$env:System_DefaultWorkingDirectory" -Filter "$(project.Current)*test*.csproj" -Recurse -File | ForEach-Object {
        $count = $count + 1
      }
      Write-Host Test projects found: $count
      Write-Output ("##vso[task.setvariable variable=project.TestProjectsCount;]$count")
    displayName: Find Test Projects


# Final steps, which operates only with relevant project "project.Current".
#   - Run all tests for current project, but only if we have test assemblies (project.TestProjectsCount > 0).
#   - Pack NuGet package.
#   - Copy NuGet package to the staging folder.
#   - Publish NuGet package.
  - task: DotNetCoreCLI@2
    displayName: 'Tests'
    condition: gt(variables['project.TestProjectsCount'], 0)
    inputs:
      command: test
      projects: '**/$(project.current)*[Tt]ests*.csproj'

  - task: DotNetCoreCLI@2
    displayName: 'Pack'
    inputs:
      command: pack
      projects: '**/$(project.current).csproj'

  - task: CopyFiles@2
    displayName: 'Copy package files to staging directory'
    inputs:
      Contents: '**/$(project.current)*.nupkg'
      TargetFolder: '$(build.artifactStagingDirectory)'
      FlattenFolders: true

# This is our template for pushing to nuget.
# It just calls "nuget push" with correct parameters: feed URL, feed API key...
  - template: steps/nuget-push.yml@templates
    parameters:
      feed: '$(nuget.feed)'
      packages: '$(Build.ArtifactStagingDirectory)/$(project.Current)*.nupkg'