Skip to content
This repository was archived by the owner on Jul 19, 2024. It is now read-only.

Basic travis CI setup #2

Merged
merged 1 commit into from
Jun 4, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
sudo: required

language: csharp
dotnet: 2.1
mono: none

services:
- docker

dist: trusty
addons:
apt:
sources:
- sourceline: "deb [arch=amd64] https://packages.microsoft.com/ubuntu/14.04/prod trusty main"
key_url: "https://packages.microsoft.com/keys/microsoft.asc"
packages:
- powershell

before_install:
- chmod ugo+x ./scripts/setup_repo.sh && ./scripts/setup_repo.sh
- sudo apt-get install -y powershell

install:
- pwsh -f "./Install-Prerequisites.ps1"
- export GitVersion_Version=$(docker run --rm -v "$(pwd):/repo" gittools/gitversion:5.0.0-linux-debian-9-netcoreapp2.2 /repo -output json -showvariable majorminorpatch)
- "echo \"GitVersion says: ${GitVersion_Version} \""

script:
- pwsh -c "Invoke-Psake -buildFile Build.ps1 -taskList build,test"

deploy:
provider: script
script: pwsh -c "Invoke-Psake -buildFile Build.ps1 -taskList build,test,publish"
on:
tags: true
branch: master
116 changes: 6 additions & 110 deletions Build.ps1
Original file line number Diff line number Diff line change
@@ -1,43 +1,3 @@
# This is a PSake script that supports the following tasks:
# clean, build, test and publish. The default task is build.
#
# The publish task uses the Publish-Module command to publish
# to either the PowerShell Gallery (the default) or you can change
# the $Repository property to the name of an alternate repository.
#
# The test task invokes Pester to run any Pester tests in your
# workspace folder. Name your test scripts <TestName>.Tests.ps1
# and Pester will find and run the tests contained in the files.
#
# You can run this build script directly using the invoke-psake
# command which will execute the build task. This task "builds"
# a temporary folder from which the module can be published.
#
# PS C:\> invoke-psake build.ps1
#
# You can run your Pester tests (if any) by running the following command.
#
# PS C:\> invoke-psake build.ps1 -taskList test
#
# You can execute the publish task with the following command. Note that
# the publish task will run the test task first. The Pester tests must pass
# before the publish task will run. The first time you run the publish
# command, you will be prompted to enter your PowerShell Gallery NuGetApiKey.
# After entering the key, it is encrypted and stored so you will not have to
# enter it again.
#
# PS C:\> invoke-psake build.ps1 -taskList publish
#
# You can verify the stored and encrypted NuGetApiKey by running the following
# command. This will display your NuGetApiKey in plain text!
#
# PS C:\> invoke-psake build.ps1 -taskList showKey
#
# You can store a new NuGetApiKey with this command. You can leave off
# the -properties parameter and you'll be prompted for the key.
#
# PS C:\> invoke-psake build.ps1 -taskList storeKey -properties @{NuGetApiKey='test123'}
#

###############################################################################
# Customize these properties for your module.
Expand All @@ -63,31 +23,18 @@ Properties {
(Split-Path $PSCommandPath -Leaf)
)

# Name of the repository you wish to publish to. Default repo is the PSGallery.
$PublishRepository = $null

# Your NuGet API key for the PSGallery. Leave it as $null and the first time
# you publish you will be prompted to enter your API key. The build will
# store the key encrypted in a file, so that on subsequent publishes you
# will no longer be prompted for the API key.
$NuGetApiKey = $null
$EncryptedApiKeyPath = "$env:LOCALAPPDATA\vscode-powershell\NuGetApiKey.clixml"
}

###############################################################################
# Customize these tasks for performing operations before and/or after publish.
###############################################################################
Task PrePublish {
$functionDeclarations = @( Get-ChildItem -Path $PublishDir\Public\*.ps1 -ErrorAction SilentlyContinue )
$functionNames = @()
foreach ($function in $functionDeclarations) {
$functionNames += $function.BaseName
}
$functionsToExport = $functionNames -join ","
[string[]]$functionNames = @($functionDeclarations.BaseName)

Update-ModuleManifest -Path $PublishDir\${ModuleName}.psd1 `
-ModuleVersion "0.0.14" `
-FunctionsToExport $functionsToExport
-ModuleVersion "$env:GitVersion_Version" `
-FunctionsToExport $functionNames
}

Task PostPublish {
Expand All @@ -102,8 +49,8 @@ Task default -depends Build
Task Publish -depends Test, PrePublish, PublishImpl, PostPublish {
}

Task PublishImpl -depends Test -requiredVariables PublishDir, EncryptedApiKeyPath {
$NuGetApiKey = Get-NuGetApiKey $NuGetApiKey $EncryptedApiKeyPath
Task PublishImpl -depends Test -requiredVariables PublishDir {
$NuGetApiKey = $env:PSGalleryAPIToken

$publishParams = @{
Path = $PublishDir
Expand All @@ -119,7 +66,7 @@ Task PublishImpl -depends Test -requiredVariables PublishDir, EncryptedApiKeyPat

Task Test -depends Build {
Import-Module Pester
Invoke-Pester $PSScriptRoot
Invoke-Pester $PSScriptRoot/Tests
}

Task Build -depends Clean -requiredVariables PublishDir, Exclude, ModuleName {
Expand Down Expand Up @@ -148,58 +95,7 @@ Task Init -requiredVariables PublishDir {
}
}

Task StoreKey -requiredVariables EncryptedApiKeyPath {
if (Test-Path $EncryptedApiKeyPath) {
Remove-Item $EncryptedApiKeyPath
}

$null = Get-NuGetApiKey $NuGetApiKey $EncryptedApiKeyPath
"The NuGetApiKey has been stored in $EncryptedApiKeyPath"
}

Task ShowKey -requiredVariables EncryptedApiKeyPath {
$NuGetApiKey = Get-NuGetApiKey $NuGetApiKey $EncryptedApiKeyPath
"The stored NuGetApiKey is: $NuGetApiKey"
}

Task ? -description 'Lists the available tasks' {
"Available tasks:"
$psake.context.Peek().tasks.Keys | Sort
}

###############################################################################
# Helper functions
###############################################################################
function Get-NuGetApiKey($NuGetApiKey, $EncryptedApiKeyPath) {
$storedKey = $null
if (!$NuGetApiKey) {
if (Test-Path $EncryptedApiKeyPath) {
$storedKey = Import-Clixml $EncryptedApiKeyPath | ConvertTo-SecureString
$cred = New-Object -TypeName PSCredential -ArgumentList 'kh',$storedKey
$NuGetApiKey = $cred.GetNetworkCredential().Password
Write-Verbose "Retrieved encrypted NuGetApiKey from $EncryptedApiKeyPath"
}
else {
$apiKeySS = Read-Host -Prompt "Enter your NuGet API Key" -AsSecureString
$cred = New-Object -TypeName PSCredential -ArgumentList 'dw',$apiKeySS
$NuGetApiKey = $cred.GetNetworkCredential().Password
}
}

if (!$storedKey) {
# Store encrypted NuGet API key to use for future invocations
if (!$apiKeySS) {
$apiKeySS = ConvertTo-SecureString -String $NuGetApiKey -AsPlainText -Force
}

$parentDir = Split-Path $EncryptedApiKeyPath -Parent
if (!(Test-Path -Path $parentDir)) {
$null = New-Item -Path $parentDir -ItemType Directory
}

$apiKeySS | ConvertFrom-SecureString | Export-Clixml $EncryptedApiKeyPath
Write-Verbose "Stored encrypted NuGetApiKey to $EncryptedApiKeyPath"
}

$NuGetApiKey
}
4 changes: 4 additions & 0 deletions GitVersion.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
mode: ContinuousDelivery
branches: {}
ignore:
sha: []
6 changes: 6 additions & 0 deletions Install-Prerequisites.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# The psake module is needed to run tests and publish the module to powershell gallery.
Set-PSRepository -Name "PSGallery" -InstallationPolicy Trusted
Install-Module -Name psake -RequiredVersion 4.8.0 -Repository "PSGallery"
Install-Module -Name pester -RequiredVersion 4.8.0 -Repository "PSGallery"


7 changes: 7 additions & 0 deletions Public/Invoke-Jenkins.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ function Invoke-Jenkins {

$attempts = 0

Write-Debug "---- Invoke-Jenkins ----"
Write-Debug "Resource: $Resource"
Write-Debug "Request: $request"
Write-Debug "Method: $Method"
Write-Debug "Body: $Body"
Write-Debug "Query: $Query"

while ($attempts -lt $MaximumAttempts) {

try {
Expand Down
8 changes: 5 additions & 3 deletions ReleaseNotes.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
Release Notes for v0.0.14
====================================
# Release Notes

## v0.1.0
Initial version that supports making basic requests to Jenkins via the Remote API.
Includes convenience functions to make and delete jobs.

Really nothing special to note yet.
29 changes: 15 additions & 14 deletions Tests/Invoke-Jenkins.Tests.ps1
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Import-Module "$PSScriptRoot\..\ThreeShape.Jenkins.psm1" -Force
Import-Module "$PSScriptRoot\..\Threeshape.Jenkins.Beta.psm1" -Force
. $PSScriptRoot\..\Private\Get-JenkinsRequestHeaders.ps1
. $PSScriptRoot\..\Private\ConvertTo-BasicAuth.ps1
. $PSScriptRoot\..\Private\Get-CrumbHeader.ps1
Expand Down Expand Up @@ -36,6 +36,7 @@ function Get-MockHttpResponseException {
Describe "Initialize-Jenkins method" {

BeforeAll {
$script:moduleName = (Get-Item $PSScriptRoot\..\*.psd1)[0].BaseName
$jenkinsUrl = "http://localhost"
$apiUser = "Bobby Bobbelhead"
$apiPassword = "Fallout4ever" | ConvertTo-SecureString -AsPlainText -Force
Expand All @@ -44,8 +45,8 @@ Describe "Initialize-Jenkins method" {
-ApiUsername $apiUser `
-ApiPassword $apiPassword

Mock -ModuleName ThreeShape.Jenkins -CommandName Get-CrumbHeader { return "this=crumb" }
Mock -ModuleName ThreeShape.Jenkins -CommandName Invoke-RestMethod { return "dfgdfg:sdfsdsf" }
Mock -ModuleName $script:moduleName -CommandName Get-CrumbHeader { return "this=crumb" }
Mock -ModuleName $script:moduleName -CommandName Invoke-RestMethod { return "dfgdfg:sdfsdsf" }
}

Context 'When invalid MaximumAttempts args are passed to Invoke-Jenkins' {
Expand All @@ -63,34 +64,34 @@ Describe "Initialize-Jenkins method" {
Context 'When a request to a jenkins backend is succesful' {

It 'Then Invoke-WebRequest is called within the Invoke-Jenkins method once and only once' {
Mock -ModuleName ThreeShape.Jenkins Invoke-WebRequest { "return 200 OK"}
Mock -ModuleName $script:moduleName Invoke-WebRequest { "return 200 OK"}

$result = Invoke-JenkinsRequest -Resource "nowhere" `
-Username "rasmus" `
-Password $script:apiPassword

$result | Should -Be "return 200 OK"

Assert-MockCalled -ModuleName ThreeShape.Jenkins -Scope "It" Invoke-WebRequest -Exactly -Times 1
Assert-MockCalled -ModuleName $script:moduleName -Scope "It" Invoke-WebRequest -Exactly -Times 1
}
}

Context 'When a request to jenkins fails' {
It 'then Invoke-WebRequest call is retried three times by default' {
Mock -ModuleName ThreeShape.Jenkins Invoke-WebRequest { throw [System.Net.Http.HttpRequestException]::new("Simulate an exception") }
Mock -ModuleName $script:moduleName Invoke-WebRequest { throw [System.Net.Http.HttpRequestException]::new("Simulate an exception") }

$result = Invoke-JenkinsRequest -Resource "nowhere" `
-Username "rasmus" `
-Password $script:apiPassword

$result | Should -BeExactly $null

Assert-MockCalled -ModuleName ThreeShape.Jenkins -Scope "It" Invoke-WebRequest -Exactly -Times 3
Assert-MockCalled -ModuleName $script:moduleName -Scope "It" Invoke-WebRequest -Exactly -Times 3
}


It 'Then Invoke-WebRequest is retried up to the number of times specified' {
Mock -ModuleName ThreeShape.Jenkins Invoke-WebRequest { throw [System.Net.Http.HttpRequestException]::new("Simulate an exception") }
Mock -ModuleName $script:moduleName Invoke-WebRequest { throw [System.Net.Http.HttpRequestException]::new("Simulate an exception") }

$result = Invoke-JenkinsRequest -Resource "nowhere" `
-Username "rasmus" `
Expand All @@ -99,13 +100,13 @@ Describe "Initialize-Jenkins method" {

$result | Should -BeExactly $null

Assert-MockCalled -ModuleName ThreeShape.Jenkins -Scope "It" Invoke-WebRequest -Exactly -Times 5
Assert-MockCalled -ModuleName $script:moduleName -Scope "It" Invoke-WebRequest -Exactly -Times 5
}

It 'Any failure causes an exception to be re-thrown' {
$exceptionBlock = Get-MockHttpResponseException -HttpStatusCode "[System.Net.HttpStatusCode]::Forbidden"

Mock -ModuleName ThreeShape.Jenkins Invoke-WebRequest $exceptionBlock
Mock -ModuleName $script:moduleName Invoke-WebRequest $exceptionBlock

$request = {
Invoke-JenkinsRequest -Resource "nowhere" `
Expand All @@ -117,7 +118,7 @@ Describe "Initialize-Jenkins method" {
}

It 'Any unexpected exception is rethrown for the caller to handle' {
Mock -ModuleName ThreeShape.Jenkins Invoke-WebRequest { throw [System.AccessViolationException]::new() }
Mock -ModuleName $script:moduleName Invoke-WebRequest { throw [System.AccessViolationException]::new() }

$request = {
Invoke-JenkinsRequest -Resource "nowhere" `
Expand All @@ -132,19 +133,19 @@ Describe "Initialize-Jenkins method" {
Context 'When a request returns a redirect' {
It 'The redirect is not treated as an exception when TreatRedirectsAsSucces is true as is the case by default)' {
$exceptionBlock = Get-MockHttpResponseException -HttpStatusCode "[System.Net.HttpStatusCode]::Redirect"
Mock -ModuleName ThreeShape.Jenkins Invoke-WebRequest $exceptionBlock
Mock -ModuleName $script:moduleName Invoke-WebRequest $exceptionBlock

$result = Invoke-JenkinsRequest -Resource "nowhere" `
-Username "rasmus" `
-Password $script:apiPassword

Assert-MockCalled -ModuleName ThreeShape.Jenkins -Scope "It" Invoke-WebRequest -Exactly -Times 1
Assert-MockCalled -ModuleName $script:moduleName -Scope "It" Invoke-WebRequest -Exactly -Times 1
$result | Should -Not -BeNullOrEmpty
}

It 'The redirect causes an exception if the caller sets TreatRedirectsAsSucces = false' {
$exceptionBlock = Get-MockHttpResponseException -HttpStatusCode "[System.Net.HttpStatusCode]::Redirect"
Mock -ModuleName ThreeShape.Jenkins Invoke-WebRequest $exceptionBlock
Mock -ModuleName $script:moduleName Invoke-WebRequest $exceptionBlock

$request = {
Invoke-JenkinsRequest -Resource "nowhere" `
Expand Down
Loading