Skip to content

Commit

Permalink
Start with GitHub Actions (#34)
Browse files Browse the repository at this point in the history
  • Loading branch information
AArnott committed Jan 14, 2020
1 parent 56ab8cb commit 366d5df
Show file tree
Hide file tree
Showing 11 changed files with 222 additions and 99 deletions.
99 changes: 99 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
name: CI

on:
push:
branches:
- master
- microbuild
- validate/*
pull_request:

env:
TreatWarningsAsErrors: true
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
BUILDCONFIGURATION: Release
codecov_token: 4dc9e7e2-6b01-4932-a180-847b52b43d35 # Get a new one from https://codecov.io/
ci_feed: /a5a3bad0-e566-4c53-be83-6458be8d1653 # find guid used by Azure DevOps Artifacts for the feed. Learn more at https://github.com/AArnott/Library.Template/issues/28
# NUGET_PACKAGES: ${{ env.GITHUB_WORKSPACE }}/.nuget/packages

jobs:
build:

runs-on: ${{ matrix.os }}
strategy:
matrix:
os:
- ubuntu-18.04
- macos-latest
- windows-latest

steps:
- uses: actions/checkout@v2
- name: Deep clone
run: git fetch --prune --unshallow origin HEAD
- name: Install prerequisites
run: |
./init.ps1 -UpgradePrerequisites
dotnet --info
shell: pwsh
- name: Set pipeline variables based on source
run: azure-pipelines/variables/_pipelines.ps1
shell: pwsh
- name: build
run: dotnet build src --no-restore -c ${{ env.BUILDCONFIGURATION }} /v:m /bl:"bin/build_logs/build.binlog"
- name: pack
run: dotnet pack src --no-build -c ${{ env.BUILDCONFIGURATION }} /v:m /bl:"bin/build_logs/pack.binlog"
- name: test
run: dotnet test src --no-build -c ${{ env.BUILDCONFIGURATION }} /bl:"bin/build_logs/test.binlog" --filter "TestCategory!=FailsInCloudTest" -v n /p:CollectCoverage=true
- name: Update pipeline variables based on build outputs
run: azure-pipelines/variables/_pipelines.ps1
shell: pwsh
- name: Collect artifacts
run: azure-pipelines/artifacts/_stage_all.ps1
shell: pwsh
- name: Upload project.assets.json files
if: always()
uses: actions/upload-artifact@v1
with:
name: projectAssetsJson-${{ runner.os }}
path: obj/_artifacts/projectAssetsJson
continue-on-error: true
- name: Upload variables
uses: actions/upload-artifact@v1
with:
name: variables
path: obj/_artifacts/variables
if: runner.os == 'Windows'
continue-on-error: true
- name: Upload build_logs
if: always()
uses: actions/upload-artifact@v1
with:
name: build_logs-${{ runner.os }}
path: obj/_artifacts/build_logs
continue-on-error: true
- name: Upload coverageResults
if: always()
uses: actions/upload-artifact@v1
with:
name: coverageResults-${{ runner.os }}
path: obj/_artifacts/coverageResults
continue-on-error: true
- name: Upload symbols
uses: actions/upload-artifact@v1
with:
name: symbols
path: obj/_artifacts/symbols
if: runner.os == 'Windows'
continue-on-error: true
- name: Upload deployables
uses: actions/upload-artifact@v1
with:
name: deployables
path: obj/_artifacts/deployables
if: runner.os == 'Windows'
- name: Publish code coverage results to codecov.io
run: bash <(curl -s https://codecov.io/bash)
shell: bash
timeout-minutes: 3
continue-on-error: true
3 changes: 2 additions & 1 deletion Expand-Template.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,8 @@ try {
}
Replace-Placeholders -Path "README.md" -Replacements @{
"(?m)^.*\[NuGet package\][^`r`n]*"="[![NuGet package](https://img.shields.io/nuget/v/$LibraryName.svg)](https://nuget.org/packages/$LibraryName)"
"(?m)^.*\[Build Status\].*`r?`n"=""
"(?m)^.*\[Azure Pipelines status\].*`r?`n"=""
"(?m)^.*\[GitHub Actions status\].*`r?`n"=""
"(?m)^.*\[codecov\].*`r?`n"=""
}

Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
***An awesome template for your awesome library***

![NuGet package](https://img.shields.io/badge/nuget-your--package--here-yellow.svg)
[![Build Status](https://dev.azure.com/andrewarnott/OSS/_apis/build/status/AArnott.Library.Template?branchName=master)](https://dev.azure.com/andrewarnott/OSS/_build/latest?definitionId=29&branchName=master)

[![Azure Pipelines status](https://dev.azure.com/andrewarnott/OSS/_apis/build/status/AArnott.Library.Template?branchName=master)](https://dev.azure.com/andrewarnott/OSS/_build/latest?definitionId=29&branchName=master)
![GitHub Actions status](https://github.com/aarnott/Library.Template/workflows/CI/badge.svg)
[![codecov](https://codecov.io/gh/aarnott/library.template/branch/master/graph/badge.svg)](https://codecov.io/gh/aarnott/library.template)

## Features
Expand Down
1 change: 0 additions & 1 deletion azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ variables:
TreatWarningsAsErrors: true
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
BuildConfiguration: Release
BuildPlatform: Any CPU
codecov_token: 4dc9e7e2-6b01-4932-a180-847b52b43d35 # Get a new one from https://codecov.io/
ci_feed: /a5a3bad0-e566-4c53-be83-6458be8d1653 # find guid used by Azure DevOps Artifacts for the feed. Learn more at https://github.com/AArnott/Library.Template/issues/28
NUGET_PACKAGES: $(Agent.TempDirectory)/.nuget/packages
Expand Down
46 changes: 43 additions & 3 deletions azure-pipelines/Set-EnvVars.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,70 @@
[CmdletBinding(SupportsShouldProcess=$true)]
Param(
[Parameter(Mandatory=$true, Position=1)]
$Variables
$Variables,
[string[]]$PrependPath
)

if ($Variables.Count -eq 0) {
return $true
}

$cmdInstructions = !$env:TF_BUILD -and $env:PS1UnderCmd -eq '1'
$cmdInstructions = !$env:TF_BUILD -and !$env:GITHUB_ACTIONS -and $env:PS1UnderCmd -eq '1'
if ($cmdInstructions) {
Write-Warning "Environment variables have been set that will be lost because you're running under cmd.exe"
Write-Host "Environment variables that must be set manually:" -ForegroundColor Blue
} else {
Write-Host "Environment variables set:" -ForegroundColor Blue
$envVars
if ($PrependPath) {
Write-Host "Paths prepended to PATH: $PrependPath"
}
}

if ($env:TF_BUILD) {
Write-Host "Azure Pipelines detected. Logging commands will be used to propagate environment variables and prepend path."
}

if ($env:GITHUB_ACTIONS) {
Write-Host "GitHub Actions detected. Logging commands will be used to propagate environment variables and prepend path."
}

$Variables.GetEnumerator() |% {
Set-Item -Path env:$($_.Key) -Value $_.Value

# If we're running in Azure Pipelines, set these environment variables
# If we're running in a cloud CI, set these environment variables so they propagate.
if ($env:TF_BUILD) {
Write-Host "##vso[task.setvariable variable=$($_.Key);]$($_.Value)"
}
if ($env:GITHUB_ACTIONS) {
Write-Host "::set-env name=$($_.Key)::$($_.Value)"
}

if ($cmdInstructions) {
Write-Host "SET $($_.Key)=$($_.Value)"
}
}

$pathDelimiter = ';'
if ($IsMacOS -or $IsLinux) {
$pathDelimiter = ':'
}

if ($PrependPath) {
$PrependPath |% {
$newPathValue = "$_$pathDelimiter$env:PATH"
Set-Item -Path env:PATH -Value $newPathValue
if ($cmdInstructions) {
Write-Host "SET PATH=$newPathValue"
}

if ($env:TF_BUILD) {
Write-Host "##vso[task.prependpath]$_"
}
if ($env:GITHUB_ACTIONS) {
Write-Host "::add-path::$_"
}
}
}

return !$cmdInstructions
10 changes: 5 additions & 5 deletions azure-pipelines/artifacts/Variables.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
# It "snaps" the values of these variables where we can compute them during the build,
# and otherwise captures the scripts to run later during an Azure Pipelines environment release.

$RepoRoot = [System.IO.Path]::GetFullPath("$PSScriptRoot\..\..")
$ArtifactBasePath = "$RepoRoot\obj\_artifacts"
$VariablesArtifactPath = "$ArtifactBasePath\variables"
$RepoRoot = [System.IO.Path]::GetFullPath((Join-Path $PSScriptRoot (Join-Path .. ..)))
$ArtifactBasePath = Join-Path $RepoRoot (Join-Path obj _artifacts)
$VariablesArtifactPath = Join-Path $ArtifactBasePath variables
if (-not (Test-Path $VariablesArtifactPath)) { New-Item -ItemType Directory -Path $VariablesArtifactPath | Out-Null }

# Copy variables, either by value if the value is calculable now, or by script
Get-ChildItem -Path "$PSScriptRoot\..\variables" |% {
Get-ChildItem -Path (Join-Path $PSScriptRoot (Join-Path .. variables)) |% {
$value = $null
if (-not $_.BaseName.StartsWith('_')) { # Skip trying to interpret special scripts
# First check the environment variables in case the variable was set in a queued build
Expand All @@ -32,7 +32,7 @@ Get-ChildItem -Path "$PSScriptRoot\..\variables" |% {
$value = Get-Content -Path $_.FullName
}

Set-Content -Path "$VariablesArtifactPath\$($_.Name)" -Value $value
Set-Content -Path (Join-Path $VariablesArtifactPath $_.Name) -Value $value
}

@{
Expand Down
49 changes: 2 additions & 47 deletions azure-pipelines/artifacts/_pipelines.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -5,51 +5,6 @@ param (
[string]$ArtifactNameSuffix
)

$RepoRoot = [System.IO.Path]::GetFullPath("$PSScriptRoot\..\..")
if ($env:BUILD_ARTIFACTSTAGINGDIRECTORY) {
$ArtifactStagingFolder = $env:BUILD_ARTIFACTSTAGINGDIRECTORY
} else {
$ArtifactStagingFolder = "$RepoRoot\obj\_artifacts"
if (Test-Path $ArtifactStagingFolder) {
Remove-Item $ArtifactStagingFolder -Recurse -Force
}
}

function Create-SymbolicLink {
param (
$Link,
$Target
)

if ($Link -eq $Target) {
return
}

if (Test-Path $Link) { Remove-Item $Link }
$LinkContainer = Split-Path $Link -Parent
if (!(Test-Path $LinkContainer)) { mkdir $LinkContainer }
Write-Verbose "Linking $Link to $Target"
if ($IsMacOS -or $IsLinux) {
ln $Target $Link
} else {
cmd /c mklink $Link $Target
}
}

# Stage all artifacts
$Artifacts = & "$PSScriptRoot\_all.ps1"
$Artifacts |% {
$DestinationFolder = (Join-Path (Join-Path $ArtifactStagingFolder "$($_.ArtifactName)$ArtifactNameSuffix") $_.ContainerFolder).TrimEnd('\')
$Name = "$(Split-Path $_.Source -Leaf)"

#Write-Host "$($_.Source) -> $($_.ArtifactName)\$($_.ContainerFolder)" -ForegroundColor Yellow

if (-not (Test-Path $DestinationFolder)) { New-Item -ItemType Directory -Path $DestinationFolder | Out-Null }
if (Test-Path -PathType Leaf $_.Source) { # skip folders
Create-SymbolicLink -Link "$DestinationFolder\$Name" -Target $_.Source
}
}

$Artifacts |% { $_.ArtifactName } | Get-Unique |% {
Write-Host "##vso[artifact.upload containerfolder=$_$ArtifactNameSuffix;artifactname=$_$ArtifactNameSuffix;]$ArtifactStagingFolder/$_$ArtifactNameSuffix"
& "$PSScriptRoot/_stage_all.ps1" -ArtifactNameSuffix $ArtifactNameSuffix |% {
Write-Host "##vso[artifact.upload containerfolder=$($_.Name);artifactname=$($_.Name);]$($_.Path)"
}
59 changes: 59 additions & 0 deletions azure-pipelines/artifacts/_stage_all.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# This script links all the artifacts described by _all.ps1
# into a staging directory, reading for uploading to a cloud build artifact store.
# It returns a sequence of objects with Name and Path properties.

param (
[string]$ArtifactNameSuffix
)

$RepoRoot = [System.IO.Path]::GetFullPath((Join-Path $PSScriptRoot (Join-Path .. ..)))
if ($env:BUILD_ARTIFACTSTAGINGDIRECTORY) {
$ArtifactStagingFolder = $env:BUILD_ARTIFACTSTAGINGDIRECTORY
} else {
$ArtifactStagingFolder = Join-Path $RepoRoot (Join-Path obj _artifacts)
if (Test-Path $ArtifactStagingFolder) {
Remove-Item $ArtifactStagingFolder -Recurse -Force
}
}

function Create-SymbolicLink {
param (
$Link,
$Target
)

if ($Link -eq $Target) {
return
}

if (Test-Path $Link) { Remove-Item $Link }
$LinkContainer = Split-Path $Link -Parent
if (!(Test-Path $LinkContainer)) { mkdir $LinkContainer }
Write-Verbose "Linking $Link to $Target"
if ($IsMacOS -or $IsLinux) {
ln $Target $Link | Out-Null
} else {
cmd /c mklink $Link $Target | Out-Null
}
}

# Stage all artifacts
$Artifacts = & "$PSScriptRoot\_all.ps1"
$Artifacts |% {
$DestinationFolder = (Join-Path (Join-Path $ArtifactStagingFolder "$($_.ArtifactName)$ArtifactNameSuffix") $_.ContainerFolder).TrimEnd('\')
$Name = "$(Split-Path $_.Source -Leaf)"

#Write-Host "$($_.Source) -> $($_.ArtifactName)\$($_.ContainerFolder)" -ForegroundColor Yellow

if (-not (Test-Path $DestinationFolder)) { New-Item -ItemType Directory -Path $DestinationFolder | Out-Null }
if (Test-Path -PathType Leaf $_.Source) { # skip folders
Create-SymbolicLink -Link (Join-Path $DestinationFolder $Name) -Target $_.Source
}
}

$Artifacts |% { "$($_.ArtifactName)$ArtifactNameSuffix" } | Get-Unique |% {
$artifact = New-Object -TypeName PSObject
Add-Member -InputObject $artifact -MemberType NoteProperty -Name Name -Value $_
Add-Member -InputObject $artifact -MemberType NoteProperty -Name Path -Value (Join-Path $ArtifactStagingFolder $_)
Write-Output $artifact
}
4 changes: 2 additions & 2 deletions azure-pipelines/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:

- job: Linux
pool:
vmImage: Ubuntu 16.04
vmImage: Ubuntu 18.04
steps:
- checkout: self
clean: true
Expand All @@ -41,7 +41,7 @@ jobs:
- Linux
- macOS
pool:
vmImage: Ubuntu 16.04
vmImage: Ubuntu 18.04
condition: succeededOrFailed()
steps:
- checkout: self
Expand Down
8 changes: 6 additions & 2 deletions azure-pipelines/variables/_pipelines.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@
# what the build would do. So only set them if they have not already been set.

(& "$PSScriptRoot\_all.ps1").GetEnumerator() |% {
if (Test-Path -Path "env:$($_.Key.ToUpper())") {
if (Test-Path -Path "env:$($_.Key)") {
Write-Host "Skipping setting $($_.Key) because variable is already set." -ForegroundColor Cyan
} else {
Write-Host "$($_.Key)=$($_.Value)" -ForegroundColor Yellow
Write-Host "##vso[task.setvariable variable=$($_.Key);]$($_.Value)"
if ($env:TF_BUILD) {
Write-Host "##vso[task.setvariable variable=$($_.Key);]$($_.Value)"
} elseif ($env:GITHUB_ACTIONS) {
Write-Host "::set-env name=$($_.Key)::$($_.Value)"
}
Set-Item -Path "env:$($_.Key)" -Value $_.Value
}
}
Loading

0 comments on commit 366d5df

Please sign in to comment.