Posted on August 01, 2017
There are two options to have branch-specific configuration with appveyor.yml
:
appveyor.yml
into each branch with branch-specific settings.appveyor.yml
has a list of configurations for different branches.The problem with 1st approach is merging as you are overriding appveyor.yml
in the base branch with one from the branch being merged.
2nd approach requires appveyor.yml
of the following format:
# configuration for "master" branch
# build in Release mode and deploy to Azure
-
branches:
only:
- master
configuration: Release
deploy:
provider: AzureCS
...
# configuration for all branches starting from "dev-"
# build in Debug mode and deploy locally for testing
-
branches:
only:
- /dev-.*/
configuration: Debug
deploy:
provider: Local
...
# "fall back" configuration for all other branches
# no "branches" section defined
# do not deploy at all
-
configuration: Debug
While this approach works great in the most cases there is one incovenience though - with large configuration and many branches appveyor.yml
becomes really unmanageable and error-prone as you have to repeat (copy-paste) entire configuration for every branch.
We just deployed an update to AppVeyor that allows sharing common configuration between branches in a single appveyor.yml
!
There is new for
node with a list of branch-specific configurations overriding common configuration defined on the top most level, for example:
# common configuration for ALL branches
environment:
MY_VAR1: value-A
init:
- do_something_on_init.cmd
install:
- do_something_on_install.cmd
configuration: Debug
# here we are going to override common configuration
for:
# override settings for `master` branch
-
branches:
only:
- master
configuration: Release
deploy:
provider: FTP
...
# override settings for `dev-*` branches
-
branches:
only:
- /dev-.*/
environment:
MY_VAR2: value-B
deploy:
provider: Local
...
In the example above we define environment
, init
and install
sections for all branches as well as stating that default configuration
is Debug
. Then, for master
branch we override default settings by changing configuration
to Release
and adding deployment with FTP
provider. For dev-*
branches we define a second environment variable MY_VAR2
and enable deployment to Local
environment.
Configuration merging rules:
image
, version
, configuration
, platform
, etc. defined on branch level override default ones;init
, install
, before_build
, test_script
, etc. defined on branch level override default ones;environment
sections are merged (new) and overridden (existing);deploy
, artifacts
, notifications
section can be either overridden or extended.For example, consider the following configuration:
artifacts:
- path: bin
deploy:
- provider: Local
...
notifications:
- provider: Email
...
for:
branches:
only:
- master
artifacts:
- path: docs
deploy: off
notifications:
provider: Slack
...
In the example above we do the following:
master
branch we adding docs
folder to artifacts definition, so both bin
and docs
folders collected. Both default and branch-specific collections were merged.master
branch we disable any deployment. off
or none
on branch-level clears default collection.master
branch we replace all notifications on default level with a single Slack
notification.Best regards,
AppVeyor team
Follow us on Twitter: @appveyor
Posted on March 17, 2017
This is a guest post by Cedd Burge, Software Developer Lead at RES.
CodeCov visualises code coverage and can enforce standards via GitHub and AppVeyor. More information is available on CodeCov.io.
This post is written from the point of view of someone (me) who is already proficient in C# and unit testing, but was new to AppVeyor and integrating CodeCov with GitHub.
It contains from scratch steps to run CodeCov test coverage on a sample C# project using GitHub, AppVeyor, OpenCover and XUnit. You can look at the repo I created to test this post if you get stuck.
If you are new to GitHub, see this getting started guide, otherwise simply create a new repo (YourRepositoryName from now on) and git clone it somewhere convenient.
In my version of Visual Studio (Community 2015), you can do this by clicking on “File - New - Project” on the main menu, then “Class Library” from “Templates - Visual C#”. Give it a interesting name, which I will assume to be YourSUTProjectName for the rest of this post.
Repeat this for the test project, which I will assume to be YourTestProjectName.
Add the xunit
, xunit.runner.visualstudio
and xunit.runner.console
nuget packages to your test project.
Add an XUnit test to YourTestProjectName and the corresponding thing under test to YourSUTProjectName, or copy and paste mine.
Run this test to make sure it passes.
You will need to link an AppVeyor account to your GitHub one, so let’s do that:
Now Log in to AppVeyor.com, probably using your GitHub account
When working with AppVeyor, it always makes sense to test on your own computer first. The feedback is immediate and you iterate very quickly. It takes a lot longer to modify the appveyor.yml file, push it and wait for a build to go through. Also, if it works locally but doesn’t work on AppVeyor, you know the problem is a configuration difference between your computer and the AppVeyor environment (eg a different version of msbuild).
However, this step is not required, so skip to “Run Coverage Analysis on AppVeyor” if you wish.
CodeCov.io is a tool for visualising and integrating coverage data, which we need to create. We will use OpenCover to do this.
Add the OpenCover
nuget package to the solution (which will install OpenCover.Console.exe, probably in packages\OpenCover.4.6.519\tools) and then run the following in a command window.
packages\OpenCover.4.6.519\tools\OpenCover.Console.exe -register:user -target:"packages\xunit.runner.console.2.2.0\tools\xunit.console.x86.exe" -targetargs:"YourTestDLL -noshadow" -output:".\coverage.xml" -filter:"+[YourSUTNamepace*]* -[YourTestNamespace*]*"
Download and install Python 3.x, make sure to tick the box to add Python to your path (or do so manually).
Run the following on the command line. You may need to close and reopen the console to pick up changes to the path. YourUploadToken is the CodeCov token that you took a note of earlier, or available on the project settings page on CodeCov (eg https://codecov.io/gh/YourGitHubUserName/YourRepositoryName/settings
)
pip install codecov
codecov -f "coverage.xml" -t YourUploadToken
The output will show a url with the results (eg https://codecov.io/gh/YourGitHubUserName/YourRepositoryName
)
Now that the coverage upload is working locally, we can run it on AppVeyor.
Add and commit an appveyor.yml
file to the root of the repository as below.
before_build:
- nuget restore
build_script:
- msbuild /verbosity:quiet "YourSolution"
test_script:
- .\packages\OpenCover.4.6.519\tools\OpenCover.Console.exe -register:user -target:"%xunit20%\xunit.console.x86.exe" -targetargs:"YourTestDll -noshadow" -output:"coverage.xml" -filter:"+[YourSUTNamepace*]* -[YourTestNamespace*]*"
after_test:
- "SET PATH=C:\\Python34;C:\\Python34\\Scripts;%PATH%"
- pip install codecov
- codecov -f "coverage.xml" -t YourUploadToken
There are various badges and graphs available. Click on your project in CodeCov, then “Settings” and “Badge” (eg https://codecov.io/gh/YourGitHubUserName/YourRepositoryName/settings/badge
) to see what’s available.
Copy and paste a code snippet from this in to your README.md, such as this one .
You can look at my readme for example badges
CodeCov automatically integrates with GitHub pull requests (as long as you signed up to CodeCov via your GitHub account) which you can see on this pull request.
It will show some statistics, such as the increase or decrease in coverage, and by default will fail the build if coverage decreases. You can configure this with a ‘codecov.yml’ file in the root of your repository.
There is a CodeCov browser plugin, for all reputable browsers, that adds coverage when browsing GitHub.com. Code is highlighted in red / green, and a coverage percentage is shown.
It can be difficult keeping control of test coverage for a project, especially with distributed and transient team structures. The combination of GitHub, AppVeyor OpenCover and CodeCov make it very easy to visualise the coverage, and allow you to enforce standards to ensure that it improves over time.
Best regards,
Cedd Burge
Follow Cedd on Twitter: @cuddlyburger
Follow AppVeyor on Twitter: @appveyor
Posted on December 23, 2016
This is a guest post by Cedd Burge, Software Developer Lead at RES.
SonarQube / SonarSource analyzes code, highlights quality issues and calculates metrics such as technical debt. More information is available on SonarSource.com.
This post is written from the point of view of someone (me) who is already proficient in C#, and had even used SonarQube, but was new to AppVeyor and integrating SonarQube with GitHub.
It contains from scratch steps to run the SonarQube analysis on a sample project and to publish the results to the publicly available Nemo instance of SonarQube. You can look at the repo I created to test this post if you get stuck.
If you are new to GitHub, see this getting started guide, otherwise simply create a new repo and git clone it somewhere convenient.
In my version of Visual Studio (Community 2015), you can do this by clicking on “File - New - Project” on the main menu, then “Class Library” from “Templates - Visual C#”. Give it a interesting name, which I will assume to be YourProjectName for the rest of this post.
Add some code that has some quality issues (e.g. a variable that is declared but never used). You can use the the full list of SonarQube C# issues for inspiration. Alternatively you can copy and paste some of mine.
Install the SonarLint Visual Studio Plugin. This highlights quality issues in your code as you type and gives you a chance to fix them before committing.
You will need to link an AppVeyor account to your GitHub one, so let’s do that:
Now Log in to AppVeyor.com, probably using your GitHub account
When working with AppVeyor, it always makes sense to test on your own computer first. The feedback is immediate and you iterate very quickly. It takes a lot longer to modify the appveyor.yml
file, push it and wait for a build to go through. Also, if it works locally but doesn’t work on AppVeyor, you know the problem is a configuration difference between your computer and the AppVeyor environment (e.g. a different version of msbuild).
Instead of committing SonarQube executables to the repo, we will download them during the build using Chocolatey.
choco install "msbuild-sonarqube-runner" -y
MSBuild.SonarQube.Runner.exe begin /k:"**YourUniqueProjectName**" /d:"sonar.host.url=https://sonarqube.com" /d:"sonar.login=**YourSonarQubeToken**"
"**YourPathToMSBuild**\MSBuild.exe" "**YourProjectName**.sln"
MSBuild.SonarQube.Runner.exe end /d:"sonar.login=**YourSonarQubeToken**"
When finished, you will be able to see the results at sonarqube.com/. If it isn’t working, make sure you are using MSBuild 14 and Java 1.8 or later. The SonarQube Getting Started page is excellent if these instructions become out of date.
Now that this is working locally, we can run it on AppVeyor.
Add and commit an appveyor.yml file to the root of the repository as follows
before_build:
- nuget restore
build_script:
- choco install "msbuild-sonarqube-runner" -y
- MSBuild.SonarQube.Runner.exe begin /k:"YourUniqueProjectName" /d:"sonar.host.url=https://sonarqube.com" /d:"sonar.login=YourSonarQubeToken"
- msbuild "YourProjectName.sln"
- MSBuild.SonarQube.Runner.exe end /d:"sonar.login=YourSonarQubeToken"
Again, you can check the results at sonarqube.com.
There are are variety of Quality Gate and Metrics badges available.
To add a standard badge, add the following to readme.md.
[![Quality Gate](https://sonarqube.com/api/badges/gate?key=YourUniqueProjectName)](https://sonarqube.com/dashboard/index/YourUniqueProjectName)
SonarQube can analyze Pull Requests for quality issues, which you can see on this pull request.
This requires a GitHub authentication token, which must be secured, secure variables to be enabled in pull requests and a differential build for Pull Requests.
Go to your profile and click “Edit Profile”. Click on “Personal access tokens” in the “Developer settings” section. Give the token any name and tick on the “public_repo” scope. Make a note of the created token (GitHubAuthToken from now on)
Anyone with access to this token can alter your data, contact information and billing data, so we don’t want that.
On AppVeyor, click your user name in the top right hand corner and then click “Encrypt data” from the drop down menu. Enter GitHubAuthToken in to “Value to encrypt” and click “Encrypt”. AppVeyor will then display a token which you can use in place of the real value (EncryptedGitHubAuthToken from now on).
Normally AppVeyor will not decrypt secure variables in Pull Requests, as in this case a Hacker could send you a PR and then read all of your secure data. However, for SonarQube to analyze Pull Requests, it is necessary. You need to decide whether you can live with this.
If you can, go to AppVeyor, click on your project, click “Settings”, tick “Enable secure variables in Pull Requests from the same repository only” and click “Save”.
Modify AppVeyor.yml to ask SonarQube to publish results on standard builds, and to integrate with pull request builds. To achieve this, extra parameters are given to the SonarQube runner when if ($env:APPVEYOR_PULL_REQUEST_NUMBER)
detects a Pull Request build.
environment:
github_auth_token:
secure: EncryptedGitHubAuthToken
before_build:
- nuget restore
build_script:
- choco install "msbuild-sonarqube-runner" -y
- ps: if ($env:APPVEYOR_PULL_REQUEST_NUMBER) { MSBuild.SonarQube.Runner.exe begin /k:"YourUniqueProjectName" /d:"sonar.host.url=https://sonarqube.com" /d:"sonar.login=YourSonarQubeToken" /d:"sonar.analysis.mode=preview" /d:"sonar.github.pullRequest=$env:APPVEYOR_PULL_REQUEST_NUMBER" /d:"sonar.github.repository=YourRepositoryUrl" /d:"sonar.github.oauth=$env:EncryptedGitHubAuthToken" }
- ps: if (-Not $env:APPVEYOR_PULL_REQUEST_NUMBER) { MSBuild.SonarQube.Runner.exe begin /k:"YourUniqueProjectName" /d:"sonar.host.url=https://sonarqube.com" /d:"sonar.login=YourSonarQubeToken" }
- msbuild "YourProjectName.sln"
- MSBuild.SonarQube.Runner.exe end /d:"sonar.login=YourSonarQubeToken"
SonarQube is maturing fast and is becoming industry standard, and happily it is easy to integrate Open Source projects with the publicly available SonarQube server and AppVeyor. The SonarLint Visual Studio Plugin is fantastic at spotting problems before you commit them, and the GitHub integration allows you to control the quality of contributions.
Best regards,
Cedd Burge
Follow Cedd on Twitter: @cuddlyburger
Follow AppVeyor on Twitter: @appveyor
Posted on November 22, 2016
This is a guest post by Cedd Burge, Software Developer Lead at RES.
This post is written from the point of view of someone (me) who is already proficient in C#, but was new to Xamarin, Mobile phone development, and AppVeyor.
It contains from scratch steps to create a Xamarin Android application (in Visual Studio), to build it on AppVeyor and to publish it to the Play Store. You can look at the repo I created to test this post if you get stuck.
First, install Xamarin from https://www.xamarin.com/download.
If you are new to GitHub, see this getting started guide, otherwise simply create a new repo and git clone it somewhere convenient.
In my version of Visual Studio (Community 2015), this is done by clicking “File - New - Project” on the main menu and then selecting “Blank App (Xamarin.Forms Portable)” from “Templates - Visual C# - Cross-Platform”. Give it a interesting name, which I will assume to be YourAppName for the rest of this post.
Select the YourAppName.Droid project and run it. This should show the bare bones app in an emulator.
If you have Hyper-V enabled (maybe you use Docker), then you might get an Deployment Error when doing this. Disable Hyper-V and restart your machine to fix this.
You might also run in to compile errors due to ridiculous dependency weirdness.
To tell Google about your app, you have to make some changes to the Properties\AndroidManifest.xml file of the YourAppName.Droid project.
package="com.yourappname"
(or similar) attribute to the root manifest
node. The package name must be unique on Google Play and must follow normal java package name conventions. Most people use their url in reverse (eg com.yourappname instead of yourappname.com) and stick to lower case.android:versionCode="1"
attribute to the root manifest
node. This is an integer and it must be incremented every time you upload an apk on Google Play.android:versionName="0.1
attribute to the root manifest
node. This value can be anything you like and is displayed in Google Play.label
attribute on the application
node to YourAppName.Visual studio has some tools to create an APK, and they seem to be in constant churn, but at the time of writing, the process is as follows.
There are some requirements when publishing an application to Google Play, and these are likely to change, but happily google tells you what they all are. If you click on “Why can’t I publish?”, near the top right corner of the page, you will get a list of things to do.
It’s all simple stuff that can be done within the Developer Console. Some screenshots and pictures are required. If you just want to get a test version up quickly, then feel free to use mine temporarily.
There are a lot of optional things you can do as well, which can be worthwhile if you want to publish a killer app. The Google Launch Checklist, is comprehensive, but takes a long time to read.
When working with appveyor, it always makes sense to test on your own computer first. The feedback is immediate and you iterate very quickly. It takes a lot longer to modify the appveyor.yml file, push it and wait for a build to go through. Also, if it works locally but doesn’t work on AppVeyor, you know the problem is a configuration difference between your computer and the AppVeyor environment (eg a different version of msbuild).
Being as we are making a new version of the apk, we need to increment android:versionCode
in Properties/AndroidManifest.xml.
There are some Xamarin MSBuild targets, which we can use to create a Signed and ZipAligned apk as below.
There are 2 passwords required in the command because java KeyStores can contain multiple Alias’. So the first password is to access the KeyStore, and the second one is to access the specific alias. Visual studio hides this complexity from you and assigns the same password to both places.
I do a lot of work in GIT Bash, but this statement only works in Batch (the windows command line), I think because of parameter escaping.
MSBuild "/t:SignAndroidPackage" "/p:Configuration=Release" "/p:AndroidKeyStore=true" "/p:AndroidSigningKeyAlias=YourKeyAlias" "/p:AndroidSigningKeyPass=YourKeyStorePassword" "/p:AndroidSigningKeyStore=YourKeyStoreFilename" "/p:AndroidSigningStorePass=YourKeyStorePassword" "YourAppName.csproj"
This will create com.yourappname-Signed.apk in the bin\release folder. Upload this to Google Play to make sure that everything is working properly.
You will need to link an AppVeyor account to your GitHub one, so let’s do that:
Now Log in to AppVeyor.com, probably using your GitHub account
MSBuild needs to access your KeyStore file in order to sign the apk, so copy YourKeyStoreFilename in to the folder of YourAppName.Droid project (called YourKeyStoreLocalFilename from now on).
When we created the apk from the command line, we entered in some passwords, and we obviously can’t save these passwords to a public Git repository. Happily AppVeyor have thought of this, and you can convert passwords in to tokens that can be exposed publically.
To do this, click your user name in the top right hand corner and then click “Encrypt data” from the drop down menu. Enter YourKeyStorePassword in to “Value to encrypt” and click “Encrypt”. AppVeyor will then display a token which you can use in place of the real value.
Now that we have everything we need, add an appveyor.yml file to the root of your repository as below. Note that YourLocalKeyStoreFilename is relative to the csproj file being built (the YourAppName.Droid folder below).
environment:
keystore-password:
secure: DSwAr4fYt3Q35Sjob5qAN5uj # YourPassword for keystore
before_build:
- nuget restore
build_script:
- msbuild "/t:SignAndroidPackage" "/p:Configuration=Release" "/p:AndroidKeyStore=true" "/p:AndroidSigningKeyAlias=YourKeyAlias" "/p:AndroidSigningKeyPass=%keystore-password%" "/p:AndroidSigningKeyStore=YourLocalKeyStoreFilename" "/p:AndroidSigningStorePass=%keystore-password%" "YourAppName.Droid\YourAppName.csproj"
artifacts:
- path: YourAppName.Droid\bin\Release\com.yourappname-Signed.apk
Remember to update android:versionCode
and then push to GitHub. This will trigger a build on AppVeyor. The build_script
section will call msbuild to create the signed and zipaligned apk file, and the artifacts
section will archive the apk file so we can download it later.
Go to AppVeyor.com, click on your project, click on “Artifacts”, download the apk file, and then upload it to google to check that everything has worked properly.
There is a lot to learn to get everything working, and I couldn’t find a single source for all of these things, but having done it once, the process is actually quite simple, and the tools and services involved are generally a pleasure to work with.
Best regards,
Cedd Burge
Follow Cedd on Twitter: @cuddlyburger
Follow AppVeyor on Twitter: @appveyor
Posted on November 07, 2016
Appveyor does not support AWS Elastic Beanstalk deployment out of the box right now. However it can be automated in Appveyor with help of some scripting. Here is small guide based on this support forum discussion.
awsdeploy.txt
.Add the following to awsdeploy.txt
:
Template = ElasticBeanstalk
Container.ApplicationHealthcheckPath = /healthcheck
AWSAccessKeyId
as environment variable and AWSSecretKey
as secure environment variable.Set the following as a deployment script:
$packageweb = $artifacts.values | Where-Object { $_.path -like '*WebApplication1.zip' }
$exe = "C:\Program Files (x86)\AWS Tools\Deployment Tool\awsdeploy.exe"
&$exe -r "-DDeploymentPackage=$($packageweb.path)" "-DEnvironment.Name=MyAppWeb-test123" "-DApplication.Name=MyAppWeb123" "-DRegion=eu-west-1" "-DAWSAccessKey=$env:AWSAccessKeyId" "-DAWSSecretKey=$env:AWSSecretKey" "C:\projects\WebApplication1\awsdeploy.txt"
Note that this script assumes that application was already deployed at least once to Beanstalk, otherwise you need to replace -r switch with -w for single first deployment.
Here is an example YAML (only relevant parts):
environment:
AWSAccessKeyId: AKIAIODIUCY3ETD6TEST
AWSSecretKey:
secure: LEvzbXpiLkWVvswonFHnAYV9ZS6fEFL3wswjTcIQ6ZXC5j1nynd6N0Bs/VFtest
build:
publish_wap_xcopy: true
deploy_script:
- ps: |
$packageweb = $artifacts.values | Where-Object { $_.path -like '*WebApplication1.zip' }
$exe = "C:\Program Files (x86)\AWS Tools\Deployment Tool\awsdeploy.exe"
&$exe -r "-DDeploymentPackage=$($packageweb.path)" "-DEnvironment.Name=MyAppWeb-test123" "-DApplication.Name=MyAppWeb123" "-DRegion=eu-west-1" "-DAWSAccessKey=$env:AWSAccessKeyId" "-DAWSSecretKey=$env:AWSSecretKey" "C:\projects\WebApplication1\awsdeploy.txt"
Here is an example web application folder structure:
Directory of C:\Projects\WebApplication1
09/15/2016 02:48 AM <DIR> .
09/15/2016 02:48 AM <DIR> ..
07/17/2016 12:34 PM 505 .gitattributes
07/17/2016 12:34 PM 2,858 .gitignore
09/15/2016 02:40 AM 80 awsdeploy.txt
08/30/2016 03:22 PM <DIR> WebApplication1
07/21/2016 06:51 PM 1,012 WebApplication1.sln
Enjoy!