Skip to content

Commit deadbc0

Browse files
committed
Add custom PSScriptAnalyzer rules and CI scripts
- Introduced custom PSScriptAnalyzer rules in CustomRules module to enforce comment-based help, parameter descriptions, and proper casing. - Created run-pssa.ps1 script to execute PSScriptAnalyzer with custom rules for public and non-public code. - Added test.ps1 script for running Pester tests with coverage and detailed output. - Documented the delivery and release process, development overview, quality gates, and troubleshooting steps in Markdown files. - Established a structured branch model for development and release processes.
1 parent 5e00108 commit deadbc0

19 files changed

Lines changed: 1958 additions & 0 deletions

.github/copilot-instructions.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Copilot instructions for HaloAPI
2+
3+
This repository is a PowerShell module for the Halo API with helper classes, generated documentation output, and GitHub Actions workflows.
4+
5+
## General expectations
6+
7+
* Prefer small, targeted changes over wide refactors.
8+
* Preserve the repository's existing PowerShell formatting conventions:
9+
* spaces for indentation
10+
* OTBS/K\&R brace style
11+
* comment-based help for public functions
12+
* Keep public cmdlet names, aliases, and manifest exports consistent with existing patterns.
13+
* Avoid editing generated output under `Output/` unless explicitly asked.
14+
* Treat docs under `Docs/MarkDown/`, `Docs/MAML/`, and `Docs/en_GB/` as generated unless the task is specifically about docs generation.
15+
16+
## Testing and verification
17+
18+
* Prefer the existing repo entrypoints when validating changes:
19+
* `pwsh -File .\Bootstrap.ps1`
20+
* `pwsh -File .\DevOps\Quality\run-pssa.ps1`
21+
* `pwsh -File .\DevOps\Quality\test.ps1 -Suite Meta`
22+
* For interactive VS Code test runs, prefer the `Test HaloAPI` task or:
23+
* `pwsh -File .\DevOps\Quality\test.ps1 -IncludeVSCodeMarker`
24+
* Do not invoke `Invoke-Pester` directly from the VS Code host, terminal, or agent command flow for normal validation in this repo.
25+
* Use `DevOps\Quality\test.ps1` as the only supported test entrypoint; direct Pester invocation is only acceptable inside that dedicated script.
26+
* Treat CI/workflow changes carefully and keep them minimal.
27+
28+
## Release and workflow guidance
29+
30+
* Keep GitHub Actions changes focused and explicit.
31+
* Normal branch and pull request work should target `develop`; `main` remains the stable release branch.
32+
* Stable releases should continue to align with the repository's tagged release flow.
33+
* When adjusting release automation, preserve PowerShell Gallery publishing behavior and avoid changing release semantics unless explicitly requested.
34+
35+
## PowerShell module conventions
36+
37+
* Public functions belong under `Public/` and should include comment-based help.
38+
* Internal helpers belong under `Private/`.
39+
* Helper classes, validators, transformations, and completers belong under `Classes/`.
40+
* The module targets PowerShell 7 and is not intended to support Windows PowerShell 5.1.
41+
* Preserve existing parameter naming and aliasing conventions in HaloAPI even where they differ from other repos.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
***
2+
3+
applyTo: "Public/**/\*.ps1,Private/**/*.ps1,Classes/\*\*/*.psm1,Tests/**/\*.ps1,DevOps/**/\*.ps1"
4+
description: "Use for PowerShell files in HaloAPI: preserve formatting, help, structure, and PowerShell 7 conventions."
5+
-----------------------------------------------------------------------------------------------------------------------
6+
7+
# PowerShell file instructions
8+
9+
* Match the existing repository style and indentation.
10+
* Use spaces for indentation and keep OTBS/K\&R brace style.
11+
* Preserve comment-based help for public functions.
12+
* Keep public cmdlet names, aliases, and manifest exports aligned with existing patterns.
13+
* Prefer PowerShell 7-compatible solutions; this repo does not target Windows PowerShell 5.1.
14+
* Preserve existing HaloAPI parameter naming conventions even if they are not camelCase.
15+
* Treat helper classes, validators, argument transformations, and completers as part of the public module design surface and change them carefully.
16+
* For test execution, do not add or use raw `Invoke-Pester` commands as the standard repo workflow; route test runs through `DevOps/Quality/test.ps1` instead.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
***
2+
3+
applyTo: "CHANGELOG.md,HaloAPI.psd1,.github/workflows/\*\*/\*.{yml,yaml}"
4+
description: "Use for HaloAPI versioning and release work: update manifest and release automation carefully while preserving publishing behavior."
5+
--------------------------------------------------------------------------------------------------------------------------------------------------
6+
7+
# Release instructions
8+
9+
* Update `CHANGELOG.md` and `HaloAPI.psd1` together when preparing releases.
10+
* Preserve PowerShell Gallery publishing behavior unless explicitly asked to change it.
11+
* Keep release workflow changes minimal and explicit.
12+
* Treat tags and release automation as production-impacting changes.
13+
* Stable tags must be reachable from `main`; prerelease tags may be cut from `develop`.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
***
2+
3+
applyTo: ".github/workflows/**/\*.{yml,yaml},DevOps/**/\*.ps1"
4+
description: "Use for CI/CD and automation changes in HaloAPI: keep workflows explicit, safe, and consistent with the GitHub Actions-based release flow."
5+
---------------------------------------------------------------------------------------------------------------------------------------------------------
6+
7+
# Workflow and automation instructions
8+
9+
* Keep workflow changes minimal and focused.
10+
* Prefer explicit failure handling in PowerShell workflow steps.
11+
* Use the repo scripts (`Bootstrap.ps1`, `DevOps/Quality/run-pssa.ps1`, `DevOps/Quality/test.ps1`) instead of recreating logic inline in workflows.
12+
* When making GitHub Actions changes, avoid broadening secrets usage or release scope unless explicitly requested.
13+
* Preserve the repo's branch behavior: normal CI and pull request validation target `develop`, while stable releases are cut from `main`.
14+
* Do not use raw `Invoke-Pester` as a workflow, terminal, or agent execution path for HaloAPI validation.
15+
* Use `DevOps/Quality/test.ps1` as the only supported test entrypoint in CI and interactive tooling; direct Pester invocation is only allowed inside that dedicated script.
16+
* Prefer dedicated script entrypoints over ad hoc analyzer commands in CI and interactive tooling.

.github/workflows/ci.yml

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches:
6+
- develop
7+
pull_request:
8+
branches:
9+
- develop
10+
workflow_dispatch:
11+
12+
permissions:
13+
contents: read
14+
15+
jobs:
16+
lint:
17+
name: Lint with PSScriptAnalyzer
18+
runs-on: windows-latest
19+
steps:
20+
- name: Checkout repository
21+
uses: actions/checkout@v4
22+
23+
- name: Bootstrap environment
24+
shell: pwsh
25+
run: |
26+
$ErrorActionPreference = 'Stop'
27+
& "$env:GITHUB_WORKSPACE\Bootstrap.ps1"
28+
29+
- name: Run PSScriptAnalyzer
30+
shell: pwsh
31+
run: |
32+
$ErrorActionPreference = 'Stop'
33+
$results = & "$env:GITHUB_WORKSPACE\DevOps\Quality\run-pssa.ps1"
34+
35+
if ($results) {
36+
$results | Format-Table -AutoSize
37+
throw "PSScriptAnalyzer found $($results.Count) issue(s)."
38+
}
39+
40+
Write-Host 'PSScriptAnalyzer passed.' -ForegroundColor Green
41+
42+
cross-platform-smoke:
43+
name: Cross-Platform Smoke Tests
44+
runs-on: ${{ matrix.os }}
45+
needs: lint
46+
strategy:
47+
fail-fast: false
48+
matrix:
49+
os:
50+
- ubuntu-latest
51+
- macos-latest
52+
steps:
53+
- name: Checkout repository
54+
uses: actions/checkout@v4
55+
56+
- name: Bootstrap environment
57+
shell: pwsh
58+
run: |
59+
$ErrorActionPreference = 'Stop'
60+
& "$env:GITHUB_WORKSPACE\Bootstrap.ps1"
61+
62+
- name: Run metadata smoke tests
63+
shell: pwsh
64+
run: |
65+
$ErrorActionPreference = 'Stop'
66+
pwsh -NoProfile -File "$env:GITHUB_WORKSPACE\DevOps\Quality\test.ps1" -Suite Meta -Verbosity Normal
67+
68+
test:
69+
name: Run Pester Tests
70+
runs-on: windows-latest
71+
needs:
72+
- lint
73+
- cross-platform-smoke
74+
steps:
75+
- name: Checkout repository
76+
uses: actions/checkout@v4
77+
78+
- name: Bootstrap environment
79+
shell: pwsh
80+
run: |
81+
$ErrorActionPreference = 'Stop'
82+
& "$env:GITHUB_WORKSPACE\Bootstrap.ps1"
83+
84+
- name: Run metadata tests
85+
shell: pwsh
86+
run: |
87+
$ErrorActionPreference = 'Stop'
88+
pwsh -NoProfile -File "$env:GITHUB_WORKSPACE\DevOps\Quality\test.ps1" -Suite Meta -Verbosity Detailed -CodeCoverage
89+
90+
- name: Upload test results
91+
if: always()
92+
uses: actions/upload-artifact@v4
93+
with:
94+
name: pester-results
95+
path: .artifacts/TestResults.meta.xml
96+
97+
- name: Publish test results
98+
if: always()
99+
uses: dorny/test-reporter@v3
100+
with:
101+
name: Pester Tests (Meta)
102+
path: .artifacts/TestResults.meta.xml
103+
reporter: java-junit
104+
105+
- name: Upload code coverage results
106+
if: always()
107+
uses: actions/upload-artifact@v4
108+
with:
109+
name: code-coverage-results
110+
path: .artifacts/CodeCoverage.meta.xml
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
name: Create GitHub Release
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*'
7+
8+
jobs:
9+
release:
10+
runs-on: ubuntu-latest
11+
permissions:
12+
contents: write
13+
steps:
14+
- name: Checkout repository
15+
uses: actions/checkout@v4
16+
with:
17+
fetch-depth: 0
18+
19+
- name: Validate tag source
20+
shell: bash
21+
run: |
22+
set -euo pipefail
23+
TAG_NAME="${GITHUB_REF_NAME}"
24+
TAG_COMMIT="${GITHUB_SHA}"
25+
26+
if [[ "${TAG_NAME}" =~ -(alpha|beta|rc) ]]; then
27+
echo "Pre-release tag detected: ${TAG_NAME}"
28+
if git merge-base --is-ancestor "${TAG_COMMIT}" origin/develop; then
29+
echo 'Tag commit is reachable from develop.'
30+
else
31+
echo 'Tag commit is NOT reachable from develop.' >&2
32+
exit 1
33+
fi
34+
else
35+
echo "Stable tag detected: ${TAG_NAME}"
36+
if git merge-base --is-ancestor "${TAG_COMMIT}" origin/main; then
37+
echo 'Tag commit is reachable from main.'
38+
else
39+
echo 'Tag commit is NOT reachable from main.' >&2
40+
exit 1
41+
fi
42+
fi
43+
44+
- name: Create GitHub release
45+
shell: pwsh
46+
env:
47+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
48+
run: |
49+
$ErrorActionPreference = 'Stop'
50+
$tagName = $env:GITHUB_REF_NAME
51+
$versionName = $tagName.TrimStart('v')
52+
$notesPath = Join-Path -Path $env:RUNNER_TEMP -ChildPath 'release-notes.md'
53+
$changelog = Get-Content -Path (Join-Path -Path $env:GITHUB_WORKSPACE -ChildPath 'CHANGELOG.md') -Raw
54+
$escapedVersion = [regex]::Escape($versionName)
55+
$pattern = "(?ms)^##\s+.*?Version\s+$escapedVersion\s*$\r?\n(?<body>.*?)(?=^##\s+|\z)"
56+
$match = [regex]::Match($changelog, $pattern)
57+
58+
if ($match.Success) {
59+
$notes = $match.Groups['body'].Value.Trim()
60+
Set-Content -Path $notesPath -Value $notes -Encoding UTF8
61+
}
62+
63+
$preReleaseFlag = @()
64+
if ($tagName -match '-(alpha|beta|rc)') {
65+
$preReleaseFlag = @('--prerelease')
66+
}
67+
68+
if (gh release view $tagName *> $null) {
69+
gh release delete $tagName --yes
70+
}
71+
72+
if ((Test-Path -Path $notesPath) -and -not [string]::IsNullOrWhiteSpace((Get-Content -Path $notesPath -Raw))) {
73+
gh release create $tagName @preReleaseFlag --notes-file $notesPath
74+
} else {
75+
gh release create $tagName @preReleaseFlag --generate-notes
76+
}

0 commit comments

Comments
 (0)