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
|
# 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