0

The settings

My goal is to understand the CI/CD process on Azure (and in general). For that, I have build a little Wpf-App. It is not doing much. Just displaying a simple ReadMe.txt file.
A test project is included and the tests are running fine.
Also, I am practicing app-configuration by replacing placeholders in appsettings.json by varibles in azure-pipelines.yml. This is running as supposed.

The goal to accomplish

Now I am working on publishing a self-contained exe-file that is excluding appsettings.json. That is where I do need some help. Is this task configured, properly?

- task: DotNetCoreCLI@2
  displayName: 'Publish'
  inputs:
    command: publish
    publishWebProjects: false
    arguments: '-c $(buildConfiguration) -r $(runtimeId) --self-contained true --output $(build.artifactstagingdirectory)'
    zipAfterPublish: false
  enabled: true

References

enter image description here

The code

The project file:

  • the project's SelfContained property is set to true
  • the appsettings.json file ExcludeFromSingleFile property is set to true
  • the appsettings.[Environment].json files are added to gitignore.
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup> <OutputType>WinExe</OutputType> <TargetFramework>net8.0-windows10.0.19041.0</TargetFramework> <Nullable>enable</Nullable> <ImplicitUsings>enable</ImplicitUsings> <UseWPF>true</UseWPF> <SelfContained>True</SelfContained> </PropertyGroup>

<ItemGroup> <PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" /> <PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" /> </ItemGroup>

<ItemGroup> <ProjectReference Include="..\DevOpsWpf.Library\DevOpsWpf.Library.csproj" /> </ItemGroup>

<ItemGroup> <None Update="appsettings.Development.json"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </None> <None Update="appsettings.json"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> <ExcludeFromSingleFile>True</ExcludeFromSingleFile> </None> <None Update="appsettings.Production.json"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </None> <None Update="appsettings.Staging.json"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </None> <None Update="Documentations\AzureDevOpsSolution.docx"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </None> <None Update="Documentations\ReadMe.txt"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </None> <None Update="Properties\launchSettings.json"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </None> </ItemGroup>

</Project>

The azure-pipeline file:

  • task VSBuild@1 is currently disabled
  • instead task DotNetCoreCLI@2 is enabled

I can not figure out which arguments in DotNetCoreCLI@2 to use to accomplish my goal.

trigger:
- main

pool: vmImage: 'windows-latest'

Check replacetokens-task and appsettings.json

the following variables are used in appsettings.json

applicationHomeDirectory

applicationName

variables: solution: '*/.sln' buildPlatform: 'Any CPU' runtimeId: 'win-x64' buildConfiguration: 'Release' applicationHomeDirectory: 'C:\DevOpsSolution' applicationName: 'Azur DevOps Solution (azure-pipelines.yml)'

not sure, if this is needed

steps:

  • task: DeleteFiles@1 displayName: 'Delete files in artifactstagingdirectory' inputs: SourceFolder: '$(build.artifactstagingdirectory)' Contents: '**'

working as intended

  • task: NuGetToolInstaller@1 displayName: 'Use NuGet 6.8.0'

working as intended

  • task: NuGetCommand@2 displayName: 'Restore NuGet Packages' inputs: restoreSolution: '$(solution)'

working as intended

  • task: qetza.replacetokens.replacetokens-task.replacetokens@5 displayName: 'Replace tokens in appsettings.json' inputs: targetFiles: '*/.json'

disabled task for testing

  • task: VSBuild@1 displayName: 'Build solution' inputs: solution: '$(solution)' platform: '$(buildPlatform)' configuration: '$(buildConfiguration)' enabled: false

testing this task instead of VSBuild; in artifact there are tons of files, instead of one exe-file and one json-file

  • task: DotNetCoreCLI@2 displayName: 'Publish' inputs: command: publish publishWebProjects: false arguments: '-c $(buildConfiguration) -r $(runtimeId) --self-contained true --output $(build.artifactstagingdirectory)' zipAfterPublish: false enabled: true

working as intended

  • task: VSTest@2 displayName: 'Test solution' inputs: platform: '$(buildPlatform)' configuration: '$(buildConfiguration)'

working to publish it to SolutionDrop; not sure if this is all that needs to be done here

  • task: PublishBuildArtifacts@1 displayName: 'Publish Artifact: SolutionDrop' inputs: PathtoPublish: '$(build.artifactstagingdirectory)' ArtifactName: SolutionDrop condition: succeededOrFailed()

The published artifact is >200 MB and has a ton of files. That can not be correct. Here you see just the top: enter image description here

Pierre.Vriens
  • 7,225
  • 14
  • 39
  • 84

1 Answers1

0

Finally, I have received the result as it was intended to be.

This answer was the final clue. And I did find the reference in Microsoft documentation.

enter image description here

These properties are set in the project file:

    <PublishSingleFile>true</PublishSingleFile>
    <IncludeAllContentForSelfExtract>true</IncludeAllContentForSelfExtract>

There was a change in the publish process by Microsoft. If PublishSingleFile is set to true, Self-Contained is implied automatically.
When the above properties are set in the project file, they do not need to be listed as arguments in the command line.

The DotNetCoreCLI@2 task looks like this:

steps:
- task: DotNetCoreCLI@2
  displayName: 'Publish *.csproj'
  inputs:
    command: publish
    publishWebProjects: false
    projects: '**/DevOpsWpf.csproj'
    arguments: '-c Release -r win-x64 --output $(build.artifactstagingdirectory)'
    zipAfterPublish: false

The project file looks like this:

<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup> <OutputType>WinExe</OutputType> <TargetFramework>net8.0-windows10.0.19041.0</TargetFramework> <Nullable>enable</Nullable> <ImplicitUsings>enable</ImplicitUsings> <UseWPF>true</UseWPF> <PublishSingleFile>true</PublishSingleFile> <IncludeAllContentForSelfExtract>true</IncludeAllContentForSelfExtract> </PropertyGroup>

<ItemGroup> <PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" /> <PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" /> </ItemGroup>

<ItemGroup> <ProjectReference Include="..\DevOpsWpf.Library\DevOpsWpf.Library.csproj" /> </ItemGroup>

<ItemGroup> <None Update="appsettings.Development.json"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </None> <None Update="appsettings.json"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> <ExcludeFromSingleFile>True</ExcludeFromSingleFile> </None> <None Update="appsettings.Production.json"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </None> <None Update="Documentations\ReadMe.txt"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </None> <None Update="Properties\launchSettings.json"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </None> </ItemGroup>

</Project>