azure-devopsconditional-statementsazure-pipelinesmulti-projectproject-reference

How do I add a conditional attribute in my project file to detect if the code is being built locally versus built in Azure DevOps?


We have decided that even though our data layer is in a separate Azure project, we want to include the .csproj file in our solution so that we are able to debug through API and Datalayers. We do not want to use nuget, because you lose that ability to debug and make changes on the fly.

In the Azure DevOps pipeline, I have set up the datalayer to publish the dll and pdb files to the pipeline artifacts. And I have the Artifacts being downloaded to the API pipeline, but when I build, I get this error. I have also excluded the 'MyDataLayer*.csproj' from the build task, so that it is only building the projects in the pipeline's repo.

Error CS0246: The type or namespace name 'MyDataLayer.Data' could not be found (are you missing a using directive or an assembly reference?)

It makes sense since I excluded it. But how do I change the in the project file, to point to the downloaded reference files?

I was thinking maybe a conditional attribute in the project file, but I haven't found what kind of conditional attribute would allow this.

I think I'd like something like this... I've added the psuedo code and of course changed the names of objects for security.

    <ItemGroup Condition="%where build is done through VS locally%">
        <ProjectReference Include="..\..\MyProject\MyDataLayer.Data\MyDataLayer.Data.csproj" />
        <ProjectReference Include="..\..\MyProject\MyDataLayer.Models\MyDataLayer.Model.csproj" />
    </ItemGroup>

    <ItemGroup Condition="%where build is done through Azure DevOps%">
        <ProjectReference Include="ArtifactPath\MyDataLayer.Data\MyDataLayer.Data.csproj" />
        <ProjectReference Include="ArtifactPath\MyDataLayer.Models\MyDataLayer.Model.csproj" />
    </ItemGroup>

Does anyone out there know how this can be done? Is there another way that I haven't found online to accomplish this?

I was expecting that the Azure DevOps build would pick up the references that were downloaded and use those as references, but that didn't happen.

Maybe I'm downloading them to the wrong path?

My Tasks:

- task: DownloadPipelineArtifact@2
  inputs:
    buildType: 'specific'
    project: 'xxxxxxxx-xxxx-xxxx-xxxxx-xxxxxxxxxxx'
    definition: '57'
    buildVersionToDownload: 'latest'
    itemPattern: '/**/?(*.dll|*.pdb)'
    targetPath: '$(Pipeline.Workspace)'

Solution

  • There is a much better way actually. I call it a "split configuration." You can modify your project file to point to a nuget package when you are building under one configuration, and a local DLL (from another projct) when you are building with a different build configuration. Inside the project file, encapsulate your dependencies under those build configs. Do something like the following in your project in the area where your existing reference is:

    <Choose>
        <When Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
            <ItemGroup>
                <PackageReference Include="YourNugetPackage">
                    <Version>1.0.0.0</Version>
                    <IncludeAssets>all</IncludeAssets>
                </PackageReference>
            </ItemGroup>
        </When>
        <When Condition=" '$(Configuration)|$(Platform)' != 'Release|AnyCPU' ">
            <ItemGroup>
                <Reference Include="YourProjectDll">
                    <HintPath>..\..\PathToProject\Bin\YourProject.dll</HintPath>
                </Reference>
            </ItemGroup>
        </When>
    </Choose>
    

    That should do the trick. Make sure your pipeline builds against release and you build locally against any other configuration.