This commit is contained in:
parent
97761f112c
commit
8fd180b776
122
.drone.yml
Normal file
122
.drone.yml
Normal file
@ -0,0 +1,122 @@
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: "Build Pipeline"
|
||||
|
||||
trigger:
|
||||
branch:
|
||||
exclude:
|
||||
- droneDocs/*
|
||||
|
||||
steps:
|
||||
- name: "Pwsh FileLinter"
|
||||
image: mcr.microsoft.com/dotnet/sdk:6.0-focal
|
||||
failure: ignore
|
||||
environment:
|
||||
EXCLUDE: "(.exe|.dll|.ico|.gitkeep)"
|
||||
commands:
|
||||
- |
|
||||
pwsh -NonInteractive -c "& {
|
||||
Import-Module './src/DroneHelper.psd1';
|
||||
Invoke-FileLinter
|
||||
}"
|
||||
|
||||
- name: "ScriptAnalyzer"
|
||||
image: mcr.microsoft.com/dotnet/sdk:6.0-focal
|
||||
failure: ignore
|
||||
commands:
|
||||
- |
|
||||
pwsh -NonInteractive -c "& {
|
||||
Import-Module './src/DroneHelper.psd1';
|
||||
Invoke-Linter
|
||||
}"
|
||||
|
||||
- name: "Pester"
|
||||
image: mcr.microsoft.com/dotnet/sdk:6.0-focal
|
||||
failure: ignore
|
||||
commands:
|
||||
- |
|
||||
pwsh -NonInteractive -c "& {
|
||||
Import-Module './src/DroneHelper.psd1';
|
||||
Invoke-UnitTest -ExcludeTag 'Integration'
|
||||
}"
|
||||
|
||||
- name: "PRComment"
|
||||
image: mcr.microsoft.com/dotnet/sdk:6.0-focal
|
||||
failure: ignore
|
||||
environment:
|
||||
GITEA_TOKEN:
|
||||
from_secret: GITEA_TOKEN
|
||||
CUSTOM_PIPELINE_STATE: true
|
||||
LOG_FILES: "build/*.log"
|
||||
commands:
|
||||
- |
|
||||
pwsh -NonInteractive -c "& {
|
||||
Import-Module './src/DroneHelper.psd1';
|
||||
Send-PRComment
|
||||
}"
|
||||
when:
|
||||
event:
|
||||
include:
|
||||
- pull_request
|
||||
|
||||
- name: "buildState"
|
||||
image: mcr.microsoft.com/dotnet/sdk:6.0-focal
|
||||
commands:
|
||||
- |
|
||||
pwsh -NonInteractive -c "& {
|
||||
Import-Module './src/DroneHelper.psd1';
|
||||
Invoke-BuildState
|
||||
}"
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: "Publish Pipeline"
|
||||
|
||||
depends_on:
|
||||
- "Build Pipeline"
|
||||
|
||||
trigger:
|
||||
event:
|
||||
- tag
|
||||
|
||||
steps:
|
||||
- name: BuildArtifacts
|
||||
image: mcr.microsoft.com/dotnet/sdk:6.0-focal
|
||||
#failure: ignore
|
||||
commands:
|
||||
- |
|
||||
pwsh -NonInteractive -c "& {
|
||||
Import-Module './src/DroneHelper.psd1';
|
||||
Update-ModuleMeta -Verbose
|
||||
}"
|
||||
- |
|
||||
pwsh -NonInteractive -c "& {
|
||||
Import-Module './src/DroneHelper.psd1';
|
||||
New-BuildPackage -AdditionalPath './src/Rules' -Verbose
|
||||
}"
|
||||
|
||||
- name: GiteaRelease
|
||||
image: plugins/gitea-release
|
||||
settings:
|
||||
api_key:
|
||||
from_secret: GITEA_TOKEN
|
||||
base_url: https://gitea.ocram85.com
|
||||
files:
|
||||
- "bin/${DRONE_REPO_NAME}.zip"
|
||||
title: ${DRONE_TAG}
|
||||
note: CHANGELOG.md
|
||||
|
||||
- name: "PublishModule"
|
||||
image: mcr.microsoft.com/dotnet/sdk:6.0-focal
|
||||
#failure: ignore
|
||||
environment:
|
||||
NexusToken:
|
||||
from_secret: NexusToken
|
||||
commands:
|
||||
- |
|
||||
pwsh -NonInteractive -c "& {
|
||||
Import-Module './src/DroneHelper.psd1';
|
||||
Invoke-Publish -Verbose
|
||||
}"
|
27
.editorconfig
Normal file
27
.editorconfig
Normal file
@ -0,0 +1,27 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
end_of_line = crlf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
|
||||
[*.yml]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.md]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
21
.gitattributes
vendored
Normal file
21
.gitattributes
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
# images
|
||||
|
||||
*.jpg binary
|
||||
*.jpeg binary
|
||||
*.bmp binary
|
||||
*.tiff binary
|
||||
*.png binary
|
||||
*.svg binary
|
||||
*.ico binary
|
||||
|
||||
# binary files
|
||||
*.exe binary
|
||||
*.dll binary
|
||||
|
||||
# PowerShell specific
|
||||
*.ps1 working-tree-encoding=UTF-8
|
||||
*.psm1 working-tree-encoding=UTF-8
|
||||
*.psd1 working-tree-encoding=UTF-8
|
||||
|
||||
# set markdown to lf for online editing
|
||||
*.md working-tree-encoding=UTF-8
|
11
.gitea/ISSUE_TEMPLATE.md
Normal file
11
.gitea/ISSUE_TEMPLATE.md
Normal file
@ -0,0 +1,11 @@
|
||||
---
|
||||
name: "Default"
|
||||
about: "Use this template if nothing seems to work."
|
||||
title: ":question: "
|
||||
labels:
|
||||
- question
|
||||
---
|
||||
|
||||
#### :grey_question: Simply ask your question here: :grey_question:
|
||||
|
||||
<!-- Take your time an think about your problem.... -->
|
48
.gitea/ISSUE_TEMPLATE/Bug.md
Normal file
48
.gitea/ISSUE_TEMPLATE/Bug.md
Normal file
@ -0,0 +1,48 @@
|
||||
---
|
||||
name: "Bug"
|
||||
about: "This template is used to report bugs!"
|
||||
title: ":lady_beetle: "
|
||||
labels:
|
||||
- bug
|
||||
---
|
||||
<!--
|
||||
This bug report is ony for content provided in this repository!
|
||||
|
||||
- Make sure you're able to reproduce the error in the latest version of this package.
|
||||
- Search of already existing issues.
|
||||
- Refer to the known issues and FAQ section.
|
||||
-->
|
||||
|
||||
#### :bomb: Steps to reproduce
|
||||
|
||||
```bash
|
||||
|
||||
```
|
||||
|
||||
#### :rocket: Expected behavior
|
||||
|
||||
```bash
|
||||
|
||||
```
|
||||
|
||||
#### :boom: Actual behavior
|
||||
|
||||
```bash
|
||||
|
||||
```
|
||||
|
||||
#### :notebook: Environment data
|
||||
|
||||
<!-- You can add additional environment data here--->
|
||||
|
||||
```bash
|
||||
|
||||
```
|
||||
|
||||
#### :framed_picture: Screenshots
|
||||
|
||||
<!-- Paste your screenshots here. -->
|
||||
|
||||
#### :bookmark: Refs
|
||||
|
||||
<!-- A place for additional references to other issues and PRs -->
|
24
.gitea/ISSUE_TEMPLATE/Enhancement.md
Normal file
24
.gitea/ISSUE_TEMPLATE/Enhancement.md
Normal file
@ -0,0 +1,24 @@
|
||||
---
|
||||
name: "Enhancement"
|
||||
about: "Wite about new features."
|
||||
title: ":flying_saucer: "
|
||||
labels:
|
||||
- enhancement
|
||||
---
|
||||
<!--
|
||||
This issue template is used to describe whished features.
|
||||
-->
|
||||
|
||||
#### :satellite: Suggestion
|
||||
|
||||
|
||||
|
||||
#### :artificial_satellite: Implementation ideas
|
||||
|
||||
|
||||
|
||||
#### :framed_picture: Mock-up Images
|
||||
|
||||
|
||||
|
||||
#### :bookmark: Refs.
|
19
.gitea/PULL_REQUEST_TEMPLATE.md
Normal file
19
.gitea/PULL_REQUEST_TEMPLATE.md
Normal file
@ -0,0 +1,19 @@
|
||||
#### :book: Summary
|
||||
|
||||
<!-- Provide a summary of your changes. Describe the why and not how. -->
|
||||
|
||||
#### :bookmark_tabs: Test Plan
|
||||
|
||||
> :bulb: Select your test plan for the code changes.
|
||||
|
||||
- [ ] Tested via Drone.io pipeline
|
||||
- [ ] Custom test
|
||||
- [ ] No test plan
|
||||
|
||||
##### Details / Justification
|
||||
|
||||
<!-- Add your test details or justification for missing tests here. -->
|
||||
|
||||
#### :books: Additional Notes
|
||||
|
||||
<!-- A place for additional detail notes. -->
|
14
.gitignore
vendored
Normal file
14
.gitignore
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
# Basic ignore patterns
|
||||
*.log
|
||||
*.secret
|
||||
|
||||
# data dir related prod files
|
||||
data/*.csv
|
||||
|
||||
# Ignore templ build artifacts
|
||||
/bin/*
|
||||
!bin/.gitkeep
|
||||
|
||||
# Ignore Unit Test result files
|
||||
coverage.xml
|
||||
testResults.xml
|
19
.gitlocal
Normal file
19
.gitlocal
Normal file
@ -0,0 +1,19 @@
|
||||
[alias]
|
||||
|
||||
# simplified logs
|
||||
log1 = log --graph --abbrev-commit --decorate --date=relative --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(bold yellow)%d%C(reset)' --all
|
||||
log2 = log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold cyan)%aD%C(reset) %C(bold green)(%ar)%C(reset)%C(bold yellow)%d%C(reset)%n'' %C(white)%s%C(reset) %C(dim white)- %an%C(reset)' --all
|
||||
|
||||
# Phabricator inspired workflow
|
||||
# 1. Create new feature branch
|
||||
feature = "!f(){ b=$1; git checkout master; git pull; git checkout -b "$b" master; };f"
|
||||
|
||||
# 2. Working with code
|
||||
wip = !"git add -A; git commit -m '[WIP]'"
|
||||
squish = !"git add -A; git commit --no-edit --amend"
|
||||
|
||||
# 3. Push to origin
|
||||
pod = !"git push origin dev"
|
||||
|
||||
# 4. Push to custom remote branch
|
||||
poc = "!f(){ b=$1; git push origin "$b";};f"
|
22
.vscode/cSpell.json
vendored
Normal file
22
.vscode/cSpell.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
// cSpell Settings
|
||||
{
|
||||
// Version of the setting file. Always 0.1
|
||||
"version": "0.1",
|
||||
// language - current active spelling language
|
||||
"language": "en,de,de-DE",
|
||||
// words - list of words to be always considered correct
|
||||
"words": [],
|
||||
// flagWords - list of words to be always considered incorrect
|
||||
// This is useful for offensive words and common spelling errors.
|
||||
// For example "hte" should be "the"
|
||||
"flagWords": [],
|
||||
"dictionaryDefinitions": [
|
||||
{
|
||||
"name": "default",
|
||||
"path": "./dictionaries/default.txt"
|
||||
}
|
||||
],
|
||||
"dictionaries": [
|
||||
"default"
|
||||
]
|
||||
}
|
0
.vscode/dictionaries/default.txt
vendored
Normal file
0
.vscode/dictionaries/default.txt
vendored
Normal file
10
.vscode/extensions.json
vendored
Normal file
10
.vscode/extensions.json
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"streetsidesoftware.code-spell-checker",
|
||||
"streetsidesoftware.code-spell-checker-german",
|
||||
"editorconfig.editorconfig",
|
||||
"eamodio.gitlens",
|
||||
"vscode-icons-team.vscode-icons",
|
||||
"ryanluker.vscode-coverage-gutters"
|
||||
]
|
||||
}
|
48
.vscode/launch.json
vendored
Normal file
48
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "PowerShell",
|
||||
"request": "launch",
|
||||
"name": "PowerShell Launch Current File",
|
||||
"script": "${file}",
|
||||
"args": [],
|
||||
"cwd": "${file}"
|
||||
},
|
||||
{
|
||||
"type": "PowerShell",
|
||||
"request": "launch",
|
||||
"name": "PowerShell Launch Current File in Temporary Console",
|
||||
"script": "${file}",
|
||||
"args": [],
|
||||
"cwd": "${file}",
|
||||
"createTemporaryIntegratedConsole": true
|
||||
},
|
||||
{
|
||||
"type": "PowerShell",
|
||||
"request": "launch",
|
||||
"name": "PowerShell Launch Current File w/Args Prompt",
|
||||
"script": "${file}",
|
||||
"args": [
|
||||
"${command:SpecifyScriptArgs}"
|
||||
],
|
||||
"cwd": "${file}"
|
||||
},
|
||||
{
|
||||
"type": "PowerShell",
|
||||
"request": "attach",
|
||||
"name": "PowerShell Attach to Host Process",
|
||||
"processId": "${command:PickPSHostProcess}",
|
||||
"runspaceId": 1
|
||||
},
|
||||
{
|
||||
"type": "PowerShell",
|
||||
"request": "launch",
|
||||
"name": "PowerShell Interactive Session",
|
||||
"cwd": "${workspaceRoot}"
|
||||
}
|
||||
]
|
||||
}
|
31
.vscode/pwsh.code-snippets
vendored
Normal file
31
.vscode/pwsh.code-snippets
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
{
|
||||
// Place your PowerShell-Module workspace snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and
|
||||
// description. Add comma separated ids of the languages where the snippet is applicable in the scope field. If scope
|
||||
// is left empty or omitted, the snippet gets applied to all languages. The prefix is what is
|
||||
// used to trigger the snippet and the body will be expanded and inserted. Possible variables are:
|
||||
// $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders.
|
||||
// Placeholders with the same ids are connected.
|
||||
// Example:
|
||||
// "Print to console": {
|
||||
// "scope": "javascript,typescript",
|
||||
// "prefix": "log",
|
||||
// "body": [
|
||||
// "console.log('$1');",
|
||||
// "$2"
|
||||
// ],
|
||||
// "description": "Log output to console"
|
||||
// }
|
||||
// PSScriptAnalyzder Rule Suppression
|
||||
"Rule Suppression": {
|
||||
"scope": "powershell",
|
||||
"prefix": "[Diag",
|
||||
"description": "Suppresses Scriptanalyzer Rules",
|
||||
"body": [
|
||||
"[Diagnostics.CodeAnalysis.SuppressMessageAttribute(",
|
||||
" '${1|PSProvideCommentHelp,PSAvoidLongLines,PSAvoidUsingWriteHost,PSUseShouldProcessForStateChangingFunctions,PSUseConsistentWhitespace|}',",
|
||||
" '',",
|
||||
" Justification = '${justification}'",
|
||||
")]"
|
||||
]
|
||||
}
|
||||
}
|
62
.vscode/settings.json
vendored
Normal file
62
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
{
|
||||
"files.encoding": "utf8",
|
||||
"files.eol": "auto",
|
||||
"files.trimTrailingWhitespace": true,
|
||||
"files.insertFinalNewline": true,
|
||||
"editor.renderWhitespace": "boundary",
|
||||
"editor.formatOnSave": true,
|
||||
"editor.formatOnType": true,
|
||||
"editor.rulers": [
|
||||
116
|
||||
],
|
||||
"cSpell.enabled": true,
|
||||
"cSpell.enabledLanguageIds": [
|
||||
"c",
|
||||
"cpp",
|
||||
"csharp",
|
||||
"go",
|
||||
"javascript",
|
||||
"javascriptreact",
|
||||
"json",
|
||||
"latex",
|
||||
"markdown",
|
||||
"php",
|
||||
"plaintext",
|
||||
"powershell",
|
||||
"python",
|
||||
"text",
|
||||
"typescript",
|
||||
"typescriptreact",
|
||||
"yaml",
|
||||
"yml"
|
||||
],
|
||||
"cSpell.language": "en,de,de-DE",
|
||||
// powershell general
|
||||
"powershell.startAutomatically": true,
|
||||
"powershell.useX86Host": false,
|
||||
"powershell.enableProfileLoading": true,
|
||||
"powershell.scriptAnalysis.enable": true,
|
||||
// powershell code Formatting
|
||||
"powershell.codeFormatting.openBraceOnSameLine": true,
|
||||
"powershell.codeFormatting.newLineAfterOpenBrace": true,
|
||||
"powershell.codeFormatting.newLineAfterCloseBrace": true,
|
||||
"powershell.codeFormatting.whitespaceBeforeOpenBrace": true,
|
||||
"powershell.codeFormatting.whitespaceBeforeOpenParen": true,
|
||||
"powershell.codeFormatting.whitespaceAroundOperator": true,
|
||||
"powershell.codeFormatting.whitespaceAfterSeparator": true,
|
||||
"powershell.codeFormatting.ignoreOneLineBlock": true,
|
||||
"powershell.codeFormatting.alignPropertyValuePairs": true,
|
||||
"powershell.scriptAnalysis.settingsPath": "resources/PSScriptAnalyzerSettings.psd1",
|
||||
"[yaml]": {
|
||||
"editor.insertSpaces": true,
|
||||
"editor.tabSize": 2,
|
||||
"editor.quickSuggestions": {
|
||||
"other": true,
|
||||
"comments": false,
|
||||
"strings": true
|
||||
},
|
||||
"editor.autoIndent": "full"
|
||||
},
|
||||
"coverage-gutters.showGutterCoverage": false,
|
||||
"coverage-gutters.showLineCoverage": true
|
||||
}
|
196
.vscode/tasks.json
vendored
Normal file
196
.vscode/tasks.json
vendored
Normal file
@ -0,0 +1,196 @@
|
||||
// A task runner that invokes Pester to run all Pester tests under the
|
||||
// current workspace folder.
|
||||
// NOTE: This Test task runner requires an updated version of Pester (>=4.0.3)
|
||||
// in order for the problemMatcher to find failed test information (message, line, file).
|
||||
// If you don't have that version, you can update Pester from the PowerShell Gallery
|
||||
// with this command:
|
||||
//
|
||||
// PS C:\> Update-Module Pester
|
||||
//
|
||||
// If that gives an error like:
|
||||
// "Module 'Pester' was not installed by using Install-Module, so it cannot be updated."
|
||||
// then execute:
|
||||
//
|
||||
// PS C:\> Install-Module Pester -Scope CurrentUser -Force
|
||||
//
|
||||
// NOTE: The Clean, Build and Publish tasks require PSake. PSake can be installed
|
||||
// from the PowerShell Gallery with this command:
|
||||
//
|
||||
// PS C:\> Install-Module PSake -Scope CurrentUser -Force
|
||||
//
|
||||
// Available variables which can be used inside of strings:
|
||||
// ${workspaceFolder} the path of the workspace folder that contains the tasks.json file
|
||||
// ${workspaceFolderBasename} the name of the workspace folder that contains the tasks.json file without any slashes (/)
|
||||
// ${file} the current opened file
|
||||
// ${relativeFile} the current opened file relative to the workspace folder containing the file
|
||||
// ${fileBasename} the current opened file's basename
|
||||
// ${fileBasenameNoExtension} the current opened file's basename without the extension
|
||||
// ${fileDirname} the current opened file's dirname
|
||||
// ${fileExtname} the current opened file's extension
|
||||
// ${cwd} the task runner's current working directory on startup
|
||||
// ${lineNumber} the current selected line number in the active file
|
||||
{
|
||||
"version": "2.0.0",
|
||||
//"windows": {
|
||||
// "options": {
|
||||
// "shell": {
|
||||
// // switch back to windows powershell 5.1
|
||||
// // "executable": "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe",
|
||||
// "executable": "pwsh.exe",
|
||||
// "args": [
|
||||
// "-NoProfile",
|
||||
// "-ExecutionPolicy",
|
||||
// "Bypass",
|
||||
// "-Command"
|
||||
// ]
|
||||
// }
|
||||
// }
|
||||
//},
|
||||
//"linux": {
|
||||
// "options": {
|
||||
// "shell": {
|
||||
// "executable": "/usr/bin/pwsh",
|
||||
// "args": [
|
||||
// "-NoProfile",
|
||||
// "-Command"
|
||||
// ]
|
||||
// }
|
||||
// }
|
||||
//},
|
||||
//"osx": {
|
||||
// "options": {
|
||||
// "shell": {
|
||||
// "executable": "/usr/local/bin/pwsh",
|
||||
// "args": [
|
||||
// "-NoProfile",
|
||||
// "-Command"
|
||||
// ]
|
||||
// }
|
||||
// }
|
||||
//},
|
||||
"tasks": [
|
||||
{
|
||||
"label": "DroneHelper: Invoke-FileLinter",
|
||||
"type": "shell",
|
||||
"command": [
|
||||
"Remove-Item ./build/FileLinter-Results.log -ErrorAction 'SilentlyContinue';",
|
||||
"Remove-Item ./failure.log -ErrorAction 'SilentlyContinue';",
|
||||
"Import-Module ./src/DroneHelper.psd1;",
|
||||
"Invoke-FileLinter"
|
||||
],
|
||||
"group": "test",
|
||||
"problemMatcher": [
|
||||
"$pester"
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "DroneHelper: Invoke-Linter",
|
||||
"type": "shell",
|
||||
"command": [
|
||||
"Remove-Item ./build/ScriptAnalyzer-Results.log -ErrorAction 'SilentlyContinue';",
|
||||
"Remove-Item ./failure.log -ErrorAction 'SilentlyContinue';",
|
||||
"Import-Module ./src/DroneHelper.psd1;",
|
||||
"Invoke-Linter"
|
||||
],
|
||||
"group": "test",
|
||||
"problemMatcher": [
|
||||
"$pester"
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "DroneHelper: Invoke-UnitTest",
|
||||
"type": "shell",
|
||||
"command": [
|
||||
"Remove-Item ./coverage.xml -ErrorAction 'SilentlyContinue';",
|
||||
"Remove-Item ./testResults.xml -ErrorAction 'SilentlyContinue';",
|
||||
"Remove-Item ./build/FileLinter-Results.log -ErrorAction 'SilentlyContinue';",
|
||||
"Remove-Item ./build/Pester-Results.log -ErrorAction 'SilentlyContinue';",
|
||||
"Remove-Item ./failure.log -ErrorAction 'SilentlyContinue';",
|
||||
"Import-Module ./src/DroneHelper.psd1;",
|
||||
"Invoke-UnitTest -CoverageFormat 'CoverageGutters' -Verbosity 'Detailed'"
|
||||
],
|
||||
"group": "test",
|
||||
"problemMatcher": [
|
||||
"$pester"
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "DroneHelper: Full Test",
|
||||
"type": "shell",
|
||||
"command": [
|
||||
"Remove-Item ./build/ScriptAnalyzer-Results.log -ErrorAction 'SilentlyContinue';",
|
||||
"Remove-Item ./build/FileLinter-Results.log -ErrorAction 'SilentlyContinue';",
|
||||
"Remove-Item ./build/Pester-Results.log -ErrorAction 'SilentlyContinue';",
|
||||
"Remove-Item ./coverage.xml -ErrorAction 'SilentlyContinue';",
|
||||
"Remove-Item ./testResults.xml -ErrorAction 'SilentlyContinue';",
|
||||
"Remove-Item ./failure.log -ErrorAction 'SilentlyContinue';",
|
||||
"Import-Module ./src/DroneHelper.psd1;",
|
||||
"Invoke-FileLinter;",
|
||||
"Invoke-Linter;",
|
||||
"Invoke-UnitTest -CoverageFormat 'CoverageGutters' -Verbosity 'Detailed'"
|
||||
],
|
||||
"group": {
|
||||
"kind": "test",
|
||||
"isDefault": true
|
||||
},
|
||||
"problemMatcher": [
|
||||
"$pester"
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "Add dictionary item",
|
||||
"type": "shell",
|
||||
"command": [
|
||||
"$DefaultFile = Get-ChildItem -Path './.vscode/dictionaries/default.txt';",
|
||||
"$Content = Get-Content -Path $DefaultFile;",
|
||||
"$Content += '${input:DictionaryItem}';",
|
||||
"$Content = $Content | Sort-Object -Unique;",
|
||||
"Set-Content -Value $Content -Path $DefaultFile"
|
||||
],
|
||||
"group": "none",
|
||||
"problemMatcher": [
|
||||
"$pester"
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "DroneHelper: New Docs",
|
||||
"type": "shell",
|
||||
"command": [
|
||||
"Import-Module ./src/DroneHelper.psd1;",
|
||||
"New-Docs"
|
||||
],
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "DroneHelper: Update Docs",
|
||||
"type": "shell",
|
||||
"command": [
|
||||
"Import-Module ./src/DroneHelper.psd1;",
|
||||
"Update-Docs"
|
||||
],
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "DroneHelper: Update Changelog",
|
||||
"type": "shell",
|
||||
"command": [
|
||||
"Import-Module ./src/DroneHelper.psd1;",
|
||||
"Update-Changelog -NewVersion '${input:NewVersion}'"
|
||||
],
|
||||
"problemMatcher": []
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"id": "DictionaryItem",
|
||||
"type": "promptString",
|
||||
"description": "Input for dictionary file default.txt"
|
||||
},
|
||||
{
|
||||
"id": "NewVersion",
|
||||
"type": "promptString",
|
||||
"description": "Enter a new semver version id",
|
||||
"default": "v1.0.0"
|
||||
}
|
||||
]
|
||||
}
|
193
README.md
193
README.md
@ -1,3 +1,194 @@
|
||||
# DroneHelper
|
||||
|
||||
Helper module for Drone.io CI.
|
||||
[![Build Status](https://drone.ocram85.com/api/badges/OCram85/DroneHelper/status.svg)](https://drone.ocram85.com/OCram85/DroneHelper)
|
||||
|
||||
## Description
|
||||
|
||||
Helper module for Drone.io based build pipelines.
|
||||
|
||||
## About
|
||||
|
||||
The DroneHelper PowerShell Modules adds several feature to a `Gitea -> Drone.IO` based build pipeline. It's designed
|
||||
to perform all needed tasks for PowerShell Module development like:
|
||||
|
||||
- `FileLinter` -> Runs basic FileLinter tests with console and log file output
|
||||
- `Linter` -> Runs PSScriptAnalyer with embedded to custom profiles.
|
||||
- `UnitTest` -> Executes Pester tests with code coverage with console and log file output.
|
||||
- `BuildReport` -> Takes all generated reports and reports them back as Pull Request Comment for a simplified overview.
|
||||
- `StateReporter` -> Marks the current pipeline run / build as failed if the previous steps also raised errors.
|
||||
- `DoksUpdater` -> Automatically updates the markdown based docs generated form your Comment Based Help blocks in your functions
|
||||
|
||||
To use these feature, all you have to do, is follow the `.drone.yml` template:
|
||||
|
||||
### `.drone.yml` Template
|
||||
|
||||
```yaml
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: "Build Pipeline"
|
||||
|
||||
trigger:
|
||||
branch:
|
||||
exclude:
|
||||
- droneDocs/*
|
||||
|
||||
steps:
|
||||
- name: "Pwsh FileLinter"
|
||||
image: mcr.microsoft.com/dotnet/sdk:6.0-focal
|
||||
failure: ignore
|
||||
environment:
|
||||
EXCLUDE: "(.exe|.dll|.ico|.gitkeep)"
|
||||
commands:
|
||||
- |
|
||||
pwsh -NonInteractive -c "& {
|
||||
Import-Module 'DroneHelper';
|
||||
Invoke-FileLinter
|
||||
}"
|
||||
|
||||
- name: "ScriptAnalyzer"
|
||||
image: mcr.microsoft.com/dotnet/sdk:6.0-focal
|
||||
failure: ignore
|
||||
commands:
|
||||
- |
|
||||
pwsh -NonInteractive -c "& {
|
||||
Import-Module -Name 'DroneHelper';
|
||||
Install-ModuleDependency;
|
||||
Invoke-Linter
|
||||
}"
|
||||
|
||||
- name: "Pester"
|
||||
image: mcr.microsoft.com/dotnet/sdk:6.0-focal
|
||||
failure: ignore
|
||||
commands:
|
||||
- |
|
||||
pwsh -NonInteractive -c "& {
|
||||
Import-Module -Name 'DroneHelper';
|
||||
Install-ModuleDependency;
|
||||
Invoke-UnitTest -Verbosity 'Detailed' -ExcludeTag 'Integration'
|
||||
}"
|
||||
|
||||
- name: "PRComment"
|
||||
image: mcr.microsoft.com/dotnet/sdk:6.0-focal
|
||||
failure: ignore
|
||||
environment:
|
||||
GITEA_TOKEN:
|
||||
from_secret: GITEA_TOKEN
|
||||
CUSTOM_PIPELINE_STATE: true
|
||||
LOG_FILES: "build/*.log"
|
||||
commands:
|
||||
- |
|
||||
pwsh -NonInteractive -c "& {
|
||||
Import-Module 'DroneHelper';
|
||||
Send-PRComment
|
||||
}"
|
||||
when:
|
||||
event:
|
||||
include:
|
||||
- pull_request
|
||||
|
||||
- name: "buildState"
|
||||
image: mcr.microsoft.com/dotnet/sdk:6.0-focal
|
||||
commands:
|
||||
- |
|
||||
pwsh -NonInteractive -c "& {
|
||||
Import-Module -Name 'DroneHelper';
|
||||
Install-ModuleDependency;
|
||||
Invoke-BuildState
|
||||
}"
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: "Publish Pipeline"
|
||||
|
||||
depends_on:
|
||||
- "Build Pipeline"
|
||||
|
||||
trigger:
|
||||
event:
|
||||
- tag
|
||||
|
||||
steps:
|
||||
- name: BuildArtifacts
|
||||
image: mcr.microsoft.com/dotnet/sdk:6.0-focal
|
||||
#failure: ignore
|
||||
commands:
|
||||
- |
|
||||
pwsh -NonInteractive -c "& {
|
||||
Import-Module -Name 'DroneHelper';
|
||||
Install-ModuleDependency;
|
||||
Update-ModuleMeta -Verbose
|
||||
}"
|
||||
- |
|
||||
pwsh -NonInteractive -c "& {
|
||||
Import-Module -Name 'DroneHelper';
|
||||
Install-ModuleDependency;
|
||||
New-BuildPackage -Verbose
|
||||
}"
|
||||
|
||||
- name: GiteaRelease
|
||||
image: plugins/gitea-release
|
||||
settings:
|
||||
api_key:
|
||||
from_secret: GITEA_TOKEN
|
||||
base_url: https://gitea.ocram85.com
|
||||
files:
|
||||
- "bin/${DRONE_REPO_NAME}.zip"
|
||||
- "bin/PSModule.zip"
|
||||
title: "${DRONE_TAG}"
|
||||
note: CHANGELOG.md
|
||||
|
||||
- name: "PublishModule"
|
||||
image: mcr.microsoft.com/dotnet/sdk:6.0-focal
|
||||
#failure: ignore
|
||||
environment:
|
||||
NexusToken:
|
||||
from_secret: NexusToken
|
||||
commands:
|
||||
- |
|
||||
pwsh -NonInteractive -c "& {
|
||||
Import-Module -Name 'DroneHelper';
|
||||
Install-ModuleDependency;
|
||||
Invoke-Publish -Verbose
|
||||
}"
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: "Update Docs"
|
||||
|
||||
depends_on:
|
||||
- "Build Pipeline"
|
||||
|
||||
trigger:
|
||||
event:
|
||||
exclude:
|
||||
- pull_request
|
||||
branch:
|
||||
include:
|
||||
- master
|
||||
|
||||
steps:
|
||||
- name: "Update Docs"
|
||||
image: mcr.microsoft.com/dotnet/sdk:6.0-focal
|
||||
commands:
|
||||
- |
|
||||
pwsh -NonInteractive -c "& {
|
||||
Import-Module -Name 'DroneHelper';
|
||||
Install-ModuleDependency;
|
||||
Update-Docs -Verbose
|
||||
}"
|
||||
|
||||
- name: "push commit"
|
||||
image: appleboy/drone-git-push
|
||||
settings:
|
||||
remote_name: origin
|
||||
branch: "droneDocs/${DRONE_COMMIT:0:8}"
|
||||
local_ref: droneDocs
|
||||
commit: true
|
||||
commit_message: "docs updated by drone [CI SKIP]"
|
||||
author_name: drone
|
||||
author_email: noreply@ocram85.com
|
||||
force: true
|
||||
```
|
||||
|
1
assets/.gitkeep
Normal file
1
assets/.gitkeep
Normal file
@ -0,0 +1 @@
|
||||
git placeholder file
|
1
bin/.gitkeep
Normal file
1
bin/.gitkeep
Normal file
@ -0,0 +1 @@
|
||||
git placeholder file
|
1
build/.gitkeep
Normal file
1
build/.gitkeep
Normal file
@ -0,0 +1 @@
|
||||
git placeholder file
|
0
resources/.gitkeep
Normal file
0
resources/.gitkeep
Normal file
141
resources/PSScriptAnalyzerSettings.psd1.back
Normal file
141
resources/PSScriptAnalyzerSettings.psd1.back
Normal file
@ -0,0 +1,141 @@
|
||||
@{
|
||||
Severity = 'Error', 'Warning', 'Information'
|
||||
|
||||
IncludeRules = @(
|
||||
'PSAlignAssignmentStatement',
|
||||
'PSAvoidAssignmentToAutomaticVariable',
|
||||
'PSAvoidDefaultValueForMandatoryParameter',
|
||||
'PSAvoidDefaultValueSwitchParameter',
|
||||
'PSAvoidGlobalAliases',
|
||||
'PSAvoidGlobalFunctions',
|
||||
'PSAvoidGlobalVars',
|
||||
'PSAvoidInvokingEmptyMembers',
|
||||
'PSAvoidLongLines',
|
||||
'PSAvoidNullOrEmptyHelpMessageAttribute',
|
||||
'PSAvoidOverwritingBuiltInCmdlets',
|
||||
'PSAvoidShouldContinueWithoutForce',
|
||||
'PSAvoidTrailingWhitespace',
|
||||
'PSAvoidUsingCmdletAliases',
|
||||
'PSAvoidUsingComputerNameHardcoded',
|
||||
'PSAvoidUsingConvertToSecureStringWithPlainText',
|
||||
'PSAvoidUsingDeprecatedManifestFields',
|
||||
'PSAvoidUsingDoubleQuotesForConstantString',
|
||||
'PSAvoidUsingEmptyCatchBlock',
|
||||
'PSAvoidUsingInvokeExpression',
|
||||
'PSAvoidUsingPlainTextForPassword',
|
||||
'PSAvoidUsingPositionalParameters',
|
||||
'PSAvoidUsingUsernameAndPasswordParams',
|
||||
'PSAvoidUsingWMICmdlet',
|
||||
'PSAvoidUsingWriteHost',
|
||||
'PSMisleadingBacktick',
|
||||
'PSMissingModuleManifestField',
|
||||
'PSPlaceCloseBrace',
|
||||
'PSPlaceOpenBrace',
|
||||
'PSPossibleIncorrectComparisonWithNull',
|
||||
'PSPossibleIncorrectUsageOfAssignmentOperator',
|
||||
'PSPossibleIncorrectUsageOfRedirectionOperator',
|
||||
'PSProvideCommentHelp',
|
||||
'PSReservedCmdletChar',
|
||||
'PSReservedParams',
|
||||
'PSReviewUnusedParameter',
|
||||
'PSShouldProcess',
|
||||
'PSUseApprovedVerbs',
|
||||
'PSUseBOMForUnicodeEncodedFile',
|
||||
'PSUseCmdletCorrectly',
|
||||
# There is no predefined set for Pwsh7 Cmdlets
|
||||
'PSUseCompatibleCmdlets',
|
||||
#'PSUseCompatibleCommands',
|
||||
'PSUseCompatibleSyntax',
|
||||
#'PSUseCompatibleTypes',
|
||||
'PSUseConsistentIndentation',
|
||||
# Disable if bug in 1.19.1 version occurs.
|
||||
'PSUseConsistentWhitespace',
|
||||
'PSUseCorrectCasing',
|
||||
'PSUseDeclaredVarsMoreThanAssignments',
|
||||
'PSUseLiteralInitializerForHashtable',
|
||||
'PSUseOutputTypeCorrectly',
|
||||
'PSUsePSCredentialType',
|
||||
'PSUseProcessBlockForPipelineCommand',
|
||||
'PSUseShouldProcessForStateChangingFunctions',
|
||||
'PSUseSingularNouns',
|
||||
'PSUseSupportsShouldProcess',
|
||||
'PSUseToExportFieldsInManifest',
|
||||
'PSUseUTF8EncodingForHelpFile',
|
||||
'PSUseUsingScopeModifierInNewRunspaces'
|
||||
)
|
||||
|
||||
Rules = @{
|
||||
|
||||
PSAvoidLongLines = @{
|
||||
Enable = $true
|
||||
MaximumLineLength = 116
|
||||
}
|
||||
|
||||
PSPlaceOpenBrace = @{
|
||||
Enable = $true
|
||||
OnSameLine = $true
|
||||
NewLineAfter = $true
|
||||
IgnoreOneLineBlock = $true
|
||||
}
|
||||
|
||||
PSPlaceCloseBrace = @{
|
||||
Enable = $true
|
||||
NewLineAfter = $true
|
||||
IgnoreOneLineBlock = $true
|
||||
NoEmptyLineBefore = $false
|
||||
}
|
||||
|
||||
PSProvideCommentHelp = @{
|
||||
Enable = $true
|
||||
ExportedOnly = $false
|
||||
BlockComment = $true
|
||||
VSCodeSnippetCorrection = $false
|
||||
Placement = "begin"
|
||||
}
|
||||
|
||||
PSUseCompatibleCmdlets = @{
|
||||
compatibility = @(
|
||||
"desktop-5.1.14393.206-windows",
|
||||
"core-6.1.0-windows"
|
||||
)
|
||||
}
|
||||
|
||||
PSUseCompatibleSyntax = @{
|
||||
Enable = $true
|
||||
TargetVersions = @(
|
||||
"7.0",
|
||||
"5.1"
|
||||
)
|
||||
}
|
||||
|
||||
PSUseConsistentIndentation = @{
|
||||
Enable = $true
|
||||
Kind = 'space'
|
||||
PipelineIndentation = 'IncreaseIndentationForFirstPipeline'
|
||||
IndentationSize = 4
|
||||
}
|
||||
|
||||
PSUseConsistentWhitespace = @{
|
||||
Enable = $true
|
||||
CheckInnerBrace = $true
|
||||
CheckOpenBrace = $true
|
||||
CheckOpenParen = $true
|
||||
CheckOperator = $true
|
||||
CheckPipe = $true
|
||||
CheckPipeForRedundantWhitespace = $false
|
||||
CheckSeparator = $true
|
||||
CheckParameter = $false
|
||||
IgnoreAssignmentOperatorInsideHashTable = $true
|
||||
}
|
||||
|
||||
PSAlignAssignmentStatement = @{
|
||||
Enable = $true
|
||||
CheckHashtable = $false
|
||||
}
|
||||
|
||||
PSUseCorrectCasing = @{
|
||||
Enable = $true
|
||||
}
|
||||
}
|
||||
|
||||
}
|
9
resources/TestData/encodingTest.txt
Normal file
9
resources/TestData/encodingTest.txt
Normal file
@ -0,0 +1,9 @@
|
||||
This is just a test file. Used for testing the encoding linter
|
||||
|
||||
#### Test Data ####
|
||||
|
||||
ABCD
|
||||
abcdefg
|
||||
12345678
|
||||
öäü
|
||||
!"§$%&/()
|
21
src/Build/Merge-ModuleRoot.Tests.ps1
Normal file
21
src/Build/Merge-ModuleRoot.Tests.ps1
Normal file
@ -0,0 +1,21 @@
|
||||
BeforeAll {
|
||||
$Repo = Get-RepoPath
|
||||
Import-Module $Repo.Src.Manifest.Item.FullName -Force
|
||||
}
|
||||
Describe 'Merge-ModuleRoot' {
|
||||
Context 'Default tests' -Tag 'Default' {
|
||||
It 'Test Function' {
|
||||
{ Get-Command -Name 'Merge-ModuleRoot' -Module $Repo.Artifact } | Should -Not -Throw
|
||||
}
|
||||
|
||||
It 'Test Help' {
|
||||
{ Get-Help -Name 'Merge-ModuleRoot' } | Should -Not -Throw
|
||||
}
|
||||
It 'Help Content' {
|
||||
$foo = Get-Help -Name 'Merge-ModuleRoot'
|
||||
$foo.Synopsis.Length | Should -BeGreaterThan 5
|
||||
$foo.Description.Count | Should -BeGreaterOrEqual 1
|
||||
$foo.Description[0].Text.Length | Should -BeGreaterThan 5
|
||||
}
|
||||
}
|
||||
}
|
42
src/Build/Merge-ModuleRoot.ps1
Normal file
42
src/Build/Merge-ModuleRoot.ps1
Normal file
@ -0,0 +1,42 @@
|
||||
function Merge-ModuleRoot {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Merges single ps1 files into one module script file.
|
||||
|
||||
.DESCRIPTION
|
||||
This Cmdlet is used in build pipeline to reduce the file load and import performance to the target module.
|
||||
|
||||
.INPUTS
|
||||
[None] No pipeline input.
|
||||
|
||||
.OUTPUTS
|
||||
[None] No pipeline output.
|
||||
|
||||
.EXAMPLE
|
||||
Import-Module -Name DroneHelper; Merge-ModuleRoot
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
param ()
|
||||
|
||||
process {
|
||||
$Repo = Get-RepoPath
|
||||
|
||||
$srcFiles = Get-ChildItem -Path $Repo.Src.Path -Recurse -File | Where-Object {
|
||||
($_.Name -notmatch '.Tests.') -and ($_.Name -match '.ps1') -and ($_.Name -notmatch '.ps1xml')
|
||||
}
|
||||
$Output = @()
|
||||
foreach ($psFile in $srcFiles) {
|
||||
$fileContent = Get-Content -Path $psFile.FullName -Raw -Encoding 'utf8'
|
||||
$Output += '# srcFile: {0}' -f $psFile.FullName
|
||||
$Output += $fileContent.TrimEnd()
|
||||
$Output += '{0}' -f [Environment]::NewLine
|
||||
}
|
||||
try {
|
||||
$Output | Out-File -FilePath $Repo.Bin.ScriptModuleName -Encoding 'utf8' -Force -ErrorAction Stop
|
||||
}
|
||||
catch {
|
||||
Write-FailureStateFile -StepName 'MergeModuleRoot'
|
||||
throw 'Could not write the final module root script file!'
|
||||
}
|
||||
}
|
||||
}
|
21
src/Build/New-BuildPackage.Tests.ps1
Normal file
21
src/Build/New-BuildPackage.Tests.ps1
Normal file
@ -0,0 +1,21 @@
|
||||
BeforeAll {
|
||||
$Repo = Get-RepoPath
|
||||
Import-Module $Repo.Src.Manifest.Item.FullName -Force
|
||||
}
|
||||
Describe 'New-BuildPackage' {
|
||||
Context 'Default tests' -Tag 'Default' {
|
||||
It 'Test Function' {
|
||||
{ Get-Command -Name 'New-BuildPackage' -Module $Repo.Artifact } | Should -Not -Throw
|
||||
}
|
||||
|
||||
It 'Test Help' {
|
||||
{ Get-Help -Name 'New-BuildPackage' } | Should -Not -Throw
|
||||
}
|
||||
It 'Help Content' {
|
||||
$foo = Get-Help -Name 'New-BuildPackage'
|
||||
$foo.Synopsis.Length | Should -BeGreaterThan 5
|
||||
$foo.Description.Count | Should -BeGreaterOrEqual 1
|
||||
$foo.Description[0].Text.Length | Should -BeGreaterThan 5
|
||||
}
|
||||
}
|
||||
}
|
74
src/Build/New-BuildPackage.ps1
Normal file
74
src/Build/New-BuildPackage.ps1
Normal file
@ -0,0 +1,74 @@
|
||||
function New-BuildPackage {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Creates a new module package as compressed archive.
|
||||
|
||||
.DESCRIPTION
|
||||
This function is used in build pipeline to create an uploadable module version for the Gitea release page.
|
||||
|
||||
.PARAMETER AdditionalPath
|
||||
You can provide additional paths to add files or folders in published module.
|
||||
|
||||
.INPUTS
|
||||
[None] No pipeline input.
|
||||
|
||||
.OUTPUTS
|
||||
[None] No pipeline output.
|
||||
|
||||
.EXAMPLE
|
||||
Import-Module -Name DroneHelper; New-BuildPackage
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
[OutputType()]
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
|
||||
'PSUseConsistentWhitespace',
|
||||
'',
|
||||
Justification = 'Hashtable bug in ScriptAnalyzer 1.19.1'
|
||||
)]
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
|
||||
'PSUseShouldProcessForStateChangingFunctions',
|
||||
'',
|
||||
Justification = 'system state does not change permanent in temp build clients.'
|
||||
)]
|
||||
|
||||
param (
|
||||
[Parameter(Mandatory = $false)]
|
||||
[String[]]$AdditionalPath
|
||||
)
|
||||
|
||||
process {
|
||||
$Repo = Get-RepoPath
|
||||
$res = @()
|
||||
foreach ($item in $AdditionalPath) {
|
||||
try {
|
||||
$res += Resolve-Path -Path $item -ErrorAction Stop
|
||||
}
|
||||
catch {
|
||||
Write-Error -Message ('The given additional path does not exist! ({0})' -f $item) -ErrorAction Stop
|
||||
}
|
||||
}
|
||||
Merge-ModuleRoot -ErrorAction Stop
|
||||
$CompressParams = @{
|
||||
Path = @(
|
||||
# psm1 file
|
||||
$Repo.Bin.ScriptModuleName
|
||||
# psd1 file
|
||||
$Repo.Src.Manifest.Item.FullName
|
||||
# Formats/ folder
|
||||
$Repo.Src.Formats.Path
|
||||
)
|
||||
DestinationPath = $Repo.Bin.ArtifactPath
|
||||
Force = $true
|
||||
ErrorAction = 'Stop'
|
||||
Verbose = $VerbosePreference
|
||||
}
|
||||
$CompressParams.Path += $res
|
||||
try {
|
||||
Compress-Archive @CompressParams
|
||||
}
|
||||
catch {
|
||||
Write-FailureStateFile -StepName 'BuildPackage'
|
||||
throw $_.Exception.Message
|
||||
}
|
||||
}
|
||||
}
|
21
src/Build/Update-ModuleMeta.Tests.ps1
Normal file
21
src/Build/Update-ModuleMeta.Tests.ps1
Normal file
@ -0,0 +1,21 @@
|
||||
BeforeAll {
|
||||
$Repo = Get-RepoPath
|
||||
Import-Module $Repo.Src.Manifest.Item.FullName -Force
|
||||
}
|
||||
Describe 'Update-ModuleMeta' {
|
||||
Context 'Default tests' -Tag 'Default' {
|
||||
It 'Test Function' {
|
||||
{ Get-Command -Name 'Update-ModuleMeta' -Module $Repo.Artifact } | Should -Not -Throw
|
||||
}
|
||||
|
||||
It 'Test Help' {
|
||||
{ Get-Help -Name 'Update-ModuleMeta' } | Should -Not -Throw
|
||||
}
|
||||
It 'Help Content' {
|
||||
$foo = Get-Help -Name 'Update-ModuleMeta'
|
||||
$foo.Synopsis.Length | Should -BeGreaterThan 5
|
||||
$foo.Description.Count | Should -BeGreaterOrEqual 1
|
||||
$foo.Description[0].Text.Length | Should -BeGreaterThan 5
|
||||
}
|
||||
}
|
||||
}
|
75
src/Build/Update-ModuleMeta.ps1
Normal file
75
src/Build/Update-ModuleMeta.ps1
Normal file
@ -0,0 +1,75 @@
|
||||
function Update-ModuleMeta {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Updates the module manifest file fields to prepare the new build.
|
||||
|
||||
.DESCRIPTION
|
||||
Replaces the version fields in the manifest file. Uses Drone env vars populated by pushed tags.
|
||||
|
||||
.INPUTS
|
||||
[None] No pipeline input.
|
||||
|
||||
.OUTPUTS
|
||||
[None] No pipeline output.
|
||||
|
||||
.EXAMPLE
|
||||
Import-Module -Name DroneHelper; Update-ModuleMeta
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
[OutputType()]
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
|
||||
'PSUseConsistentWhitespace',
|
||||
'',
|
||||
Justification = 'Hashtable bug in ScriptAnalyzer 1.19.1'
|
||||
)]
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
|
||||
'PSUseShouldProcessForStateChangingFunctions',
|
||||
'',
|
||||
Justification = 'system state does not change permanent in temp build clients.'
|
||||
)]
|
||||
param ()
|
||||
|
||||
process {
|
||||
if ($Env:DRONE) {
|
||||
$Repo = Get-RepoPath
|
||||
if ($Env:DRONE_BUILD_EVENT -eq 'tag') {
|
||||
if ($null -ne $Env:DRONE_SEMVER) {
|
||||
$nVersion = $Env:DRONE_SEMVER_SHORT
|
||||
|
||||
if ($null -ne $Env:DRONE_SEMVER_PRERELEASE) {
|
||||
$nPreRelease = $Env:DRONE_SEMVER_PRERELEASE
|
||||
}
|
||||
$ModManifestParams = @{
|
||||
Path = $Repo.Src.Manifest.Item.FullName
|
||||
ModuleVersion = $nVersion
|
||||
ErrorAction = 'Stop'
|
||||
}
|
||||
if ($nPreRelease) {
|
||||
$ModManifestParams.PreRelease = $nPreRelease
|
||||
}
|
||||
|
||||
$ManifestData = Test-ModuleManifest -Path $Repo.Src.Manifest.Item.FullName
|
||||
|
||||
if (
|
||||
($nVersion -ne $ManifestData.Version) -or
|
||||
($nVersion -ne $ManifestData.PrivateData.PSData.Prerelease)
|
||||
) {
|
||||
Update-ModuleManifest @ModManifestParams
|
||||
}
|
||||
else {
|
||||
Write-Verbose -Message 'Identical version given. Skipping update.'
|
||||
}
|
||||
}
|
||||
else {
|
||||
Write-Verbose -Message 'Could not read the new Tag / Semver!'
|
||||
}
|
||||
}
|
||||
else {
|
||||
Write-Verbose -Message 'This pipeline was not triggered by a tag.'
|
||||
}
|
||||
}
|
||||
else {
|
||||
Write-Verbose -Message 'Running outside of drone.io pipeline. Skipping module update!'
|
||||
}
|
||||
}
|
||||
}
|
3
src/CHANGELOG.md
Normal file
3
src/CHANGELOG.md
Normal file
@ -0,0 +1,3 @@
|
||||
# Changelog
|
||||
|
||||
<!-- insertMark -->
|
21
src/Changelog/Update-Changelog.Tests.ps1
Normal file
21
src/Changelog/Update-Changelog.Tests.ps1
Normal file
@ -0,0 +1,21 @@
|
||||
BeforeAll {
|
||||
$Repo = Get-RepoPath
|
||||
Import-Module $Repo.Src.Manifest.Item.FullName -Force
|
||||
}
|
||||
Describe 'Update-Changelog' {
|
||||
Context 'Default tests' -Tag 'Default' {
|
||||
It 'Test Function' {
|
||||
{ Get-Command -Name 'Update-Changelog' -Module $Repo.Artifact } | Should -Not -Throw
|
||||
}
|
||||
|
||||
It 'Test Help' {
|
||||
{ Get-Help -Name 'Update-Changelog' } | Should -Not -Throw
|
||||
}
|
||||
It 'Help Content' {
|
||||
$foo = Get-Help -Name 'Update-Changelog'
|
||||
$foo.Synopsis.Length | Should -BeGreaterThan 5
|
||||
$foo.Description.Count | Should -BeGreaterOrEqual 1
|
||||
$foo.Description[0].Text.Length | Should -BeGreaterThan 5
|
||||
}
|
||||
}
|
||||
}
|
93
src/Changelog/Update-Changelog.ps1
Normal file
93
src/Changelog/Update-Changelog.ps1
Normal file
@ -0,0 +1,93 @@
|
||||
function Update-Changelog {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Updates the changelog file with recent commits
|
||||
|
||||
.DESCRIPTION
|
||||
This helper function is used to insert recent changes for an upcoming release.
|
||||
|
||||
.Parameter NewVersion
|
||||
Provide a valid semver based version tag for the upcoming release like:
|
||||
|
||||
- `v0.0.1-dev1`
|
||||
- `v1.0.0`
|
||||
|
||||
.Parameter SkipCleanup
|
||||
You can skip the tag update and additional test.
|
||||
|
||||
.INPUTS
|
||||
[None] No pipeline input.
|
||||
|
||||
.OUTPUTS
|
||||
[None] no pipeline putput.
|
||||
|
||||
.EXAMPLE
|
||||
Import-Module -Name DroneHelper; Update-Changelog -NewVersion '0.0.1-dev5'
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
|
||||
'PSAvoidUsingInvokeExpression',
|
||||
'',
|
||||
Justification = 'raw git commands needed'
|
||||
)]
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
|
||||
'PSUseShouldProcessForStateChangingFunctions',
|
||||
'',
|
||||
Justification = 'system state does not change permanent in temp build clients.'
|
||||
)]
|
||||
param (
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidatePattern('^(v)?([0-9]+)\.([0-9]+)\.([0-9]+)(-([A-Za-z]+)([0-9]+))?$')]
|
||||
[String]$NewVersion,
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[Switch]$SkipCleanup
|
||||
)
|
||||
process {
|
||||
if (-not $SkipCleanup.IsPresent) {
|
||||
Invoke-Expression -Command 'git tag -d $(git tag -l)' | Write-Verbose
|
||||
Invoke-Expression -Command 'git fetch --tags --prune' | Write-Verbose
|
||||
$GitState = Get-GitStatus
|
||||
|
||||
if ($GitState.Branch -eq 'master') {
|
||||
Write-Error -Message 'You can nor update the changelog within the master branch!' -ErrorAction Stop
|
||||
}
|
||||
if (
|
||||
($GitState.BehindBy -ne 0) -or
|
||||
($GitState.AheadBy -ne 0) -or
|
||||
($GitState.HasUntracked -ne $false) -or
|
||||
($GitState.HasWorking -ne $false)
|
||||
) {
|
||||
Write-Error -Message 'Your branch is a mess! Cleanup and try it again.' -ErrorAction Stop
|
||||
}
|
||||
}
|
||||
|
||||
$Repo = Get-RepoPath
|
||||
$Tags = Invoke-Expression -Command 'git tag'
|
||||
$NormalizedTags = $Tags | Where-Object { $_ -notmatch '-' } | ForEach-Object {
|
||||
[PSCustomObject]@{
|
||||
tag = $_
|
||||
rawVersion = (
|
||||
($_ -split '-')[0] -replace 'v', ''
|
||||
)
|
||||
}
|
||||
}
|
||||
$LTag = $NormalizedTags | Sort-Object -Property 'rawVersion' | Select-Object -ExpandProperty 'tag' -Last 1
|
||||
Write-Debug -Message ('Last tag: {0}' -f $LTag)
|
||||
if ($null -eq $LTag) {
|
||||
Write-Error -Message 'No tags found!' -ErrorAction 'Stop'
|
||||
}
|
||||
$Expr = "git log {0}..HEAD --format='- (%h) %s'" -f $LTag
|
||||
$Res = Invoke-Expression -Command $Expr
|
||||
Write-Debug -Message ('New Changelog: {0}' -f $Res)
|
||||
if ($Repo.Changelog.Exists) {
|
||||
$Content = Get-Content -Path $Repo.Changelog.Item.FullName
|
||||
$Content[2] += "{0}## ``{2}``{0}{0}{1}" -f [Environment]::NewLine, ($Res | Out-String), $NewVersion
|
||||
$Content | Out-File -FilePath $Repo.Changelog.Item.FullName -Encoding utf8
|
||||
Set-EOL -Path $Repo.Changelog.Item.FullName
|
||||
}
|
||||
else {
|
||||
Write-Error -Message 'Changelog file does not exist!' -ErrorAction Stop
|
||||
}
|
||||
}
|
||||
}
|
21
src/Deploy/Invoke-Publish.Tests.ps1
Normal file
21
src/Deploy/Invoke-Publish.Tests.ps1
Normal file
@ -0,0 +1,21 @@
|
||||
BeforeAll {
|
||||
$Repo = Get-RepoPath
|
||||
Import-Module $Repo.Src.Manifest.Item.FullName -Force
|
||||
}
|
||||
Describe 'Invoke-Publish' {
|
||||
Context 'Default tests' -Tag 'Default' {
|
||||
It 'Test Function' {
|
||||
{ Get-Command -Name 'Invoke-Publish' -Module $Repo.Artifact } | Should -Not -Throw
|
||||
}
|
||||
|
||||
It 'Test Help' {
|
||||
{ Get-Help -Name 'Invoke-Publish' } | Should -Not -Throw
|
||||
}
|
||||
It 'Help Content' {
|
||||
$foo = Get-Help -Name 'Invoke-Publish'
|
||||
$foo.Synopsis.Length | Should -BeGreaterThan 5
|
||||
$foo.Description.Count | Should -BeGreaterOrEqual 1
|
||||
$foo.Description[0].Text.Length | Should -BeGreaterThan 5
|
||||
}
|
||||
}
|
||||
}
|
46
src/Deploy/Invoke-Publish.ps1
Normal file
46
src/Deploy/Invoke-Publish.ps1
Normal file
@ -0,0 +1,46 @@
|
||||
function Invoke-Publish {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Publishes powershell module to internal Nexus repository.
|
||||
|
||||
.DESCRIPTION
|
||||
This Cmdlet is used to publish the module via Drone pipeline.
|
||||
|
||||
.INPUTS
|
||||
[None] No pipeline input.
|
||||
|
||||
.OUTPUTS
|
||||
[None] No pipeline output.
|
||||
|
||||
.EXAMPLE
|
||||
Invoke-Publish
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
|
||||
'PSUseConsistentWhitespace',
|
||||
'',
|
||||
Justification = 'Hashtable bug in ScriptAnalyzer 1.19.1'
|
||||
)]
|
||||
param ()
|
||||
|
||||
process {
|
||||
$Repo = Get-RepoPath
|
||||
$ExpandParams = @{
|
||||
Path = $Repo.Bin.ArtifactPath
|
||||
DestinationPath = $Repo.Bin.ExpandPath
|
||||
Force = $true
|
||||
ErrorAction = 'Stop'
|
||||
Verbose = $VerbosePreference
|
||||
}
|
||||
Expand-Archive @ExpandParams
|
||||
|
||||
$PublishParams = @{
|
||||
Repository = 'Nexus'
|
||||
Path = $Repo.Bin.ExpandPath
|
||||
NuGetApiKey = $Env:NexusToken
|
||||
Verbose = $VerbosePreference
|
||||
ErrorAction = 'Stop'
|
||||
}
|
||||
Publish-Module @PublishParams
|
||||
}
|
||||
}
|
32
src/Deps/Install-ModuleDependency.Tests.ps1
Normal file
32
src/Deps/Install-ModuleDependency.Tests.ps1
Normal file
@ -0,0 +1,32 @@
|
||||
BeforeAll {
|
||||
$Repo = Get-RepoPath
|
||||
Import-Module $Repo.Src.Manifest.Item.FullName -Force
|
||||
}
|
||||
Describe 'Install-ModuleDependency' {
|
||||
Context 'Default tests' -Tag 'Default' {
|
||||
It 'Test Function' {
|
||||
{ Get-Command -Name 'Install-ModuleDependency' -Module $Repo.Artifact } | Should -Not -Throw
|
||||
}
|
||||
|
||||
It 'Test Help' {
|
||||
{ Get-Help -Name 'Install-ModuleDependency' } | Should -Not -Throw
|
||||
}
|
||||
|
||||
It 'Help Content' {
|
||||
$foo = Get-Help -Name 'Install-ModuleDependency'
|
||||
$foo.Synopsis.Length | Should -BeGreaterThan 5
|
||||
$foo.Description.Count | Should -BeGreaterOrEqual 1
|
||||
$foo.Description[0].Text.Length | Should -BeGreaterThan 5
|
||||
}
|
||||
}
|
||||
Context 'Unit tests' -Tag 'Unit' {
|
||||
It 'Should throw' {
|
||||
{ Install-ModuleDependency -foo } | Should -Throw
|
||||
}
|
||||
|
||||
#It 'Should not throw' {
|
||||
# Mock 'Install-Module' -ModuleName $Repo.Artifact {}
|
||||
# { Install-ModuleDependency } | Should -Not -Throw
|
||||
#}
|
||||
}
|
||||
}
|
74
src/Deps/Install-ModuleDependency.ps1
Normal file
74
src/Deps/Install-ModuleDependency.ps1
Normal file
@ -0,0 +1,74 @@
|
||||
function Install-ModuleDependency {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Install required modules of the module manifest file.
|
||||
|
||||
.DESCRIPTION
|
||||
Use this cmdlet to install required modules of the module manifest file.
|
||||
|
||||
.INPUTS
|
||||
[None]
|
||||
|
||||
.OUTPUTS
|
||||
[None]
|
||||
|
||||
.EXAMPLE
|
||||
Install-ModuleDependency
|
||||
|
||||
.NOTES
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
#[OutputType([String])]
|
||||
param ()
|
||||
|
||||
begin {
|
||||
}
|
||||
|
||||
process {
|
||||
$Repo = Get-RepoPath
|
||||
$ManifestContent = Import-PowerShellDataFile -Path $Repo.Src.Manifest.Item.FullName
|
||||
if ($ManifestContent.RequiredModules) {
|
||||
foreach ($Module in $ManifestContent.RequiredModules) {
|
||||
if ($Module.RequiredVersion) {
|
||||
$ParamsInstallModule = @{
|
||||
Name = $Module.ModuleName
|
||||
Scope = 'AllUsers'
|
||||
RequiredVersion = $Module.RequiredVersion
|
||||
Force = $true
|
||||
AllowClobber = $true
|
||||
Verbose = $VerbosePreference
|
||||
ErrorAction = 'Stop'
|
||||
}
|
||||
}
|
||||
else {
|
||||
$ParamsInstallModule = @{
|
||||
Name = $Module.ModuleName
|
||||
Scope = 'AllUsers'
|
||||
MinimumVersion = $Module.ModuleVersion
|
||||
Force = $true
|
||||
AllowClobber = $true
|
||||
Verbose = $VerbosePreference
|
||||
ErrorAction = 'Stop'
|
||||
}
|
||||
}
|
||||
try {
|
||||
Install-Module @ParamsInstallModule
|
||||
$Message = 'Module <{0}> successfully installed' -f $Module.ModuleName
|
||||
Write-Verbose -Message $Message
|
||||
}
|
||||
catch {
|
||||
$Message = 'Module <{0}> could not be installed! ' -f $Module.ModuleName
|
||||
$Message += $_.Exception.Message
|
||||
Write-Error -Message $Message -ErrorAction 'Stop'
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
Write-Verbose -Message 'no required modules found...'
|
||||
}
|
||||
}
|
||||
|
||||
end {
|
||||
}
|
||||
}
|
21
src/Deps/Invoke-InstallDependency.Tests.ps1
Normal file
21
src/Deps/Invoke-InstallDependency.Tests.ps1
Normal file
@ -0,0 +1,21 @@
|
||||
BeforeAll {
|
||||
$Repo = Get-RepoPath
|
||||
Import-Module $Repo.Src.Manifest.Item.FullName -Force
|
||||
}
|
||||
Describe 'Invoke-InstallDependency' {
|
||||
Context 'Default tests' -Tag 'Default' {
|
||||
It 'Test Function' {
|
||||
{ Get-Command -Name 'Invoke-InstallDependency' -Module $Repo.Artifact } | Should -Not -Throw
|
||||
}
|
||||
|
||||
It 'Test Help' {
|
||||
{ Get-Help -Name 'Invoke-InstallDependency' } | Should -Not -Throw
|
||||
}
|
||||
It 'Help Content' {
|
||||
$foo = Get-Help -Name 'Invoke-InstallDependency'
|
||||
$foo.Synopsis.Length | Should -BeGreaterThan 5
|
||||
$foo.Description.Count | Should -BeGreaterOrEqual 1
|
||||
$foo.Description[0].Text.Length | Should -BeGreaterThan 5
|
||||
}
|
||||
}
|
||||
}
|
72
src/Deps/Invoke-InstallDependency.ps1
Normal file
72
src/Deps/Invoke-InstallDependency.ps1
Normal file
@ -0,0 +1,72 @@
|
||||
function Invoke-InstallDependency {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Install required modules for executing the DroneHelper pipeline helpers.
|
||||
|
||||
.DESCRIPTION
|
||||
This can be used in drone.io docker pipeline if the modules are not integrated in the build image.
|
||||
|
||||
.INPUTS
|
||||
[None] No Input required.
|
||||
|
||||
.OUTPUTS
|
||||
[None] No Output
|
||||
|
||||
.EXAMPLE
|
||||
Import-Module -Name DroneHelper; Invoke-Install-Dependency
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
[OutputType()]
|
||||
param ()
|
||||
|
||||
process {
|
||||
try {
|
||||
$PSScriptParams = @{
|
||||
Name = 'PSScriptAnalyzer'
|
||||
Scope = 'CurrentUser'
|
||||
RequiredVersion = '1.20.0'
|
||||
Force = $true
|
||||
SkipPublisherCheck = $true
|
||||
AllowClobber = $true
|
||||
Verbose = $VerbosePreference
|
||||
ErrorAction = 'Stop'
|
||||
}
|
||||
Install-Module @PSScriptParams
|
||||
|
||||
$PesterParams = @{
|
||||
Name = 'Pester'
|
||||
Scope = 'CurrentUser'
|
||||
RequiredVersion = '5.3.1'
|
||||
Force = $true
|
||||
SkipPublisherCheck = $true
|
||||
AllowClobber = $true
|
||||
Verbose = $VerbosePreference
|
||||
ErrorAction = 'Stop'
|
||||
}
|
||||
Install-Module @PesterParams
|
||||
|
||||
$PoshParams = @{
|
||||
Name = 'posh-git'
|
||||
Scope = 'CurrentUser'
|
||||
RequiredVersion = '1.0.0'
|
||||
Force = $true
|
||||
SkipPublisherCheck = $true
|
||||
AllowClobber = $true
|
||||
Verbose = $VerbosePreference
|
||||
ErrorAction = 'Stop'
|
||||
}
|
||||
Install-Module @PoshParams
|
||||
}
|
||||
catch {
|
||||
$ExecParams = @{
|
||||
Exception = [System.Exception]::new(
|
||||
'Could not install required build dependencies!',
|
||||
$PSItem.Exception
|
||||
)
|
||||
ErrorAction = 'Stop'
|
||||
}
|
||||
Write-Error @ExecParams
|
||||
}
|
||||
|
||||
}
|
||||
}
|
21
src/Docs/New-Docs.Tests.ps1
Normal file
21
src/Docs/New-Docs.Tests.ps1
Normal file
@ -0,0 +1,21 @@
|
||||
BeforeAll {
|
||||
$Repo = Get-RepoPath
|
||||
Import-Module $Repo.Src.Manifest.Item.FullName -Force
|
||||
}
|
||||
Describe 'New-Docs' {
|
||||
Context 'Default tests' -Tag 'Default' {
|
||||
It 'Test Function' {
|
||||
{ Get-Command -Name 'New-Docs' -Module $Repo.Artifact } | Should -Not -Throw
|
||||
}
|
||||
|
||||
It 'Test Help' {
|
||||
{ Get-Help -Name 'New-Docs' } | Should -Not -Throw
|
||||
}
|
||||
It 'Help Content' {
|
||||
$foo = Get-Help -Name 'New-Docs'
|
||||
$foo.Synopsis.Length | Should -BeGreaterThan 5
|
||||
$foo.Description.Count | Should -BeGreaterOrEqual 1
|
||||
$foo.Description[0].Text.Length | Should -BeGreaterThan 5
|
||||
}
|
||||
}
|
||||
}
|
50
src/Docs/New-Docs.ps1
Normal file
50
src/Docs/New-Docs.ps1
Normal file
@ -0,0 +1,50 @@
|
||||
function New-Docs {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Creates a ne set of markdown based help in the docs folder.
|
||||
|
||||
.DESCRIPTION
|
||||
This Cmdlet should be used once locally, or after adding new functions. The function `Update-Docs`
|
||||
can be used via pipeline to keep the docs up to date.
|
||||
.INPUTS
|
||||
[None] No pipeline input.
|
||||
|
||||
.OUTPUTS
|
||||
[None] No pipeline output.
|
||||
|
||||
.EXAMPLE
|
||||
New-Docs
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
|
||||
'PSUseSingularNouns',
|
||||
'',
|
||||
Justification = 'New-Doc already in use by other popular modules.'
|
||||
)]
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
|
||||
'PSUseShouldProcessForStateChangingFunctions',
|
||||
'',
|
||||
Justification = 'system state does not change permanent in temp build clients.'
|
||||
)]
|
||||
param ()
|
||||
|
||||
process {
|
||||
$Repo = Get-RepoPath
|
||||
Import-Module $Repo.Src.Manifest.Item.FullName -Global -Force
|
||||
Import-Module -Name 'platyPS'
|
||||
$MarkdownParams = @{
|
||||
Module = $Repo.Artifact
|
||||
OutputFolder = $Repo.Docs.Path
|
||||
WithModulePage = $true
|
||||
ModulePagePath = $Repo.Docs.ModulePagePath
|
||||
Force = $true
|
||||
}
|
||||
New-MarkdownHelp @MarkdownParams
|
||||
|
||||
$Docs = Get-Item -Path $Repo.Docs.MarkdownFilter
|
||||
foreach ($Doc in $Docs) {
|
||||
Write-Verbose -Message ('Converting {0}' -f $Doc.FullName)
|
||||
Set-EOL -Path $Doc
|
||||
}
|
||||
}
|
||||
}
|
21
src/Docs/Update-Docs.Tests.ps1
Normal file
21
src/Docs/Update-Docs.Tests.ps1
Normal file
@ -0,0 +1,21 @@
|
||||
BeforeAll {
|
||||
$Repo = Get-RepoPath
|
||||
Import-Module $Repo.Src.Manifest.Item.FullName -Force
|
||||
}
|
||||
Describe 'Update-Docs' {
|
||||
Context 'Default tests' -Tag 'Default' {
|
||||
It 'Test Function' {
|
||||
{ Get-Command -Name 'Update-Docs' -Module $Repo.Artifact } | Should -Not -Throw
|
||||
}
|
||||
|
||||
It 'Test Help' {
|
||||
{ Get-Help -Name 'Update-Docs' } | Should -Not -Throw
|
||||
}
|
||||
It 'Help Content' {
|
||||
$foo = Get-Help -Name 'Update-Docs'
|
||||
$foo.Synopsis.Length | Should -BeGreaterThan 5
|
||||
$foo.Description.Count | Should -BeGreaterOrEqual 1
|
||||
$foo.Description[0].Text.Length | Should -BeGreaterThan 5
|
||||
}
|
||||
}
|
||||
}
|
49
src/Docs/Update-Docs.ps1
Normal file
49
src/Docs/Update-Docs.ps1
Normal file
@ -0,0 +1,49 @@
|
||||
function Update-Docs {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Publishes powershell module to internal Nexus repository.
|
||||
|
||||
.DESCRIPTION
|
||||
This Cmdlet is used to publish the module via Drone pipeline.
|
||||
|
||||
.INPUTS
|
||||
[None] No pipeline input.
|
||||
|
||||
.OUTPUTS
|
||||
[None] No pipeline output.
|
||||
|
||||
.EXAMPLE
|
||||
Update-Docs
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
|
||||
'PSUseShouldProcessForStateChangingFunctions',
|
||||
'',
|
||||
Justification = 'Underlying platyPS can not be mocked.'
|
||||
)]
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
|
||||
'PSUseSingularNouns',
|
||||
'',
|
||||
Justification = 'New-Doc already in use by other popular modules.'
|
||||
)]
|
||||
param ()
|
||||
|
||||
process {
|
||||
$Repo = Get-RepoPath
|
||||
Import-Module $Repo.Src.Manifest.Item.FullName -Global -Force
|
||||
Import-Module -Name 'platyPS'
|
||||
$MarkdownParams = @{
|
||||
Path = $Repo.Docs.Path
|
||||
RefreshModulePage = $true
|
||||
ModulePagePath = $Repo.Docs.ModulePagePath
|
||||
Force = $true
|
||||
}
|
||||
Update-MarkdownHelpModule @MarkdownParams
|
||||
|
||||
$Docs = Get-Item -Path $Repo.Docs.MarkdownFilter
|
||||
foreach ($Doc in $Docs) {
|
||||
Write-Verbose -Message ('Converting {0}' -f $Doc.FullName)
|
||||
Set-EOL -Path $Doc
|
||||
}
|
||||
}
|
||||
}
|
190
src/DroneHelper.psd1
Normal file
190
src/DroneHelper.psd1
Normal file
@ -0,0 +1,190 @@
|
||||
#
|
||||
# Module manifest for module 'DroneHelper'
|
||||
#
|
||||
# Generated by: OCram85
|
||||
#
|
||||
# Generated on: 13.06.2022
|
||||
#
|
||||
|
||||
@{
|
||||
|
||||
# Script module or binary module file associated with this manifest.
|
||||
RootModule = 'ModuleRoot.psm1'
|
||||
|
||||
# Version number of this module.
|
||||
ModuleVersion = '0.0.1'
|
||||
|
||||
# Supported PSEditions
|
||||
CompatiblePSEditions = @(
|
||||
'Desktop',
|
||||
'Core'
|
||||
)
|
||||
|
||||
# ID used to uniquely identify this module
|
||||
GUID = '4293292f-eac8-42ed-8e9d-437d4f405d2c'
|
||||
|
||||
# Author of this module
|
||||
Author = 'OCram85'
|
||||
|
||||
# Company or vendor of this module
|
||||
CompanyName = ''
|
||||
|
||||
# Copyright statement for this module
|
||||
Copyright = '(c) OCram85. All rights reserved.'
|
||||
|
||||
# Description of the functionality provided by this module
|
||||
Description = 'Helper module for Drone.io CI.'
|
||||
|
||||
# Minimum version of the PowerShell engine required by this module
|
||||
PowerShellVersion = '5.1'
|
||||
|
||||
# Name of the PowerShell host required by this module
|
||||
# PowerShellHostName = ''
|
||||
|
||||
# Minimum version of the PowerShell host required by this module
|
||||
# PowerShellHostVersion = ''
|
||||
|
||||
# Minimum version of Microsoft .NET Framework required by this module.
|
||||
# This prerequisite is valid for the PowerShell Desktop edition only.
|
||||
# DotNetFrameworkVersion = ''
|
||||
|
||||
# Minimum version of the common language runtime (CLR) required by this module.
|
||||
# This prerequisite is valid for the PowerShell Desktop edition only.
|
||||
# ClrVersion = ''
|
||||
|
||||
# Processor architecture (None, X86, Amd64) required by this module
|
||||
# ProcessorArchitecture = ''
|
||||
|
||||
# Modules that must be imported into the global environment prior to importing this module
|
||||
RequiredModules = @(
|
||||
@{
|
||||
ModuleName = 'PSScriptAnalyzer'
|
||||
RequiredVersion = '1.20.0'
|
||||
},
|
||||
@{
|
||||
ModuleName = 'Pester'
|
||||
RequiredVersion = '5.3.1'
|
||||
},
|
||||
@{
|
||||
ModuleName = 'posh-git'
|
||||
ModuleVersion = '1.1.0'
|
||||
}
|
||||
)
|
||||
|
||||
# Assemblies that must be loaded prior to importing this module
|
||||
# RequiredAssemblies = @()
|
||||
|
||||
# Script files (.ps1) that are run in the caller's environment prior to importing this module.
|
||||
# ScriptsToProcess = @()
|
||||
|
||||
# Type files (.ps1xml) to be loaded when importing this module
|
||||
# TypesToProcess = @()
|
||||
|
||||
# Format files (.ps1xml) to be loaded when importing this module
|
||||
# FormatsToProcess = @()
|
||||
|
||||
# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
|
||||
# NestedModules = @()
|
||||
|
||||
# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry,
|
||||
# use an empty array if there are no functions to export.
|
||||
FunctionsToExport = @(
|
||||
# Build
|
||||
'Merge-ModuleRoot',
|
||||
'New-BuildPackage',
|
||||
'Update-ModuleMeta',
|
||||
# Changelog
|
||||
'Update-Changelog',
|
||||
# Deploy
|
||||
'Invoke-Publish',
|
||||
# Deps
|
||||
'Install-ModuleDependency',
|
||||
'Invoke-InstallDependency',
|
||||
# Docs
|
||||
'New-Docs',
|
||||
'Update-Docs',
|
||||
# FileLinter
|
||||
'Invoke-FileLinter',
|
||||
'Test-FileBOM',
|
||||
'Test-FileEncoding',
|
||||
'Test-FileEOF',
|
||||
'Test-FileEOL',
|
||||
'Test-FileTab',
|
||||
'Test-FileTailingWhitespace',
|
||||
# Helper
|
||||
'Get-RepoPath',
|
||||
'Set-EOL',
|
||||
# Pester
|
||||
'Invoke-UnitTest',
|
||||
# PRComment
|
||||
'Send-PRComment',
|
||||
# PSScriptAnalyzer
|
||||
'Invoke-Linter',
|
||||
# State
|
||||
'Invoke-BuildState',
|
||||
'Write-FailureStateFile',
|
||||
'Write-ResultFile'
|
||||
)
|
||||
|
||||
# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry,
|
||||
# use an empty array if there are no cmdlets to export.
|
||||
CmdletsToExport = @()
|
||||
|
||||
# Variables to export from this module
|
||||
VariablesToExport = '*'
|
||||
|
||||
# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry,
|
||||
# use an empty array if there are no aliases to export.
|
||||
AliasesToExport = @()
|
||||
|
||||
# DSC resources to export from this module
|
||||
# DscResourcesToExport = @()
|
||||
|
||||
# List of all modules packaged with this module
|
||||
# ModuleList = @()
|
||||
|
||||
# List of all files packaged with this module
|
||||
# FileList = @()
|
||||
|
||||
# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData
|
||||
# hashtable with additional module metadata used by PowerShell.
|
||||
PrivateData = @{
|
||||
|
||||
PSData = @{
|
||||
|
||||
# Tags applied to this module. These help with module discovery in online galleries.
|
||||
# Tags = @()
|
||||
|
||||
# A URL to the license for this module.
|
||||
# LicenseUri = ''
|
||||
|
||||
# A URL to the main website for this project.
|
||||
ProjectUri = 'https://gitea.ocram85.com/OCram85/DroneHelper'
|
||||
|
||||
# A URL to an icon representing this module.
|
||||
# IconUri = ''
|
||||
|
||||
# ReleaseNotes of this module
|
||||
# ReleaseNotes = ''
|
||||
|
||||
# Prerelease string of this module
|
||||
# Prerelease = ''
|
||||
|
||||
# Flag to indicate whether the module requires explicit user acceptance for install/update/save
|
||||
# RequireLicenseAcceptance = false
|
||||
|
||||
# External dependent modules of this module
|
||||
# ExternalModuleDependencies = @()
|
||||
|
||||
} # End of PSData hashtable
|
||||
|
||||
} # End of PrivateData hashtable
|
||||
|
||||
# HelpInfo URI of this module
|
||||
# HelpInfoURI = ''
|
||||
|
||||
# Default prefix for commands exported from this module. Override the default prefix using
|
||||
# Import-Module -Prefix.
|
||||
# DefaultCommandPrefix = ''
|
||||
|
||||
}
|
81
src/FileLinter/Invoke-FileLinter.Tests.ps1
Normal file
81
src/FileLinter/Invoke-FileLinter.Tests.ps1
Normal file
@ -0,0 +1,81 @@
|
||||
BeforeAll {
|
||||
$Repo = Get-RepoPath
|
||||
Import-Module $Repo.Src.Manifest.Item.FullName -Force
|
||||
$MoveBackup = @{
|
||||
Path = $Repo.Build.FileLinterLogPath
|
||||
Destination = Join-Path -Path $Repo.Build.Path -ChildPath 'FileLinter.backup'
|
||||
}
|
||||
Move-Item @MoveBackup
|
||||
}
|
||||
|
||||
Describe 'Invoke-FileLinter' {
|
||||
Context 'Default tests' -Tag 'Default' {
|
||||
It 'Test Function' {
|
||||
{ Get-Command -Name 'Invoke-FileLinter' -Module $Repo.Artifact } | Should -Not -Throw
|
||||
}
|
||||
|
||||
It 'Test Help' {
|
||||
{ Get-Help -Name 'Invoke-FileLinter' } | Should -Not -Throw
|
||||
}
|
||||
|
||||
It 'Help Content' {
|
||||
$foo = Get-Help -Name 'Invoke-FileLinter'
|
||||
$foo.Synopsis.Length | Should -BeGreaterThan 5
|
||||
$foo.Description.Count | Should -BeGreaterOrEqual 1
|
||||
$foo.Description[0].Text.Length | Should -BeGreaterThan 5
|
||||
}
|
||||
}
|
||||
Context 'Coding tests' -Tag 'Unit' {
|
||||
# Mocking doesn't get executed. Switch to Integration test class to avoid duplicated output.
|
||||
BeforeEach {
|
||||
Mock 'Write-FailureStateFile' {
|
||||
Write-Debug 'Mocking function Write-FailureStateFile.'
|
||||
} -ModuleName 'DroneHelper'
|
||||
|
||||
Mock 'Write-ResultFile' {
|
||||
Write-Debug 'Mocking function Write-ResultFile.'
|
||||
} -ModuleName 'DroneHelper'
|
||||
}
|
||||
It 'Should throw' {
|
||||
#Mock 'Write-FailureStateFile' { Write-Debug 'Mocking Report generator' }
|
||||
#Mock 'Write-ResultFile' { Write-Debug 'Mocking function Write-ResultFile.' }
|
||||
{ Invoke-FileLinter -foo } | Should -Throw
|
||||
}
|
||||
It 'Should not throw' {
|
||||
#Mock 'Write-FailureStateFile' { Write-Debug 'Mocking Report generator' }
|
||||
#Mock 'Write-ResultFile' { Write-Debug 'Mocking function Write-ResultFile.' }
|
||||
{ Invoke-FileLinter } | Should -Not -Throw
|
||||
}
|
||||
|
||||
It 'Should have found files' {
|
||||
#Mock Write-FailureStateFile { Write-Debug 'Mocking Report generator' }
|
||||
#Mock 'Write-ResultFile' { Write-Debug 'Mocking function Write-ResultFile.' }
|
||||
$res = Invoke-FileLinter -PassThru
|
||||
$res.FilesCount | Should -Not -BeNullOrEmpty
|
||||
$res.FilesCount | Should -BeGreaterThan 0
|
||||
}
|
||||
|
||||
It 'Should run without linter issues' {
|
||||
#Mock 'Write-FailureStateFile' { Write-Debug 'Mocking Report generator' }
|
||||
#Mock 'Write-ResultFile' { Write-Debug 'Mocking function Write-ResultFile.' }
|
||||
$res = Invoke-FileLinter -PassThru
|
||||
$res.FailedCount | Should -Be 0
|
||||
}
|
||||
|
||||
It 'Should Sum up ' {
|
||||
#Mock 'Write-FailureStateFile' { Write-Debug 'Mocking Report generator' }
|
||||
#Mock 'Write-ResultFile' { Write-Debug 'Mocking function Write-ResultFile.' }
|
||||
$res = Invoke-FileLinter -PassThru
|
||||
$res.FailedCount | Should -Be 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AfterAll {
|
||||
$Repo = Get-RepoPath
|
||||
$RestoreBackup = @{
|
||||
Path = Join-Path -Path $Repo.Build.Path -ChildPath 'FileLinter.backup'
|
||||
Destination = $Repo.Build.FileLinterLogPath
|
||||
}
|
||||
Move-Item @RestoreBackup -Force
|
||||
}
|
115
src/FileLinter/Invoke-FileLinter.ps1
Normal file
115
src/FileLinter/Invoke-FileLinter.ps1
Normal file
@ -0,0 +1,115 @@
|
||||
function Invoke-FileLinter {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Runs the file linter for all src files found in current repository.
|
||||
|
||||
.DESCRIPTION
|
||||
Invoke-FileLinter runs the basic file tests and generates a report file for furher usage in the
|
||||
drone pipeline.
|
||||
|
||||
.INPUTS
|
||||
[None]
|
||||
|
||||
.OUTPUTS
|
||||
[DroneHelper.FileLinter.Report]
|
||||
|
||||
.EXAMPLE
|
||||
Invoke-FileLinter
|
||||
|
||||
.NOTES
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
[OutputType('DroneHelper.FileLinter.Report')]
|
||||
|
||||
param (
|
||||
[Parameter(Mandatory = $false)]
|
||||
[switch]$PassThru
|
||||
)
|
||||
|
||||
begin {
|
||||
}
|
||||
|
||||
process {
|
||||
$FileSet = @()
|
||||
$Repo = Get-RepoPath
|
||||
$RawFiles = (Get-ChildItem -Path $Repo.src.Path -Recurse -File).FullName
|
||||
Write-Debug -Message ('EXCLUDE Filter. {0}' -f $Env:EXCLUDE)
|
||||
if ($Env:EXCLUDE) {
|
||||
$Files = $RawFiles -notmatch $Env:EXCLUDE
|
||||
Write-Debug -Message ('Raw File List: {0} | Filtered Files: {1}' -f $RawFiles.Count, $Files.Count)
|
||||
}
|
||||
else {
|
||||
$Files = $RawFiles
|
||||
}
|
||||
foreach ($file in $Files) {
|
||||
Write-Verbose -Message ('Running FileLinter tests for: {0}' -f $file)
|
||||
$FileResults = [PSCustomObject]@{
|
||||
Name = $file
|
||||
FailedCount = 0
|
||||
Tests = [ordered]@{
|
||||
Encoding = (Test-FileEncoding -Path $file)
|
||||
BOM = (Test-FileBOM -Path $file)
|
||||
EOL = (Test-FileEOL -Path $file)
|
||||
EOF = (Test-FileEOF -Path $file)
|
||||
TAB = (Test-FileTab -Path $file)
|
||||
TailingWhite = (Test-FileTailingWhitespace -Path $file)
|
||||
}
|
||||
}
|
||||
Write-Verbose -Message ('Populating property FailedCount for current file.')
|
||||
foreach ($item in $FileResults.Tests.Keys.GetEnumerator()) {
|
||||
if (($FileResults.Tests.$item) -ne $true) {
|
||||
$FileResults.FailedCount++
|
||||
}
|
||||
}
|
||||
$FileSet += [PSCustomObject]$FileResults
|
||||
}
|
||||
$LinterReport = [PSCustomObject]@{
|
||||
Success = $null
|
||||
FilesCount = ($FileSet | Measure-Object).Count
|
||||
FailedCount = 0
|
||||
Files = $FileSet
|
||||
|
||||
}
|
||||
Write-Verbose -Message ('Populating total FailedCount property.')
|
||||
foreach ($i in $LinterReport.Files.FailedCount) {
|
||||
if ($i -ne 0) {
|
||||
$LinterReport.FailedCount = $LinterReport.FailedCount + $i
|
||||
}
|
||||
}
|
||||
if ($LinterReport.FailedCount -eq 0) {
|
||||
$LinterReport.Success = $true
|
||||
}
|
||||
else {
|
||||
$LinterReport.Success = $false
|
||||
}
|
||||
$LinterReport.PSObject.TypeNames.Insert(0, 'DroneHelper.FileLinter.Report')
|
||||
|
||||
$LinterReport.Files | Out-String | Write-Verbose -Verbose
|
||||
|
||||
$LinterReport | Format-Table -Property @(
|
||||
'Success',
|
||||
'FilesCount',
|
||||
'FailedCount'
|
||||
) | Out-String | Write-Verbose -Verbose
|
||||
|
||||
|
||||
$ResultParams = @{
|
||||
Type = 'FileLinter'
|
||||
Path = $Repo.Build.FileLinterLogPath
|
||||
InputObject = $LinterReport
|
||||
}
|
||||
Write-ResultFile @ResultParams
|
||||
|
||||
if (-not ($LinterReport.Success)) {
|
||||
Write-FailureStateFile -StepName 'FileLinter'
|
||||
throw 'FileLinter failed!'
|
||||
}
|
||||
}
|
||||
|
||||
end {
|
||||
if ($PassThru.IsPresent) {
|
||||
Write-Output $LinterReport
|
||||
}
|
||||
}
|
||||
}
|
37
src/FileLinter/Test-FileBOM.Tests.ps1
Normal file
37
src/FileLinter/Test-FileBOM.Tests.ps1
Normal file
@ -0,0 +1,37 @@
|
||||
BeforeAll {
|
||||
$Repo = Get-RepoPath
|
||||
Import-Module $Repo.Src.Manifest.Item.FullName -Force
|
||||
#$srcFile = Join-Path -Path $Repo.Src.Path -ChildPath 'FileLinter/Test-FileBOM.ps1'
|
||||
#. "$srcFile"
|
||||
}
|
||||
Describe 'Test-FileBOM' {
|
||||
Context 'Default tests' -Tag 'Default' {
|
||||
It 'Test Function' {
|
||||
{ Get-Command -Name 'Test-FileBOM' -Module $Repo.Artifact } | Should -Not -Throw
|
||||
}
|
||||
|
||||
It 'Test Help' {
|
||||
{ Get-Help -Name 'Test-FileBOM' } | Should -Not -Throw
|
||||
}
|
||||
|
||||
It 'Help Content' {
|
||||
$foo = Get-Help -Name 'Test-FileBOM'
|
||||
$foo.Synopsis.Length | Should -BeGreaterThan 5
|
||||
$foo.Description.Count | Should -BeGreaterOrEqual 1
|
||||
$foo.Description[0].Text.Length | Should -BeGreaterThan 5
|
||||
}
|
||||
}
|
||||
Context 'Unit tests' -Tag 'Unit' {
|
||||
It 'Should throw' {
|
||||
{ Test-FileBOM -foo } | Should -Throw
|
||||
}
|
||||
|
||||
It 'Should not throw' {
|
||||
{ Test-FileBOM -Path $Repo.Src.Manifest.Item.FullName } | Should -Not -Throw
|
||||
}
|
||||
|
||||
It 'Should return true' {
|
||||
Test-FileBOM -Path $Repo.Src.Manifest.Item.FullName | Should -Be $true
|
||||
}
|
||||
}
|
||||
}
|
61
src/FileLinter/Test-FileBOM.ps1
Normal file
61
src/FileLinter/Test-FileBOM.ps1
Normal file
@ -0,0 +1,61 @@
|
||||
function Test-FileBOM {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Tests given file if native utf8 w/o BOM is used. Returns false if BOM is present.
|
||||
|
||||
.DESCRIPTION
|
||||
This function is used to test for a valid encoding without BOM.
|
||||
|
||||
.PARAMETER Path
|
||||
Full or relative path to existing file.
|
||||
|
||||
.INPUTS
|
||||
[None]
|
||||
|
||||
.OUTPUTS
|
||||
[bool]
|
||||
|
||||
.EXAMPLE
|
||||
Test-FileBOM -Path './Testfile.txt'
|
||||
|
||||
.NOTES
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
[OutputType([bool])]
|
||||
|
||||
param (
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidateScript(
|
||||
{
|
||||
Test-Path -Path $_
|
||||
}
|
||||
)]
|
||||
[string]$Path
|
||||
)
|
||||
|
||||
begin {
|
||||
}
|
||||
|
||||
process {
|
||||
try {
|
||||
$contents = [byte[]]::new(3)
|
||||
$stream = [System.IO.File]::OpenRead($Path)
|
||||
$stream.Read($contents, 0, 3) | Out-Null
|
||||
$stream.Close()
|
||||
}
|
||||
catch {
|
||||
Write-Error -Message 'Could not read the given file!' -ErrorAction 'Stop'
|
||||
}
|
||||
Write-Debug -Message ('BOM Content was: {0}' -f ([System.BitConverter]::ToString($contents)))
|
||||
if ( $contents[0] -eq 0xEF -and $contents[1] -eq 0xBB -and $contents -eq 0xBF ) {
|
||||
Write-Output $false
|
||||
}
|
||||
else {
|
||||
Write-Output $true
|
||||
}
|
||||
}
|
||||
|
||||
end {
|
||||
}
|
||||
}
|
37
src/FileLinter/Test-FileEOF.Tests.ps1
Normal file
37
src/FileLinter/Test-FileEOF.Tests.ps1
Normal file
@ -0,0 +1,37 @@
|
||||
BeforeAll {
|
||||
$Repo = Get-RepoPath
|
||||
Import-Module $Repo.Src.Manifest.Item.FullName -Force
|
||||
#$srcFile = Join-Path -Path $Repo.Src.Path -ChildPath 'FileLinter/Test-FileEOF.ps1'
|
||||
#. "$srcFile"
|
||||
#$srcFile = Join-Path -Path $Repo.Src.Path -ChildPath 'FileLinter/Test-FileEOL.ps1'
|
||||
#. "$srcFile"
|
||||
}
|
||||
Describe 'Test-FileEOF' {
|
||||
Context 'Default tests' -Tag 'Default' {
|
||||
It 'Test Function' {
|
||||
{ Get-Command -Name 'Test-FileEOF' -Module $Repo.Artifact } | Should -Not -Throw
|
||||
}
|
||||
|
||||
It 'Test Help' {
|
||||
{ Get-Help -Name 'Test-FileEOF' } | Should -Not -Throw
|
||||
}
|
||||
|
||||
It 'Help Content' {
|
||||
$foo = Get-Help -Name 'Test-FileEOF'
|
||||
$foo.Synopsis.Length | Should -BeGreaterThan 5
|
||||
$foo.Description.Count | Should -BeGreaterOrEqual 1
|
||||
$foo.Description[0].Text.Length | Should -BeGreaterThan 5
|
||||
}
|
||||
}
|
||||
Context 'Coding tests' -Tag 'Unit' {
|
||||
It 'Should throw' {
|
||||
{ Test-FileEOF -foo } | Should -Throw
|
||||
}
|
||||
It 'Should not throw' {
|
||||
{ Test-FileEOF -Path $Repo.Src.Manifest.Item.FullName } | Should -Not -Throw
|
||||
}
|
||||
It 'Should be true' {
|
||||
Test-FileEOF -Path $Repo.Src.Manifest.Item.FullName | Should -Be $true
|
||||
}
|
||||
}
|
||||
}
|
56
src/FileLinter/Test-FileEOF.ps1
Normal file
56
src/FileLinter/Test-FileEOF.ps1
Normal file
@ -0,0 +1,56 @@
|
||||
function Test-FileEOF {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Returns false if EOF isn't an empty line.
|
||||
|
||||
.DESCRIPTION
|
||||
Test the given file against the EOF standard (final empty/blank line + CRLF) and returns true or false.
|
||||
|
||||
.PARAMETER Path
|
||||
Relative or full path to an existing file.
|
||||
|
||||
.INPUTS
|
||||
[none]
|
||||
|
||||
.OUTPUTS
|
||||
[bool]
|
||||
|
||||
.EXAMPLE
|
||||
Test-FileEOF -Path './testfile.txt'
|
||||
|
||||
.NOTES
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
[OutputType([bool])]
|
||||
|
||||
param (
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$Path
|
||||
)
|
||||
|
||||
begin {
|
||||
}
|
||||
|
||||
process {
|
||||
if (-not (Test-FileEOL -Path $Path)) {
|
||||
Write-Warning -Message ('The given file does not use CRLF! ({0})' -f $Path)
|
||||
Write-Output $false
|
||||
}
|
||||
$content = Get-Content -Path $Path -Raw -Encoding 'utf8'
|
||||
$lastLine = ($content -split "`r`n")[-1].Length
|
||||
# Test for multiple lines without content on EOF
|
||||
$perLine = ($content -split "`r`n")[-2].Length
|
||||
if (($lastLine -eq 0) -and ($perLine -ne 0)) {
|
||||
Write-Debug -Message ('EOF: LastLine {0}; PenultimateLine {1} -> true' -f $lastLine, $perLine)
|
||||
Write-Output $true
|
||||
}
|
||||
else {
|
||||
Write-Debug -Message ('EOF: LastLine {0}; PenultimateLine {1} -> false' -f $lastLine, $perLine)
|
||||
Write-Output $false
|
||||
}
|
||||
}
|
||||
|
||||
end {
|
||||
}
|
||||
}
|
38
src/FileLinter/Test-FileEOL.Tests.ps1
Normal file
38
src/FileLinter/Test-FileEOL.Tests.ps1
Normal file
@ -0,0 +1,38 @@
|
||||
BeforeAll {
|
||||
$Repo = Get-RepoPath
|
||||
Import-Module $Repo.Src.Manifest.Item.FullName -Force
|
||||
#$srcFile = Join-Path -Path $Repo.Src.Path -ChildPath 'FileLinter/Test-FileEOL.ps1'
|
||||
#. "$srcFile"
|
||||
}
|
||||
Describe 'Test-FileEOL' {
|
||||
Context 'Default tests' -Tag 'Default' {
|
||||
It 'Test Function' {
|
||||
{ Get-Command -Name 'Test-FileEOL' -Module $Repo.Artifact } | Should -Not -Throw
|
||||
}
|
||||
|
||||
It 'Test Help' {
|
||||
{ Get-Help -Name 'Test-FileEOL' } | Should -Not -Throw
|
||||
}
|
||||
|
||||
It 'Help Content' {
|
||||
$foo = Get-Help -Name 'Test-FileEOL'
|
||||
$foo.Synopsis.Length | Should -BeGreaterThan 5
|
||||
$foo.Description.Count | Should -BeGreaterOrEqual 1
|
||||
$foo.Description[0].Text.Length | Should -BeGreaterThan 5
|
||||
}
|
||||
}
|
||||
Context 'Coding tests' -Tag 'Unit' {
|
||||
It 'Should throw' {
|
||||
{ Test-FileEOL -foo } | Should -Throw
|
||||
}
|
||||
It 'Should not throw' {
|
||||
{ Test-FileEOL -Path $Repo.Src.Manifest.Item.FullName } | Should -Not -Throw
|
||||
}
|
||||
It 'Should be true' {
|
||||
Test-FileEOL -Path $Repo.Src.Manifest.Item.FullName | Should -Be $true
|
||||
}
|
||||
It 'Should be false' {
|
||||
Test-FileEOL -Path $Repo.Changelog.Path | Should -Be $false
|
||||
}
|
||||
}
|
||||
}
|
61
src/FileLinter/Test-FileEOL.ps1
Normal file
61
src/FileLinter/Test-FileEOL.ps1
Normal file
@ -0,0 +1,61 @@
|
||||
function Test-FileEOL {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Returns false if EOL isn't CRLF
|
||||
|
||||
.DESCRIPTION
|
||||
Tests given file against valid EOL. Returns true if CRLF is used.
|
||||
|
||||
.PARAMETER Path
|
||||
Relative or full path to an existing file.
|
||||
|
||||
.INPUTS
|
||||
[None]
|
||||
|
||||
.OUTPUTS
|
||||
[bool]
|
||||
|
||||
.EXAMPLE
|
||||
Test-FileEOL -Path './TestFile.txt'
|
||||
|
||||
.NOTES
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
[OutputType([bool])]
|
||||
|
||||
param (
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidateScript(
|
||||
{
|
||||
Test-Path -Path $_
|
||||
}
|
||||
)]
|
||||
[string]$Path
|
||||
)
|
||||
|
||||
begin {
|
||||
}
|
||||
|
||||
process {
|
||||
$content = Get-Content -Path $Path -Raw -Encoding 'utf8'
|
||||
$CRLFCount = ([regex]::Matches($content, "`r`n$")).Count
|
||||
$LFCount = ([regex]::Matches($content, "`n$")).Count
|
||||
|
||||
if ($CRLFCount -eq $LFCount) {
|
||||
Write-Debug -Message 'EOL: CRLFCount = LFCount -> true'
|
||||
Write-Output $true
|
||||
}
|
||||
elseif ($CRLFCount -gt $LFCount) {
|
||||
Write-Debug -Message 'EOL: CRLFCount > LFCount -> false'
|
||||
Write-Output $false
|
||||
}
|
||||
elseif ($LFCount -gt $CRLFCount) {
|
||||
Write-Debug -Message 'EOL: CRLFCount < LFCount -> false'
|
||||
Write-Output $false
|
||||
}
|
||||
}
|
||||
|
||||
end {
|
||||
}
|
||||
}
|
41
src/FileLinter/Test-FileEncoding.Tests.ps1
Normal file
41
src/FileLinter/Test-FileEncoding.Tests.ps1
Normal file
@ -0,0 +1,41 @@
|
||||
BeforeAll {
|
||||
$Repo = Get-RepoPath
|
||||
Import-Module $Repo.Src.Manifest.Item.FullName -Force
|
||||
#$srcFile = Join-Path -Path $Repo.Src.Path -ChildPath 'FileLinter/Test-FileEncoding.ps1'
|
||||
#. "$srcFile"
|
||||
}
|
||||
Describe 'Test-FileEncoding' {
|
||||
Context 'Default tests' -Tag 'Default' {
|
||||
It 'Test Function' {
|
||||
{ Get-Command -Name 'Test-FileEncoding' -Module $Repo.Artifact } | Should -Not -Throw
|
||||
}
|
||||
|
||||
It 'Test Help' {
|
||||
{ Get-Help -Name 'Test-FileEncoding' } | Should -Not -Throw
|
||||
}
|
||||
|
||||
It 'Help Content' {
|
||||
$foo = Get-Help -Name 'Test-FileEncoding'
|
||||
$foo.Synopsis.Length | Should -BeGreaterThan 5
|
||||
$foo.Description.Count | Should -BeGreaterOrEqual 1
|
||||
$foo.Description[0].Text.Length | Should -BeGreaterThan 5
|
||||
}
|
||||
}
|
||||
Context 'Coding tests' -Tag 'Unit' {
|
||||
It 'Should throw' {
|
||||
{ Test-FileEncoding -foo } | Should -Throw
|
||||
}
|
||||
It 'Should not throw' {
|
||||
{ Test-FileEncoding -Path $Repo.Src.Manifest.Item.FullName } | Should -Not -Throw
|
||||
}
|
||||
|
||||
It 'Should return true' {
|
||||
{ Test-FileEncoding -Path $Repo.Src.Manifest.Item.FullName } | Should -Be $true
|
||||
}
|
||||
It 'UTF-8 test file should return true' {
|
||||
Test-FileEncoding -Path (
|
||||
Join-Path -Path $repo.Resources.Path -ChildPath 'TestData/encodingTest.txt'
|
||||
) | Should -BeTrue
|
||||
}
|
||||
}
|
||||
}
|
73
src/FileLinter/Test-FileEncoding.ps1
Normal file
73
src/FileLinter/Test-FileEncoding.ps1
Normal file
@ -0,0 +1,73 @@
|
||||
function Test-FileEncoding {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Returns true if the given file is written in a valid encoding
|
||||
|
||||
.DESCRIPTION
|
||||
Test the given file against the encoding regex and returns true or false
|
||||
|
||||
.PARAMETER Path
|
||||
Relative or full path to an existing file.
|
||||
|
||||
.PARAMETER Encoding
|
||||
Optional custom encoding regex string. Default is (utf8|ascii|xml).
|
||||
|
||||
.INPUTS
|
||||
[none]
|
||||
|
||||
.OUTPUTS
|
||||
[bool]
|
||||
|
||||
.EXAMPLE
|
||||
Test-FileEncoding -Path './testfile.txt'
|
||||
|
||||
.NOTES
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
|
||||
'PSAvoidUsingInvokeExpression',
|
||||
'',
|
||||
Justification = 'static input without user manipulation'
|
||||
)]
|
||||
[OutputType([bool])]
|
||||
|
||||
param (
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidateScript(
|
||||
{
|
||||
Test-Path -Path $_
|
||||
}
|
||||
)]
|
||||
[string]$Path,
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[string]$Encoding = '(utf8|utf-8|ascii|xml)'
|
||||
)
|
||||
|
||||
begin {
|
||||
}
|
||||
|
||||
process {
|
||||
try {
|
||||
Get-Command -Name 'file' -ErrorAction 'Stop' | Out-Null
|
||||
}
|
||||
catch {
|
||||
Write-Error -Message "Could not find command called 'file'!" -ErrorAction 'Stop'
|
||||
}
|
||||
$Res = Invoke-Expression -Command ("file '{0}' " -f $Path)
|
||||
# Remove the file from matching. Use the latest array element if split doesn't work.
|
||||
$ParsedResult = ($Res -split ':')[-1]
|
||||
Write-Debug -Message ('Encoding: Raw file output {0}' -f $Res)
|
||||
Write-Debug -Message ('Parsed match string: {0}' -f $ParsedResult)
|
||||
if ($ParsedResult -match $Encoding) {
|
||||
Write-Output $true
|
||||
}
|
||||
else {
|
||||
Write-Output $false
|
||||
}
|
||||
}
|
||||
|
||||
end {
|
||||
}
|
||||
}
|
36
src/FileLinter/Test-FileTab.Tests.ps1
Normal file
36
src/FileLinter/Test-FileTab.Tests.ps1
Normal file
@ -0,0 +1,36 @@
|
||||
BeforeAll {
|
||||
$Repo = Get-RepoPath
|
||||
Import-Module $Repo.Src.Manifest.Item.FullName -Force
|
||||
#$srcFile = Join-Path -Path $Repo.Src.Path -ChildPath 'FileLinter/Test-FileTab.ps1'
|
||||
#. "$srcFile"
|
||||
}
|
||||
Describe 'Test-FileTab' {
|
||||
Context 'Default tests' -Tag 'Default' {
|
||||
It 'Test Function' {
|
||||
{ Get-Command -Name 'Test-FileTab' -Module $Repo.Artifact } | Should -Not -Throw
|
||||
}
|
||||
|
||||
It 'Test Help' {
|
||||
{ Get-Help -Name 'Test-FileTab' } | Should -Not -Throw
|
||||
}
|
||||
|
||||
It 'Help Content' {
|
||||
$foo = Get-Help -Name 'Test-FileTab'
|
||||
$foo.Synopsis.Length | Should -BeGreaterThan 5
|
||||
$foo.Description.Count | Should -BeGreaterOrEqual 1
|
||||
$foo.Description[0].Text.Length | Should -BeGreaterThan 5
|
||||
}
|
||||
}
|
||||
Context 'Coding tests' -Tag 'Unit' {
|
||||
It 'Should throw' {
|
||||
{ Test-FileTab -foo } | Should -Throw
|
||||
}
|
||||
It 'Should not throw' {
|
||||
{ Test-FileTab -Path $Repo.Src.Manifest.Item.FullName } | Should -Not -Throw
|
||||
}
|
||||
|
||||
It 'Should be true' {
|
||||
Test-FileTab -Path $Repo.Src.Manifest.Item.FullName | Should -Be $true
|
||||
}
|
||||
}
|
||||
}
|
56
src/FileLinter/Test-FileTab.ps1
Normal file
56
src/FileLinter/Test-FileTab.ps1
Normal file
@ -0,0 +1,56 @@
|
||||
function Test-FileTab {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Returns false if tab char is used in file.
|
||||
|
||||
.DESCRIPTION
|
||||
Test the given file if tabs are used. Returns false if any tabs were found.
|
||||
|
||||
.PARAMETER Path
|
||||
elative or full path to an existing file.
|
||||
|
||||
.INPUTS
|
||||
[none]
|
||||
|
||||
.OUTPUTS
|
||||
[bool]
|
||||
|
||||
.EXAMPLE
|
||||
Test-FileTab -Path './testfile.txt'
|
||||
|
||||
.NOTES
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
[OutputType([bool])]
|
||||
|
||||
param (
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidateScript(
|
||||
{
|
||||
Test-Path -Path $_
|
||||
}
|
||||
)]
|
||||
[string]$Path
|
||||
)
|
||||
|
||||
begin {
|
||||
}
|
||||
|
||||
process {
|
||||
$content = Get-Content -Path $Path -Raw -Encoding 'utf8'
|
||||
$Tabs = ([regex]::Matches($content, "`t")).Count
|
||||
|
||||
if ($Tabs -ne 0 ) {
|
||||
Write-Debug -Message ('Tabs: {0} -> false' -f $Tabs)
|
||||
Write-Output $false
|
||||
}
|
||||
else {
|
||||
Write-Debug -Message ('Tabs: {0} -> true' -f $Tabs)
|
||||
Write-Output $true
|
||||
}
|
||||
}
|
||||
|
||||
end {
|
||||
}
|
||||
}
|
36
src/FileLinter/Test-FileTailingWhitespace.Tests.ps1
Normal file
36
src/FileLinter/Test-FileTailingWhitespace.Tests.ps1
Normal file
@ -0,0 +1,36 @@
|
||||
BeforeAll {
|
||||
$Repo = Get-RepoPath
|
||||
Import-Module $Repo.Src.Manifest.Item.FullName -Force
|
||||
#$srcFile = Join-Path -Path $Repo.Src.Path -ChildPath 'FileLinter/Test-FileTailingWhitespace.ps1'
|
||||
#. "$srcFile"
|
||||
}
|
||||
Describe 'Test-FileTailingWhitespace' {
|
||||
Context 'Default tests' -Tag 'Default' {
|
||||
It 'Test Function' {
|
||||
{ Get-Command -Name 'Test-FileTailingWhitespace' -Module $Repo.Artifact } | Should -Not -Throw
|
||||
}
|
||||
|
||||
It 'Test Help' {
|
||||
{ Get-Help -Name 'Test-FileTailingWhitespace' } | Should -Not -Throw
|
||||
}
|
||||
|
||||
It 'Help Content' {
|
||||
$foo = Get-Help -Name 'Test-FileTailingWhitespace'
|
||||
$foo.Synopsis.Length | Should -BeGreaterThan 5
|
||||
$foo.Description.Count | Should -BeGreaterOrEqual 1
|
||||
$foo.Description[0].Text.Length | Should -BeGreaterThan 5
|
||||
}
|
||||
}
|
||||
Context 'Coding tests' -Tag 'Unit' {
|
||||
It 'Should throw' {
|
||||
{ Test-FileTailingWhitespace -foo } | Should -Throw
|
||||
}
|
||||
It 'Should not throw' {
|
||||
{ Test-FileTailingWhitespace -Path $Repo.Src.Manifest.Item.FullName } | Should -Not -Throw
|
||||
}
|
||||
|
||||
It 'Should be true' {
|
||||
Test-FileTailingWhitespace -Path $Repo.Src.Manifest.Item.FullName | Should -Be $true
|
||||
}
|
||||
}
|
||||
}
|
62
src/FileLinter/Test-FileTailingWhitespace.ps1
Normal file
62
src/FileLinter/Test-FileTailingWhitespace.ps1
Normal file
@ -0,0 +1,62 @@
|
||||
function Test-FileTailingWhitespace {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Returns false if there are any tailing whitespace in lines.
|
||||
|
||||
.DESCRIPTION
|
||||
Tests the given file for tailing whitespace. Returns true if not found.
|
||||
|
||||
.PARAMETER Path
|
||||
Relative or full path to an existing file.
|
||||
|
||||
.INPUTS
|
||||
[none]
|
||||
|
||||
.OUTPUTS
|
||||
[bool]
|
||||
|
||||
.EXAMPLE
|
||||
Test-FileTailingWhitespace.ps1 -Path './testfile.txt'
|
||||
|
||||
.NOTES
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
[OutputType([Bool])]
|
||||
|
||||
param (
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidateScript(
|
||||
{
|
||||
Test-Path -Path $_
|
||||
}
|
||||
)]
|
||||
[string]$Path
|
||||
)
|
||||
|
||||
begin {
|
||||
}
|
||||
|
||||
process {
|
||||
$content = Get-Content -Path $Path -Encoding 'utf8'
|
||||
$WhiteSpace = 0
|
||||
foreach ($line in $content) {
|
||||
$c = ([regex]::Matches($line, "\s+$")).Count
|
||||
if ( $c -gt 0 ) {
|
||||
$WhiteSpace++
|
||||
}
|
||||
}
|
||||
|
||||
if ($WhiteSpace -ne 0 ) {
|
||||
Write-Debug -Message ('WhiteSpace: {0} -> false' -f $WhiteSpace)
|
||||
Write-Output $false
|
||||
}
|
||||
else {
|
||||
Write-Debug -Message ('WhiteSpace: {0} -> true' -f $WhiteSpace)
|
||||
Write-Output $true
|
||||
}
|
||||
}
|
||||
|
||||
end {
|
||||
}
|
||||
}
|
1
src/Formats/.gitkeep
Normal file
1
src/Formats/.gitkeep
Normal file
@ -0,0 +1 @@
|
||||
git placeholder file
|
21
src/Helper/Get-RepoPath.Tests.ps1
Normal file
21
src/Helper/Get-RepoPath.Tests.ps1
Normal file
@ -0,0 +1,21 @@
|
||||
BeforeAll {
|
||||
$Repo = Get-RepoPath
|
||||
Import-Module $Repo.Src.Manifest.Item.FullName -Force
|
||||
}
|
||||
Describe 'Get-RepoPath' {
|
||||
Context 'Default tests' -Tag 'Default' {
|
||||
It 'Test Function' {
|
||||
{ Get-Command -Name 'Get-RepoPath' -Module $Repo.Artifact } | Should -Not -Throw
|
||||
}
|
||||
|
||||
It 'Test Help' {
|
||||
{ Get-Help -Name 'Get-RepoPath' } | Should -Not -Throw
|
||||
}
|
||||
It 'Help Content' {
|
||||
$foo = Get-Help -Name 'Get-RepoPath'
|
||||
$foo.Synopsis.Length | Should -BeGreaterThan 5
|
||||
$foo.Description.Count | Should -BeGreaterOrEqual 1
|
||||
$foo.Description[0].Text.Length | Should -BeGreaterThan 5
|
||||
}
|
||||
}
|
||||
}
|
167
src/Helper/Get-RepoPath.ps1
Normal file
167
src/Helper/Get-RepoPath.ps1
Normal file
@ -0,0 +1,167 @@
|
||||
function Get-RepoPath {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Updates the module manifest file fields to prepare the new build.
|
||||
|
||||
.DESCRIPTION
|
||||
Replaces the version fields in the manifest file. Uses Drone env vars populated by pushed tags.
|
||||
|
||||
.Parameter SubPath
|
||||
An optional string array of sub directories relative to the root.
|
||||
|
||||
.INPUTS
|
||||
[None] No pipeline input.
|
||||
|
||||
.OUTPUTS
|
||||
[DroneHelper.Repo.Path] Returns a folder structured like object with relevant full paths.s
|
||||
|
||||
.EXAMPLE
|
||||
Import-Module -Name DroneHelper; Get-RepoPath
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
[OutputType('DroneHelper.Repo.Path')]
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
|
||||
'PSUseConsistentWhitespace',
|
||||
'',
|
||||
Justification = 'Hashtable bug in ScriptAnalyzer 1.19.1'
|
||||
)]
|
||||
param (
|
||||
[Parameter(Mandatory = $false)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[String[]]$SubPath
|
||||
)
|
||||
|
||||
process {
|
||||
$root = Split-Path -Path (Get-GitDirectory)
|
||||
|
||||
$BaseName = Get-Item -Path ('{0}/src/*.psd1' -f $root) | Select-Object -ExpandProperty 'BaseName'
|
||||
|
||||
$failureLogPath = Join-Path -Path $root -ChildPath 'failure.log'
|
||||
|
||||
# *.psd1 related
|
||||
$manifestPath = Join-Path -Path $root -ChildPath 'src/*.psd1'
|
||||
$manifest = Get-Item -Path $manifestPath
|
||||
|
||||
# *.psm1 related
|
||||
$scriptModulePath = Join-Path -Path $root -ChildPath 'src/*.psm1'
|
||||
$scriptModule = Get-Item -Path $scriptModulePath
|
||||
|
||||
# Subdir related
|
||||
$srcPath = Join-Path -Path $root -ChildPath 'src'
|
||||
$binPath = Join-Path -Path $root -ChildPath 'bin'
|
||||
$buildPath = Join-Path -Path $root -ChildPath 'build'
|
||||
$resourcePath = Join-Path -Path $root -ChildPath 'resources'
|
||||
|
||||
# bin + build artifact related
|
||||
$mergedScriptModulePath = Join-Path -Path $binPath -ChildPath $scriptModule.Name
|
||||
|
||||
$artifactName = '{0}.zip' -f $BaseName
|
||||
$artifactPath = Join-Path -Path $binPath -ChildPath $artifactName
|
||||
$expandPath = Join-Path -Path $binPath -ChildPath $BaseName
|
||||
|
||||
# iteration through the optional sub paths
|
||||
$formatPath = Join-Path -Path $srcPath -ChildPath 'Formats/'
|
||||
$cachePath = Join-Path -Path $srcPath -ChildPath 'Cache/'
|
||||
|
||||
$docsPath = Join-Path -Path $root -ChildPath 'docs'
|
||||
$modulePagePath = Join-Path -Path $docsPath -ChildPath 'README.md'
|
||||
$docsMarkdownFilter = Join-Path -Path $docsPath -ChildPath '*.md'
|
||||
|
||||
$subDir = @{}
|
||||
foreach ($dir in $SubPath) {
|
||||
$subDir.$dir = Join-Path -Path $root -ChildPath $dir
|
||||
}
|
||||
|
||||
$changelogPath = Join-Path -Path $root -ChildPath 'CHANGELOG.md'
|
||||
$changelogExits = Test-Path -Path $changelogPath
|
||||
|
||||
$ps1Filter = Join-Path -Path $srcPath -ChildPath '*.ps1'
|
||||
|
||||
$pesterLogPath = Join-Path -Path $buildPath -ChildPath 'Pester-Results.log'
|
||||
$scriptAnalyzerLogPath = Join-Path -Path $buildPath -ChildPath 'ScriptAnalyzer-Results.log'
|
||||
$fileLinterLogPath = Join-Path -Path $buildPath -ChildPath 'FileLinter-Results.log'
|
||||
|
||||
$scriptAnalyzerSettingsPath = Join-Path -Path $resourcePath -ChildPath 'PSScriptAnalyzerSettings.psd1'
|
||||
|
||||
# DroneHelper Module specific
|
||||
|
||||
$droneModuleBase = $MyInvocation.MyCommand.Module.ModuleBase
|
||||
$PathParams = @{
|
||||
Path = $droneModuleBase
|
||||
ChildPath = 'Rules/PSScriptAnalyzerSettings.psd1'
|
||||
}
|
||||
$droneAnalyzerDefaultPath = Join-Path @PathParams
|
||||
|
||||
if ($changelogExits) {
|
||||
$changelog = Get-Item -Path $changelogPath
|
||||
}
|
||||
else {
|
||||
$changelog = $null
|
||||
}
|
||||
|
||||
$Path = [PSCustomObject]@{
|
||||
Artifact = $BaseName
|
||||
Root = $root
|
||||
|
||||
Src = [PSCustomObject]@{
|
||||
Path = $srcPath
|
||||
Manifest = [PSCustomObject] @{
|
||||
Path = $manifestPath
|
||||
Item = $manifest
|
||||
}
|
||||
ScriptModule = [PSCustomObject]@{
|
||||
Path = $scriptModulePath
|
||||
Item = $scriptModule
|
||||
}
|
||||
Formats = [PSCustomObject]@{
|
||||
Path = $formatPath
|
||||
Exists = Test-Path -Path $formatPath
|
||||
}
|
||||
Cache = [PSCustomObject]@{
|
||||
Path = $cachePath
|
||||
Exists = Test-Path -Path $cachePath
|
||||
}
|
||||
PS1Filter = $ps1Filter
|
||||
}
|
||||
Bin = [PSCustomObject]@{
|
||||
Path = $binPath
|
||||
ScriptModuleName = $mergedScriptModulePath
|
||||
ArtifactName = $artifactName
|
||||
ArtifactPath = $artifactPath
|
||||
ExpandPath = $expandPath
|
||||
|
||||
}
|
||||
Build = [PSCustomObject]@{
|
||||
Path = $buildPath
|
||||
PesterLogPath = $pesterLogPath
|
||||
ScriptAnalyzerLogPath = $scriptAnalyzerLogPath
|
||||
FileLinterLogPath = $fileLinterLogPath
|
||||
}
|
||||
Changelog = [PSCustomObject]@{
|
||||
Path = $changelogPath
|
||||
Exists = $changelogExits
|
||||
Item = $changelog
|
||||
}
|
||||
Docs = [PSCustomObject]@{
|
||||
Path = $docsPath
|
||||
ModulePagePath = $modulePagePath
|
||||
MarkdownFilter = $docsMarkdownFilter
|
||||
}
|
||||
DroneHelper = [PSCustomObject]@{
|
||||
ModuleBase = $MyInvocation.MyCommand.Module.ModuleBase
|
||||
ScriptAnalyzerDefaultsPath = $droneAnalyzerDefaultPath
|
||||
}
|
||||
Resources = [PSCustomObject]@{
|
||||
Path = $resourcePath
|
||||
ScriptAnalyzerSettingsPath = $scriptAnalyzerSettingsPath
|
||||
ScriptAnalyzerSettingsExist = Test-Path -Path $scriptAnalyzerSettingsPath
|
||||
|
||||
}
|
||||
FailureLogPath = $failureLogPath
|
||||
SubDir = $subDir
|
||||
}
|
||||
$Path.PSObject.TypeNames.Insert(0, 'DroneHelper.Repo.Path')
|
||||
Write-Output -InputObject $Path
|
||||
}
|
||||
|
||||
}
|
21
src/Helper/Set-EOL.Tests.ps1
Normal file
21
src/Helper/Set-EOL.Tests.ps1
Normal file
@ -0,0 +1,21 @@
|
||||
BeforeAll {
|
||||
$Repo = Get-RepoPath
|
||||
Import-Module $Repo.Src.Manifest.Item.FullName -Force
|
||||
}
|
||||
Describe 'Set-EOL' {
|
||||
Context 'Default tests' -Tag 'Default' {
|
||||
It 'Test Function' {
|
||||
{ Get-Command -Name 'Set-EOL' -Module $Repo.Artifact } | Should -Not -Throw
|
||||
}
|
||||
|
||||
It 'Test Help' {
|
||||
{ Get-Help -Name 'Set-EOL' } | Should -Not -Throw
|
||||
}
|
||||
It 'Help Content' {
|
||||
$foo = Get-Help -Name 'Set-EOL'
|
||||
$foo.Synopsis.Length | Should -BeGreaterThan 5
|
||||
$foo.Description.Count | Should -BeGreaterOrEqual 1
|
||||
$foo.Description[0].Text.Length | Should -BeGreaterThan 5
|
||||
}
|
||||
}
|
||||
}
|
59
src/Helper/Set-EOL.ps1
Normal file
59
src/Helper/Set-EOL.ps1
Normal file
@ -0,0 +1,59 @@
|
||||
function Set-EOL {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Helper function to set the EOL sequence to LF or CRLF.
|
||||
|
||||
.DESCRIPTION
|
||||
Helper for changing the EOL independent to the current OS defaults.
|
||||
|
||||
.PARAMETER Style
|
||||
Optional style parameter for `unix` or `win.`. Default is `unix`.
|
||||
|
||||
.PARAMETER Path
|
||||
Mandatory path for target file.
|
||||
|
||||
.INPUTS
|
||||
[None] No pipeline input.
|
||||
|
||||
.OUTPUTS
|
||||
[DroneHelper.Repo.Path] Returns a folder structured like object with relevant full paths.s
|
||||
|
||||
.EXAMPLE
|
||||
Import-Module -Name DroneHelper; Set-EOL -Path './Readme.md'
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
|
||||
'PSUseShouldProcessForStateChangingFunctions',
|
||||
'',
|
||||
Justification = 'system state does not change permanent in temp build clients.'
|
||||
)]
|
||||
param (
|
||||
[Parameter(Mandatory = $false)]
|
||||
[ValidateSet('unix', 'win')]
|
||||
[String]$Style = 'unix',
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[System.IO.FileInfo]$Path
|
||||
)
|
||||
|
||||
process {
|
||||
if (!(Test-Path $Path.FullName)) {
|
||||
Write-Error -Message ('{0} not found!' -f $Path.FullName) -ErrorAction Stop
|
||||
}
|
||||
switch ($Style) {
|
||||
'unix' {
|
||||
$eol = "`n"
|
||||
Write-Verbose -Message ('Reading {0}' -f $Path.FullName)
|
||||
$text = [IO.File]::ReadAllText($Path.FullName) -replace "`r`n", $eol
|
||||
Write-Debug -Message $text
|
||||
}
|
||||
'win' {
|
||||
$eol = "`r`n"
|
||||
$text = [IO.File]::ReadAllText($Path.FullName) -replace "`n", $eol
|
||||
}
|
||||
}
|
||||
Write-Verbose -Message ("Writing back {0}" -f $Path.FullName)
|
||||
[IO.File]::WriteAllText($Path.FullName, $text)
|
||||
|
||||
}
|
||||
}
|
6
src/ModuleRoot.psm1
Normal file
6
src/ModuleRoot.psm1
Normal file
@ -0,0 +1,6 @@
|
||||
# Get all child items in the Script path and exclude the Deploy script (if present.)
|
||||
$Functions = Get-ChildItem -Path $PSScriptRoot\*.ps1 -Recurse | Where-Object { $_.BaseName -notmatch '.Tests' }
|
||||
|
||||
ForEach ($Item in $Functions) {
|
||||
. $Item.FullName
|
||||
}
|
41
src/PRComment/Send-PRComment.Tests.ps1
Normal file
41
src/PRComment/Send-PRComment.Tests.ps1
Normal file
@ -0,0 +1,41 @@
|
||||
BeforeAll {
|
||||
$Repo = Get-RepoPath
|
||||
Import-Module $Repo.Src.Manifest.Item.FullName -Force
|
||||
}
|
||||
Describe 'Send-PRComment' {
|
||||
Context 'Default tests' -Tag 'Default' {
|
||||
It 'Test Function' {
|
||||
{ Get-Command -Name 'Send-PRComment' -Module $Repo.Artifact } | Should -Not -Throw
|
||||
}
|
||||
|
||||
It 'Test Help' {
|
||||
{ Get-Help -Name 'Send-PRComment' } | Should -Not -Throw
|
||||
}
|
||||
|
||||
It 'Help Content' {
|
||||
$foo = Get-Help -Name 'Send-PRComment'
|
||||
$foo.Synopsis.Length | Should -BeGreaterThan 5
|
||||
$foo.Description.Count | Should -BeGreaterOrEqual 1
|
||||
$foo.Description[0].Text.Length | Should -BeGreaterThan 5
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Unit tests' -Tag 'Unit' {
|
||||
It 'Should throw' {
|
||||
{ Send-PRComment -foo } | Should -Throw
|
||||
}
|
||||
#
|
||||
#It 'Should not throw' {
|
||||
#Mock 'FunctionName' -ModuleName $Repo.Artifact {}
|
||||
# { Send-PRComment } | Should -Not -Throw
|
||||
#}
|
||||
}
|
||||
|
||||
<#
|
||||
Context 'Integration tests' -Tag 'Integration' {
|
||||
It 'Real world example' {
|
||||
{ Send-PRComment } | Should -Should -Be $null
|
||||
}
|
||||
}
|
||||
#>
|
||||
}
|
173
src/PRComment/Send-PRComment.ps1
Normal file
173
src/PRComment/Send-PRComment.ps1
Normal file
@ -0,0 +1,173 @@
|
||||
function Send-PRComment {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Sends build report as Gitea PR comment.
|
||||
|
||||
.DESCRIPTION
|
||||
Send-PRComment is used to report the build details from drone.io pipeline.
|
||||
|
||||
.PARAMETER Mode
|
||||
Sets the report mode. Default is 'Renew'. This mode deletes the old pr comments and creates a new onw.
|
||||
Also available:
|
||||
- 'Add' -> simply adds new pr comments.
|
||||
- 'Edit' -> Edits the last known pr comment. Doesn't clean old ones.
|
||||
|
||||
.INPUTS
|
||||
[None].
|
||||
|
||||
.OUTPUTS
|
||||
[None]
|
||||
|
||||
.EXAMPLE
|
||||
Send-PRComment
|
||||
Depends on Drone.IO injected environment vars. Doesn't work locally on dev systems.
|
||||
.NOTES
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
#[OutputType([string])]
|
||||
param (
|
||||
[Parameter(Mandatory = $false, HelpMessage = 'HelpMessage')]
|
||||
[ValidateSet('Add', 'Edit', 'Renew')]
|
||||
[string]$Mode = 'Renew'
|
||||
)
|
||||
|
||||
begin {
|
||||
}
|
||||
|
||||
process {
|
||||
$Repo = Get-RepoPath
|
||||
$Workspace = $Repo.Root
|
||||
Write-Debug -Message ('Workspace: {0}' -f $Workspace)
|
||||
$PRCommentFile = Join-Path -Path $Workspace -ChildPath 'pr_comment.log'
|
||||
Write-Debug -Message ('PRCommentFile: {0}' -f $PRCommentFile)
|
||||
$PipelineStateFile = Join-Path -Path $Workspace -ChildPath 'failure.log'
|
||||
Write-Debug -Message ('PipelineStateFile: {0}' -f $PipelineStateFile)
|
||||
|
||||
Write-Debug -Message ('CUSTOM_PIPELINE_STATE: {0}' -f $Env:CUSTOM_PIPELINE_STATE)
|
||||
if ($Env:CUSTOM_PIPELINE_STATE -eq $true) {
|
||||
if (Test-Path $PipelineStateFile) {
|
||||
Write-Debug -Message ('Setting custom pipeline status to failed')
|
||||
$PipelineState = 'failed'
|
||||
}
|
||||
else {
|
||||
Write-Debug -Message ('Setting custom pipeline status to success')
|
||||
$PipelineState = 'success'
|
||||
}
|
||||
}
|
||||
else {
|
||||
Write-Debug -Message ('Setting global drone status {0}' -f $Env:DRONE_BUILD_STATUS)
|
||||
$PipelineState = $Env:DRONE_BUILD_STATUS
|
||||
}
|
||||
|
||||
if ($Env:GITEA_BASE) {
|
||||
$GiteaBase = $Env:GITEA_BASE
|
||||
}
|
||||
else {
|
||||
$GiteaBase = 'https://gitea.ocram85.com'
|
||||
}
|
||||
|
||||
$APIHeaders = @{
|
||||
accept = 'application/json'
|
||||
'Content-Type' = 'application/json'
|
||||
}
|
||||
|
||||
# Can be used with POST method to add new comment. Used with GET method returns all comments.
|
||||
$CommentAPICall = ('{0}/api/v1/repos/{1}/{2}/issues/{3}/comments?access_token={4}' -f
|
||||
$GiteaBase,
|
||||
$Env:DRONE_REPO_OWNER,
|
||||
$Env:DRONE_REPO_NAME,
|
||||
$Env:DRONE_PULL_REQUEST,
|
||||
$Env:GITEA_TOKEN
|
||||
)
|
||||
|
||||
# Update Comment API endpoint: 0 - GiteaBase, 1 - Owner, 2- Repo, 3 - PR, 4 - Token
|
||||
# Method Delete - removes the given comment. Patch - updates the given comment.
|
||||
$UpdateAPICall = '{0}/api/v1/repos/{1}/{2}/issues/comments/{3}?access_token={4}'
|
||||
|
||||
|
||||
if ($Mode -eq 'Renew') {
|
||||
$Comments = Invoke-RestMethod -Method 'Get' -Headers $APIHeaders -Uri $CommentAPICall
|
||||
$DroneComments = $Comments | Where-Object {
|
||||
$_.user.login -eq 'drone'
|
||||
} | Select-Object -ExpandProperty 'id'
|
||||
Write-Debug -Message ('Found Drone comments: {0}.' -f ($DroneComments -join ', '))
|
||||
foreach ($id in $DroneComments) {
|
||||
$ExtAPI = $UpdateAPICall -f @(
|
||||
$GiteaBase,
|
||||
$Env:DRONE_REPO_OWNER,
|
||||
$Env:DRONE_REPO_NAME,
|
||||
$id,
|
||||
$Env:GITEA_TOKEN
|
||||
)
|
||||
Write-Debug -Message ('Exec API Call: {0}' -f $ExtAPI)
|
||||
Invoke-RestMethod -Method 'Delete' -Headers $APIHeaders -Uri $ExtAPI
|
||||
}
|
||||
}
|
||||
|
||||
if ($Mode -eq 'Edit') {
|
||||
$Comments = Invoke-RestMethod -Method 'Get' -Headers $APIHeaders -Uri $CommentAPICall
|
||||
$DroneComments = $Comments | Where-Object {
|
||||
$_.user.login -eq 'drone'
|
||||
} | Select-Object -ExpandProperty 'id'
|
||||
Write-Debug -Message ('Found Drone comments: {0}.' -f ($DroneComments -join ', '))
|
||||
$EditId = $DroneComments | Sort-Object | Select-Object -Last 1
|
||||
Write-Debug -Message ('Edit Comment with id {0}' -f $EditId)
|
||||
}
|
||||
|
||||
$PRCommentHeader = ('> Drone.io PR Build No. [#{0}]({1}://{2}/{3}/{4}): ``{5}``' -f
|
||||
$Env:DRONE_BUILD_NUMBER,
|
||||
$Env:DRONE_SYSTEM_PROTO,
|
||||
$Env:DRONE_SYSTEM_HOST,
|
||||
$Env:DRONE_REPO,
|
||||
$Env:DRONE_BUILD_NUMBER,
|
||||
$PipelineState
|
||||
|
||||
)
|
||||
$PRCommentHeader | Out-File -FilePath $PRCommentFile -Encoding 'utf8'
|
||||
|
||||
$LogFiles = (Get-ChildItem -Path $Env:LOG_FILES -File).FullName
|
||||
foreach ($file in $LogFiles) {
|
||||
if (Test-Path -Path $file) {
|
||||
('#### ``{0}``' -f $file) | Out-File -FilePath $PRCommentFile -Append -Encoding 'utf8'
|
||||
$fileContent = Get-Content -Path $file -Raw -Encoding utf8
|
||||
$fileContent | Out-File -FilePath $PRCommentFile -Append -Encoding 'utf8'
|
||||
[Environment]::NewLine | Out-File -FilePath $PRCommentFile -Append -Encoding 'utf8' -NoNewline
|
||||
|
||||
}
|
||||
else {
|
||||
Write-Warning -Message ('Given file {0} not found!' -f $file)
|
||||
('##### ``{0}`` not found!' -f $file) | Out-File -FilePath $PRCommentFile -Append -Encoding 'utf8'
|
||||
}
|
||||
}
|
||||
|
||||
if ($Mode -eq 'Edit') {
|
||||
'Last mod: {0}' -f (Get-Date -Format 'u') | Out-File -FilePath $PRCommentFile -Append -Encoding 'utf8'
|
||||
}
|
||||
'end.' | Out-File -FilePath $PRCommentFile -Append -Encoding 'utf8'
|
||||
|
||||
$PRCommentJSON = ConvertTo-Json -InputObject @{
|
||||
Body = Get-Content -Path $PRCommentFile -Encoding utf8 -Raw
|
||||
}
|
||||
Write-Debug -Message ('PR JSON body has a size of {0} chars' -f $PRCommentJSON.length)
|
||||
|
||||
if ($Mode -ne 'Edit') {
|
||||
Write-Debug -Message 'Adding new Comment.'
|
||||
Invoke-RestMethod -Method 'Post' -Headers $APIHeaders -Uri $CommentAPICall -Body $PRCommentJSON
|
||||
}
|
||||
else {
|
||||
$ExtAPI = $UpdateAPICall -f @(
|
||||
$GiteaBase,
|
||||
$Env:DRONE_REPO_OWNER,
|
||||
$Env:DRONE_REPO_NAME,
|
||||
$EditId,
|
||||
$Env:GITEA_TOKEN
|
||||
)
|
||||
Write-Debug -Message 'Edit last comment.'
|
||||
Invoke-RestMethod -Method 'Patch' -Headers $APIHeaders -Uri $ExtAPI -Body $PRCommentJSON
|
||||
}
|
||||
}
|
||||
|
||||
end {
|
||||
}
|
||||
}
|
14
src/PSModule.Tests.ps1
Normal file
14
src/PSModule.Tests.ps1
Normal file
@ -0,0 +1,14 @@
|
||||
Describe 'Test module meta' {
|
||||
It 'Test manifest file' {
|
||||
$ManifestFile = (Get-Item -Path "./src/*.psd1").FullName
|
||||
Test-ModuleManifest -Path $ManifestFile | Should -Be $true
|
||||
}
|
||||
It 'Import Module' {
|
||||
$ManifestFile = (Get-Item -Path "./src/*.psd1").FullName
|
||||
{ Import-Module $ManifestFile } | Should -Not -Throw
|
||||
}
|
||||
# Dummy test to force pester error
|
||||
#It 'Force Pester Error' {
|
||||
# $true | Should -BeFalse
|
||||
#}
|
||||
}
|
21
src/PSScriptAnalyzer/Invoke-Linter.Tests.ps1
Normal file
21
src/PSScriptAnalyzer/Invoke-Linter.Tests.ps1
Normal file
@ -0,0 +1,21 @@
|
||||
BeforeAll {
|
||||
$Repo = Get-RepoPath
|
||||
Import-Module $Repo.Src.Manifest.Item.FullName -Force
|
||||
}
|
||||
Describe 'Invoke-Linter' {
|
||||
Context 'Default tests' -Tag 'Default' {
|
||||
It 'Test Function' {
|
||||
{ Get-Command -Name 'Invoke-Linter' -Module $Repo.Artifact } | Should -Not -Throw
|
||||
}
|
||||
|
||||
It 'Test Help' {
|
||||
{ Get-Help -Name 'Invoke-Linter' } | Should -Not -Throw
|
||||
}
|
||||
It 'Help Content' {
|
||||
$foo = Get-Help -Name 'Invoke-Linter'
|
||||
$foo.Synopsis.Length | Should -BeGreaterThan 5
|
||||
$foo.Description.Count | Should -BeGreaterOrEqual 1
|
||||
$foo.Description[0].Text.Length | Should -BeGreaterThan 5
|
||||
}
|
||||
}
|
||||
}
|
71
src/PSScriptAnalyzer/Invoke-Linter.ps1
Normal file
71
src/PSScriptAnalyzer/Invoke-Linter.ps1
Normal file
@ -0,0 +1,71 @@
|
||||
function Invoke-Linter() {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Runs all PSScriptAnalyzer Rules within this repo.
|
||||
|
||||
.DESCRIPTION
|
||||
This Cmdlet is used in Drone pipeline to run the PSScriptAnalyzer rules..
|
||||
|
||||
.INPUTS
|
||||
[None] No pipeline input.
|
||||
|
||||
.OUTPUTS
|
||||
[None] No pipeline output.
|
||||
|
||||
.EXAMPLE
|
||||
Invoke-Linter
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
|
||||
'PSUseConsistentWhitespace',
|
||||
'',
|
||||
Justification = 'Hashtable bug in ScriptAnalyzer 1.19.1'
|
||||
)]
|
||||
param()
|
||||
process {
|
||||
$Repo = Get-RepoPath
|
||||
# Use repo local defaults. if not present use the DroneHelper included as defaults.
|
||||
if ($Repo.Resources.ScriptAnalyzerSettingsExist) {
|
||||
$currentRules = $Repo.Resources.ScriptAnalyzerSettingsPath
|
||||
}
|
||||
else {
|
||||
$currentRules = $repo.DroneHelper.ScriptAnalyzerDefaultsPath
|
||||
}
|
||||
$AnalyzerParams = @{
|
||||
Path = $Repo.Src.Path
|
||||
Recurse = $true
|
||||
Settings = $currentRules
|
||||
Verbose = $VerbosePreference
|
||||
ReportSummary = $true
|
||||
}
|
||||
$AnalyzerResults = Invoke-ScriptAnalyzer @AnalyzerParams
|
||||
if ( $AnalyzerResults ) {
|
||||
$AnalyzerResults | Sort-Object -Property @(
|
||||
"ScriptName",
|
||||
"Line"
|
||||
) | Format-Table @(
|
||||
"Severity",
|
||||
"ScriptName",
|
||||
"Line",
|
||||
"RuleName",
|
||||
"Message"
|
||||
) -AutoSize | Out-String | Write-Verbose -Verbose
|
||||
$ResultParams = @{
|
||||
Type = 'PSScriptAnalyzer'
|
||||
Path = $Repo.Build.ScriptAnalyzerLogPath
|
||||
InputObject = $AnalyzerResults
|
||||
}
|
||||
Write-ResultFile @ResultParams
|
||||
Write-FailureStateFile -StepName 'PSScriptAnalyzer'
|
||||
throw 'PS Script Analyzer failed!'
|
||||
}
|
||||
else {
|
||||
$ResultParams = @{
|
||||
Type = 'Custom'
|
||||
Path = $Repo.Build.ScriptAnalyzerLogPath
|
||||
InputObject = ':heavy_check_mark: No violations found.'
|
||||
}
|
||||
Write-ResultFile @ResultParams
|
||||
}
|
||||
}
|
||||
}
|
21
src/Pester/Invoke-UnitTest.Tests.ps1
Normal file
21
src/Pester/Invoke-UnitTest.Tests.ps1
Normal file
@ -0,0 +1,21 @@
|
||||
BeforeAll {
|
||||
$Repo = Get-RepoPath
|
||||
Import-Module $Repo.Src.Manifest.Item.FullName -Force
|
||||
}
|
||||
Describe 'Invoke-UnitTest' {
|
||||
Context 'Default tests' -Tag 'Default' {
|
||||
It 'Test Function' {
|
||||
{ Get-Command -Name 'Invoke-UnitTest' -Module $Repo.Artifact } | Should -Not -Throw
|
||||
}
|
||||
|
||||
It 'Test Help' {
|
||||
{ Get-Help -Name 'Invoke-UnitTest' } | Should -Not -Throw
|
||||
}
|
||||
It 'Help Content' {
|
||||
$foo = Get-Help -Name 'Invoke-UnitTest'
|
||||
$foo.Synopsis.Length | Should -BeGreaterThan 5
|
||||
$foo.Description.Count | Should -BeGreaterOrEqual 1
|
||||
$foo.Description[0].Text.Length | Should -BeGreaterThan 5
|
||||
}
|
||||
}
|
||||
}
|
110
src/Pester/Invoke-UnitTest.ps1
Normal file
110
src/Pester/Invoke-UnitTest.ps1
Normal file
@ -0,0 +1,110 @@
|
||||
function Invoke-UnitTest {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Runs all Pester tests within this repo.
|
||||
|
||||
.DESCRIPTION
|
||||
This Cmdlet is used in Drone pipeline to perform the Pester based unit tests.
|
||||
|
||||
.PARAMETER CoverageFormat
|
||||
Pester provides the formats JaCoCo ans CoverageGutters. Default is JaCoCo.
|
||||
These are the known use cases:
|
||||
- JaCoCo -> Used as standard coverage report used by sonar
|
||||
- CoverageGutters -> Custom Format to show coverage in VSCode.
|
||||
|
||||
.PARAMETER Verbosity
|
||||
This parameter sets the Pester detail level. Default is 'Normal.' Available values are:
|
||||
'None', 'Normal', 'Detailed', 'Diagnostic'
|
||||
|
||||
.PARAMETER PassThru
|
||||
Tells Invoke-UnitTest to write back the Pester results into your variable / output.
|
||||
|
||||
.PARAMETER Tag
|
||||
Pester build in tag filter as string array.
|
||||
|
||||
.PARAMETER ExcludeTag
|
||||
Pester build in exclude filter for tests as string array.
|
||||
|
||||
.INPUTS
|
||||
[None] No pipeline input.
|
||||
|
||||
.OUTPUTS
|
||||
[None] No pipeline output.
|
||||
|
||||
.EXAMPLE
|
||||
Invoke-UnitTest
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
|
||||
'PSUseConsistentWhitespace',
|
||||
'',
|
||||
Justification = 'Hashtable bug in ScriptAnalyzer 1.19.1'
|
||||
)]
|
||||
param (
|
||||
[Parameter( Mandatory = $false )]
|
||||
[ValidateSet('JaCoCo', 'CoverageGutters')]
|
||||
[string]$CoverageFormat = 'JaCoCo',
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[ValidateSet('None', 'Normal', 'Detailed', 'Diagnostic')]
|
||||
[string]$Verbosity = 'Normal',
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[switch]$PassThru,
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[string[]]$Tag,
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[string[]]$ExcludeTag
|
||||
)
|
||||
|
||||
process {
|
||||
$Repo = Get-RepoPath
|
||||
Write-Verbose -Message '===== Running Pester =====' -Verbose:$VerbosePreference
|
||||
$PesterConf = New-PesterConfiguration
|
||||
$PesterConf.Run.Path = (Resolve-Path -Path './src').Path
|
||||
$PesterConf.Run.Exit = $false
|
||||
$PesterConf.Run.PassThru = $true
|
||||
$PesterConf.CodeCoverage.Enabled = $true
|
||||
$PesterConf.CodeCoverage.OutputFormat = $CoverageFormat
|
||||
$PesterConf.TestResult.Enabled = $true
|
||||
$CovFiles = Get-ChildItem -Path $Repo.Src.PS1Filter -Recurse | Where-Object {
|
||||
$_.BaseName -notmatch '.Tests'
|
||||
} | Select-Object -ExpandProperty 'FullName'
|
||||
$PesterConf.CodeCoverage.Path = $CovFiles
|
||||
$PesterConf.Output.Verbosity = $Verbosity
|
||||
|
||||
# Set Tags if given
|
||||
if ($Tag) {
|
||||
$PesterConf.Filter.Tag = $Tag
|
||||
}
|
||||
if ($ExcludeTag) {
|
||||
$PesterConf.Filter.ExcludeTag = $ExcludeTag
|
||||
}
|
||||
$TestResults = Invoke-Pester -Configuration $PesterConf -ErrorAction 'Stop'
|
||||
try {
|
||||
$ResFileParams = @{
|
||||
InputObject = $TestResults
|
||||
Path = $Repo.Build.PesterLogPath
|
||||
Type = 'Pester'
|
||||
ErrorAction = 'Stop'
|
||||
}
|
||||
Write-ResultFile @ResFileParams
|
||||
}
|
||||
catch {
|
||||
Write-FailureStateFile -StepName 'Pester'
|
||||
throw ('{0} tests failed!' -f $TestResults.FailedCount)
|
||||
}
|
||||
|
||||
if ($TestResults.FailedCount -gt 0) {
|
||||
Write-FailureStateFile -StepName 'Pester'
|
||||
throw ('{0} tests failed!' -f $TestResults.FailedCount)
|
||||
}
|
||||
if ($PassThru.IsPresent) {
|
||||
Write-Output -InputObject $TestResults
|
||||
}
|
||||
}
|
||||
}
|
43
src/Reports/Format-FileLinterReport.ps1
Normal file
43
src/Reports/Format-FileLinterReport.ps1
Normal file
@ -0,0 +1,43 @@
|
||||
function Format-FileLinterReport {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Private helper function used by Write-ResultFile.
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
[OutputType([string])]
|
||||
|
||||
param (
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[PSTypeName('DroneHelper.FileLinter.Report')]$InputObject
|
||||
)
|
||||
|
||||
begin {
|
||||
}
|
||||
|
||||
process {
|
||||
$Output = @()
|
||||
if ($InputObject.Success) {
|
||||
$Output += ':heavy_check_mark: No FileLinter violations in {0} files found.' -f $InputObject.FilesCount
|
||||
}
|
||||
else {
|
||||
$Output += "| Result | File | Failed |"
|
||||
$Output += "| :----: | :--- | -----: |"
|
||||
foreach ($file in $InputObject.Files) {
|
||||
if ($file.FailedCount -gt 0) {
|
||||
$failedTestNames = (
|
||||
$file.Tests.GetEnumerator() | Where-Object {
|
||||
$_.Value -eq $false
|
||||
} | Select-Object -ExpandProperty 'Name'
|
||||
) -join ', '
|
||||
$Output += "| :heavy_exclamation_mark: | ``{0}`` | ``{1}`` |" -f $file.Name, $failedTestNames
|
||||
}
|
||||
}
|
||||
}
|
||||
Write-Output $Output
|
||||
}
|
||||
|
||||
end {
|
||||
}
|
||||
}
|
74
src/Reports/Format-PesterReport.ps1
Normal file
74
src/Reports/Format-PesterReport.ps1
Normal file
@ -0,0 +1,74 @@
|
||||
function Format-PesterReport {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Private helper function used by Write-ResultFile.
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
[OutputType([string])]
|
||||
|
||||
param (
|
||||
[Parameter(Mandatory = $true)]
|
||||
[PSCustomObject]$InputObject,
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[ValidateSet('Normal', 'Detailed')]
|
||||
[string]$Verbosity = 'Normal'
|
||||
)
|
||||
|
||||
begin {
|
||||
}
|
||||
|
||||
process {
|
||||
$Output = @()
|
||||
$Output += "| Result | Test | Duration |"
|
||||
$Output += "| :----: | :--- | -------: |"
|
||||
foreach ($Result in $InputObject.Tests) {
|
||||
switch ($Result.Result) {
|
||||
'Passed' {
|
||||
if ($Verbosity -eq 'Detailed') {
|
||||
$RawString = "| :heavy_check_mark: | ``{0}`` | *{1}ms* |"
|
||||
$Output += $RawString -f $Result.ExpandedPath, $Result.UserDuration.Milliseconds
|
||||
}
|
||||
}
|
||||
'Failed' {
|
||||
$RawString = "| :heavy_exclamation_mark: | ``{0}`` | *{1}ms* |"
|
||||
$Output += $RawString -f $Result.ExpandedPath, $Result.UserDuration.Milliseconds
|
||||
$Parsed = $Result.ErrorRecord.Exception.Message -split "`n" | Select-Object -First 1
|
||||
$Output += "| :fire: | **{0}** | :fire: |" -f $Parsed
|
||||
}
|
||||
'NotRun' {
|
||||
$RawString = "| :trident: | ``{0}`` | *n/a* |"
|
||||
$Output += $RawString -f $Result.ExpandedPath
|
||||
}
|
||||
Default {
|
||||
$RawString = "| :warning: | ``{0}`` | *{1}ms* |"
|
||||
$Output += $RawString -f $Result.ExpandedPath, $Result.UserDuration.Milliseconds
|
||||
}
|
||||
}
|
||||
}
|
||||
$Output += [Environment]::NewLine
|
||||
# Writing test result summary
|
||||
$Output += @(
|
||||
':test_tube: **{0}** Total Tests (' -f $InputObject.TotalCount +
|
||||
':heavy_check_mark: ``{0} Passed`` :white_small_square:' -f $InputObject.PassedCount +
|
||||
':trident: ``{0} Skipped / NotRun`` :white_small_square: ' -f (
|
||||
$InputObject.SkippedCount + $InputObject.NotRunCount
|
||||
) +
|
||||
':warning: ``Unknown`` :white_small_square: ' +
|
||||
':heavy_exclamation_mark: ``{0} Failed``)' -f $InputObject.FailedCount
|
||||
)
|
||||
# Writing code coverage summary
|
||||
# Covered 37,38% / 75%. 610 analyzed Commands in 26 Files.
|
||||
$Output += @(
|
||||
':bookmark_tabs: Covered **{0}%** / ' -f [Math]::Round($InputObject.CodeCoverage.CoveragePercent, 2) +
|
||||
'{0}%. (' -f $InputObject.CodeCoverage.CoveragePercentTarget +
|
||||
':bookmark: ``{0} analyzed Commands`` ' -f $InputObject.CodeCoverage.CommandsAnalyzedCount +
|
||||
':page_facing_up: ``in {0} Files``)' -f $InputObject.CodeCoverage.FilesAnalyzedCount
|
||||
)
|
||||
Write-Output $Output
|
||||
}
|
||||
|
||||
end {
|
||||
}
|
||||
}
|
40
src/Reports/Format-ScriptAnalyzerReport.ps1
Normal file
40
src/Reports/Format-ScriptAnalyzerReport.ps1
Normal file
@ -0,0 +1,40 @@
|
||||
function Format-ScriptAnalyzerReport {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Private helper function used by Write-ResultFile.
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
[OutputType([string])]
|
||||
|
||||
param (
|
||||
[Parameter(Mandatory = $true)]
|
||||
[PSCustomObject]$InputObject
|
||||
)
|
||||
|
||||
begin {
|
||||
}
|
||||
|
||||
process {
|
||||
$Output = @()
|
||||
$Output += "| Severity | ScriptName | Line | RuleName | Message |"
|
||||
$Output += "| :------: | :--------- | :--: | :------- | :------ |"
|
||||
|
||||
foreach ( $v in $InputObject ) {
|
||||
switch ($v.Severity) {
|
||||
'Warning' { $Emoji = ':warning:' }
|
||||
'Error' { $Emoji = ':heavy_exclamation_mark:' }
|
||||
'Information' { $Emoji = ':mag:' }
|
||||
Default { $Emoji = ':fried_egg:' }
|
||||
}
|
||||
$RawString = "| {0} | {1} | {2} | {3} | {4} |"
|
||||
$Output += $RawString -f $Emoji, $v.ScriptName, $v.Line, $v.RuleName, $v.Message
|
||||
}
|
||||
$RuleURL = 'https://github.com/PowerShell/PSScriptAnalyzer/tree/master/RuleDocumentation'
|
||||
$Output += "`n> See [RuleDocumentation]({0}) for additional help.`n" -f $RuleURL
|
||||
Write-Output $Output
|
||||
}
|
||||
|
||||
end {
|
||||
}
|
||||
}
|
140
src/Rules/PSScriptAnalyzerSettings.psd1
Normal file
140
src/Rules/PSScriptAnalyzerSettings.psd1
Normal file
@ -0,0 +1,140 @@
|
||||
@{
|
||||
Severity = 'Error', 'Warning', 'Information'
|
||||
|
||||
IncludeRules = @(
|
||||
'PSAlignAssignmentStatement',
|
||||
'PSAvoidAssignmentToAutomaticVariable',
|
||||
'PSAvoidDefaultValueForMandatoryParameter',
|
||||
'PSAvoidDefaultValueSwitchParameter',
|
||||
'PSAvoidGlobalAliases',
|
||||
'PSAvoidGlobalFunctions',
|
||||
'PSAvoidGlobalVars',
|
||||
'PSAvoidInvokingEmptyMembers',
|
||||
'PSAvoidLongLines',
|
||||
'PSAvoidNullOrEmptyHelpMessageAttribute',
|
||||
'PSAvoidOverwritingBuiltInCmdlets',
|
||||
'PSAvoidShouldContinueWithoutForce',
|
||||
'PSAvoidTrailingWhitespace',
|
||||
'PSAvoidUsingCmdletAliases',
|
||||
'PSAvoidUsingComputerNameHardcoded',
|
||||
'PSAvoidUsingConvertToSecureStringWithPlainText',
|
||||
'PSAvoidUsingDeprecatedManifestFields',
|
||||
'PSAvoidUsingDoubleQuotesForConstantString',
|
||||
'PSAvoidUsingEmptyCatchBlock',
|
||||
'PSAvoidUsingInvokeExpression',
|
||||
'PSAvoidUsingPlainTextForPassword',
|
||||
'PSAvoidUsingPositionalParameters',
|
||||
'PSAvoidUsingUsernameAndPasswordParams',
|
||||
'PSAvoidUsingWMICmdlet',
|
||||
'PSAvoidUsingWriteHost',
|
||||
'PSMisleadingBacktick',
|
||||
'PSMissingModuleManifestField',
|
||||
'PSPlaceCloseBrace',
|
||||
'PSPlaceOpenBrace',
|
||||
'PSPossibleIncorrectComparisonWithNull',
|
||||
'PSPossibleIncorrectUsageOfAssignmentOperator',
|
||||
'PSPossibleIncorrectUsageOfRedirectionOperator',
|
||||
'PSProvideCommentHelp',
|
||||
'PSReservedCmdletChar',
|
||||
'PSReservedParams',
|
||||
'PSReviewUnusedParameter',
|
||||
'PSShouldProcess',
|
||||
'PSUseApprovedVerbs',
|
||||
'PSUseBOMForUnicodeEncodedFile',
|
||||
'PSUseCmdletCorrectly',
|
||||
# There is no predefined set for Pwsh7 Cmdlets
|
||||
'PSUseCompatibleCmdlets',
|
||||
#'PSUseCompatibleCommands',
|
||||
'PSUseCompatibleSyntax',
|
||||
#'PSUseCompatibleTypes',
|
||||
'PSUseConsistentIndentation',
|
||||
# Disable if bug in 1.19.1 version occurs.
|
||||
'PSUseConsistentWhitespace',
|
||||
'PSUseCorrectCasing',
|
||||
'PSUseDeclaredVarsMoreThanAssignments',
|
||||
'PSUseLiteralInitializerForHashtable',
|
||||
'PSUseOutputTypeCorrectly',
|
||||
'PSUsePSCredentialType',
|
||||
'PSUseProcessBlockForPipelineCommand',
|
||||
'PSUseShouldProcessForStateChangingFunctions',
|
||||
'PSUseSingularNouns',
|
||||
'PSUseSupportsShouldProcess',
|
||||
'PSUseToExportFieldsInManifest',
|
||||
'PSUseUTF8EncodingForHelpFile',
|
||||
'PSUseUsingScopeModifierInNewRunspaces'
|
||||
)
|
||||
|
||||
Rules = @{
|
||||
|
||||
PSAvoidLongLines = @{
|
||||
Enable = $true
|
||||
MaximumLineLength = 116
|
||||
}
|
||||
|
||||
PSPlaceOpenBrace = @{
|
||||
Enable = $true
|
||||
OnSameLine = $true
|
||||
NewLineAfter = $true
|
||||
IgnoreOneLineBlock = $true
|
||||
}
|
||||
|
||||
PSPlaceCloseBrace = @{
|
||||
Enable = $true
|
||||
NewLineAfter = $true
|
||||
IgnoreOneLineBlock = $true
|
||||
NoEmptyLineBefore = $false
|
||||
}
|
||||
|
||||
PSProvideCommentHelp = @{
|
||||
Enable = $true
|
||||
ExportedOnly = $false
|
||||
BlockComment = $true
|
||||
VSCodeSnippetCorrection = $false
|
||||
Placement = "begin"
|
||||
}
|
||||
|
||||
PSUseCompatibleCmdlets = @{
|
||||
compatibility = @(
|
||||
"desktop-5.1.14393.206-windows",
|
||||
"core-6.1.0-windows"
|
||||
)
|
||||
}
|
||||
|
||||
PSUseCompatibleSyntax = @{
|
||||
Enable = $true
|
||||
TargetVersions = @(
|
||||
"7.0",
|
||||
"5.1"
|
||||
)
|
||||
}
|
||||
|
||||
PSUseConsistentIndentation = @{
|
||||
Enable = $true
|
||||
Kind = 'space'
|
||||
PipelineIndentation = 'IncreaseIndentationForFirstPipeline'
|
||||
IndentationSize = 4
|
||||
}
|
||||
|
||||
PSUseConsistentWhitespace = @{
|
||||
Enable = $true
|
||||
CheckInnerBrace = $true
|
||||
CheckOpenBrace = $true
|
||||
CheckOpenParen = $true
|
||||
CheckOperator = $true
|
||||
CheckPipe = $true
|
||||
CheckPipeForRedundantWhitespace = $false
|
||||
CheckSeparator = $true
|
||||
CheckParameter = $false
|
||||
IgnoreAssignmentOperatorInsideHashTable = $true
|
||||
}
|
||||
|
||||
PSAlignAssignmentStatement = @{
|
||||
Enable = $true
|
||||
CheckHashtable = $false
|
||||
}
|
||||
|
||||
PSUseCorrectCasing = @{
|
||||
Enable = $true
|
||||
}
|
||||
}
|
||||
}
|
27
src/State/Invoke-BuidState.ps1
Normal file
27
src/State/Invoke-BuidState.ps1
Normal file
@ -0,0 +1,27 @@
|
||||
function Invoke-BuildState {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Sets final Drone pipeline build state.
|
||||
|
||||
.DESCRIPTION
|
||||
Marks the pipeline ass succeeded of fail based on the custom state file.
|
||||
|
||||
.INPUTS
|
||||
[None] No pipeline input.
|
||||
|
||||
.OUTPUTS
|
||||
[None] No pipeline output.
|
||||
|
||||
.EXAMPLE
|
||||
Invoke-BuildState
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
param()
|
||||
|
||||
process {
|
||||
$Repo = Get-RepoPath
|
||||
if ( Test-Path -Path $Repo.FailureLogPath ) {
|
||||
throw 'One one more pipeline steps failed. Marking the pipeline as failed!'
|
||||
}
|
||||
}
|
||||
}
|
21
src/State/Invoke-BuildState.Tests.ps1
Normal file
21
src/State/Invoke-BuildState.Tests.ps1
Normal file
@ -0,0 +1,21 @@
|
||||
BeforeAll {
|
||||
$Repo = Get-RepoPath
|
||||
Import-Module $Repo.Src.Manifest.Item.FullName -Force
|
||||
}
|
||||
Describe 'Invoke-BuildState' {
|
||||
Context 'Default tests' -Tag 'Default' {
|
||||
It 'Test Function' {
|
||||
{ Get-Command -Name 'Invoke-BuildState' -Module $Repo.Artifact } | Should -Not -Throw
|
||||
}
|
||||
|
||||
It 'Test Help' {
|
||||
{ Get-Help -Name 'Invoke-BuildState' } | Should -Not -Throw
|
||||
}
|
||||
It 'Help Content' {
|
||||
$foo = Get-Help -Name 'Invoke-BuildState'
|
||||
$foo.Synopsis.Length | Should -BeGreaterThan 5
|
||||
$foo.Description.Count | Should -BeGreaterOrEqual 1
|
||||
$foo.Description[0].Text.Length | Should -BeGreaterThan 5
|
||||
}
|
||||
}
|
||||
}
|
21
src/State/Write-FailureStateFile.Tests.ps1
Normal file
21
src/State/Write-FailureStateFile.Tests.ps1
Normal file
@ -0,0 +1,21 @@
|
||||
BeforeAll {
|
||||
$Repo = Get-RepoPath
|
||||
Import-Module $Repo.Src.Manifest.Item.FullName -Force
|
||||
}
|
||||
Describe 'Write-FailureStateFile' {
|
||||
Context 'Default tests' -Tag 'Default' {
|
||||
It 'Test Function' {
|
||||
{ Get-Command -Name 'Write-FailureStateFile' -Module $Repo.Artifact } | Should -Not -Throw
|
||||
}
|
||||
|
||||
It 'Test Help' {
|
||||
{ Get-Help -Name 'Write-FailureStateFile' } | Should -Not -Throw
|
||||
}
|
||||
It 'Help Content' {
|
||||
$foo = Get-Help -Name 'Write-FailureStateFile'
|
||||
$foo.Synopsis.Length | Should -BeGreaterThan 5
|
||||
$foo.Description.Count | Should -BeGreaterOrEqual 1
|
||||
$foo.Description[0].Text.Length | Should -BeGreaterThan 5
|
||||
}
|
||||
}
|
||||
}
|
48
src/State/Write-FailureStateFile.ps1
Normal file
48
src/State/Write-FailureStateFile.ps1
Normal file
@ -0,0 +1,48 @@
|
||||
function Write-FailureStateFile() {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Writes the current pipeline step into failure log.
|
||||
|
||||
.DESCRIPTION
|
||||
This Cmdlet is used to mark single steps as failed without stopping the complete pipeline.
|
||||
|
||||
.PARAMETER StepName
|
||||
The current DroneHelper step name which should be added into to the log.
|
||||
|
||||
.INPUTS
|
||||
[None] No pipeline input.
|
||||
|
||||
.OUTPUTS
|
||||
[None] No pipeline output.
|
||||
|
||||
.EXAMPLE
|
||||
Write-FailureStateFile
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute(
|
||||
'PSUseConsistentWhitespace',
|
||||
'',
|
||||
Justification = 'justification'
|
||||
)]
|
||||
param (
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$StepName
|
||||
)
|
||||
|
||||
process {
|
||||
$Repo = Get-RepoPath
|
||||
$WriteParams = @{
|
||||
FilePath = $Repo.FailureLogPath
|
||||
Encoding = 'utf8'
|
||||
NoClobber = $true
|
||||
Force = $true
|
||||
InputObject = $StepName
|
||||
}
|
||||
|
||||
if ( Test-Path -Path $Repo.FailureLogPath ) {
|
||||
$WriteParams.Append = $true
|
||||
}
|
||||
|
||||
Out-File @WriteParams
|
||||
}
|
||||
}
|
21
src/State/Write-RestultFile.Tests.ps1
Normal file
21
src/State/Write-RestultFile.Tests.ps1
Normal file
@ -0,0 +1,21 @@
|
||||
BeforeAll {
|
||||
$Repo = Get-RepoPath
|
||||
Import-Module $Repo.Src.Manifest.Item.FullName -Force
|
||||
}
|
||||
Describe 'Write-ResultFile' {
|
||||
Context 'Default tests' -Tag 'Default' {
|
||||
It 'Test Function' {
|
||||
{ Get-Command -Name 'Write-ResultFile' -Module $Repo.Artifact } | Should -Not -Throw
|
||||
}
|
||||
|
||||
It 'Test Help' {
|
||||
{ Get-Help -Name 'Write-ResultFile' } | Should -Not -Throw
|
||||
}
|
||||
It 'Help Content' {
|
||||
$foo = Get-Help -Name 'Write-ResultFile'
|
||||
$foo.Synopsis.Length | Should -BeGreaterThan 5
|
||||
$foo.Description.Count | Should -BeGreaterOrEqual 1
|
||||
$foo.Description[0].Text.Length | Should -BeGreaterThan 5
|
||||
}
|
||||
}
|
||||
}
|
59
src/State/Write-ResultFile.ps1
Normal file
59
src/State/Write-ResultFile.ps1
Normal file
@ -0,0 +1,59 @@
|
||||
function Write-ResultFile {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Writes the current pipeline step into failure log.
|
||||
|
||||
.DESCRIPTION
|
||||
This Cmdlet is used to mark single steps as failed without stopping the complete pipeline.
|
||||
|
||||
.PARAMETER StepName
|
||||
The current DroneHelper step name which should be added into to the log.
|
||||
|
||||
.INPUTS
|
||||
[None] No pipeline input.
|
||||
|
||||
.OUTPUTS
|
||||
[None] No pipeline output.
|
||||
|
||||
.EXAMPLE
|
||||
Write-FailureStateFile
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[PSCustomObject]$InputObject,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[String]$Path,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidateSet('Pester', 'PSScriptAnalyzer', 'FileLinter', 'Custom')]
|
||||
[String]$Type
|
||||
)
|
||||
|
||||
process {
|
||||
[String[]]$Output = @()
|
||||
if ($BlockDescription -ne "") {
|
||||
$BlockDescription | Out-File -FilePath $Path -Encoding utf8 -Force -NoClobber -Append
|
||||
}
|
||||
|
||||
switch ($Type) {
|
||||
'Pester' {
|
||||
$Output = Format-PesterReport -InputObject $InputObject
|
||||
}
|
||||
|
||||
'PSScriptAnalyzer' {
|
||||
$Output = Format-ScriptAnalyzerReport -InputObject $InputObject
|
||||
}
|
||||
|
||||
'FileLinter' {
|
||||
$Output = Format-FileLinterReport -InputObject $InputObject
|
||||
}
|
||||
'Custom' {
|
||||
# nothing to do here
|
||||
$Output = $InputObject + [Environment]::NewLine
|
||||
}
|
||||
}
|
||||
$Output | Out-File -FilePath $Path -Encoding utf8 -Force -NoClobber -Append
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user