Building and Packaging .NET Core with AppVeyor

1 -> Experimenting with the Kudu API

2 -> Building and Packaging .NET Core with AppVeyor

3 -> Parsing command line arguments in .NET Core

I’ve been working on a project called k-scratch which allows remote logging and file sync with Kudu based sites – mainly for making local editing of Azure Functions easier.

As part of that I broke out the log stream component (called KScratchLog) in to a standalone console app. I plan to make this in to a broader console app that can get, push, log stream etc all from the command prompt… but before any of that can happen I figured I should get some CI going.

I decided on AppVeyor because it has .NET Core support, is free and works well with GitHub (like super well).

AppVeyor allows you to run PowerShell and CMD scripts, and the environments that builds are run in will be familiar to most .NET developers.

Most of the heavy lifting and config is done by placing an AppVeyor.yml script in the root of your GitHub Repo.

I had a hunt around, and saw that some projects use custom build scripts with AppVeyor in conjunction with the yml file, but I wanted to try and do it all in the yml.

Searching I found an example yml file by Steven Liekens that I used as a starting point.

Setting up the project.json files

I created my project in Visual Studio. It has a console app and a series of portable projects that are .NET Standard 1.3 based.

The first thing I had to do before I could get it to build on the command line using dotnet build was reference the dependency projects in the project.json file. Visual Studio did not do this automatically as it relies on the references in the .xproj files.

"dependencies": {
"Autofac": "4.1.0",
"Microsoft.NETCore.Portable.Compatibility": "1.0.1",
"NETStandard.Library": "1.6.0",
"System.IO": "4.1.0",
"System.Xml.XmlSerializer": "4.0.11",
"KScratch.Entity": {
"target": "project"
},
"KScratch.Contract": {
"target": "project"
}

The next step was making sure the build outputted .exe files, which it doesn’t by default. This is done in project.json.

Scott Hanselman’s post on self contained apps in .NET Core was a handy reference for this.

"runtimes": {
"win7-x64": {},
"osx.10.10-x64": {},
"ubuntu.14.04-x64": {}
}

Also make sure you reference the portable projects here too:

"frameworks": {
"netcoreapp1.0": {
"imports": "dnxcore50",
"dependencies": {
"Microsoft.NETCore.App": {
"version": "1.0.1"
},
"KScratch.Contract": {
"target": "project"
},
"KScratch.Entity": {
"target": "project"
},
"KScratch.Portable": {
"target": "project"
}
}
}

The final part of the story was getting the build to work. I played around on the command line on my local machine first to get it going before transporting the commands in to the build_script section of the AppVeyor.yml file.

I also added the ability to build separate platforms in the script, for now only windows is present.

Worth noting is that the AppVeyor platform would not support win10-x64 so I had to change it to win7-x64.

Once the build is completed and dotnet publish is called I package up the file using 7z, before referencing that zip as an artefact.

You can see a sample build output here and the resulting artefact here.

Finally – I went to the AppVeyor settings and got the MD for the all important AppVeyor build status badge and inserted it in my readme.md file!

Build status

Full AppVeyor.yml listing from here

version: '1.0.{build}'
configuration:
- Release
platform:
- win7-x64
environment:
  # Don't report back to the mothership
  DOTNET_CLI_TELEMETRY_OPTOUT: 1
init:
- ps: $Env:LABEL = "CI" + $Env:APPVEYOR_BUILD_NUMBER.PadLeft(5, "0")
before_build:
- appveyor-retry dotnet restore -v Minimal
build_script:
- dotnet build "src\KScratch.Entity" -c %CONFIGURATION% -r %PLATFORM%  --no-dependencies --version-suffix %LABEL%
- dotnet build "src\KScratch.Contract" -c %CONFIGURATION% -r %PLATFORM% --no-dependencies --version-suffix %LABEL%
- dotnet build "src\KScratch.Portable" -c %CONFIGURATION%  -r %PLATFORM% --no-dependencies --version-suffix %LABEL%
- dotnet build "src\KScratchLog" -c %CONFIGURATION% -r %PLATFORM% --no-dependencies --version-suffix %LABEL%
after_build:
- dotnet publish "src\KScratchLog" -c %CONFIGURATION% -r %PLATFORM% --no-build --version-suffix %LABEL% -o artifacts\%PLATFORM%
- 7z a zip\KScratchLog_%PLATFORM%.zip %APPVEYOR_BUILD_FOLDER%\artifacts\%PLATFORM%\*.*
#test_script:
#- dotnet test "src\KScratch.Tests" -c %CONFIGURATION%
artifacts:
- path: zip\**\*.*
cache:
- '%USERPROFILE%\.nuget\packages'
on_finish: # Run the demo to show that it works