Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
116 commits
Select commit Hold shift + click to select a range
9fcd9f8
tests: migrate to Pester v5, add test helpers; ci: add coverage best-…
scweeks Mar 7, 2026
4a767c4
Fixed ci.yml.
scweeks Mar 7, 2026
abf421d
Updated the ps1 and psm1 so they would work better, be safer, easier …
scweeks Mar 8, 2026
608b22d
PSScriptAnalyzer: add ShouldProcess support to state-changing helpers
scweeks Mar 8, 2026
6196d26
PSScriptAnalyzer: add ShouldProcess support to state-changing helpers
scweeks Mar 8, 2026
9c41591
PSSA: add comment-based help for detect/export helpers
scweeks Mar 8, 2026
d75b2f4
Made more updates to resolve PSSA findings and improved directory han…
scweeks Mar 8, 2026
0c13b37
Added fujnction comments an resolved a number of PSSA findings and pa…
scweeks Mar 8, 2026
ad23b23
Adding and cleaning up tests.
scweeks Mar 8, 2026
545ccda
fixing tests and running tests on NetClean ps1 and psm1
scweeks Mar 8, 2026
8506486
fixed tests and discrepancies in the code
scweeks Mar 8, 2026
08de6ae
finished debugging preview path and added power options to non-previe…
scweeks Mar 9, 2026
260280e
update CI Actions and removed duplicate, outdated Action
scweeks Mar 9, 2026
3a9c3d3
updated logging in NetClean.psm1
scweeks Mar 10, 2026
6cea66f
Troubleshooting, debugging, and optimizing performance.
scweeks Mar 10, 2026
ce999f4
Updated functions to be safer and more efficient
scweeks Mar 10, 2026
424ac6e
Making more corrections and safety changes.
scweeks Mar 10, 2026
9e74dfc
more safety and optimization changes.
scweeks Mar 10, 2026
d86da66
Modifying functions to use the helper cmd wrapper function while impr…
scweeks Mar 10, 2026
3874ab5
improved performance tuning functions and updated launcher workflow t…
scweeks Mar 11, 2026
d78b8bf
fixing and updating workflow function
scweeks Mar 11, 2026
9d3ac73
fixed naming mismatches and trying to follow PS allowed verbs.
scweeks Mar 11, 2026
00da02c
Updating structure to be more modular. Will be breaking netclean.psm1…
scweeks Mar 15, 2026
b6a3e5e
added phase psm1 files to split the functions to.
scweeks Mar 15, 2026
ade344d
Moved out phase 1 functions to phase 1 psm1.
scweeks Mar 15, 2026
d2a263a
moved phase 2 to its psm1.
scweeks Mar 15, 2026
7a58b51
Moved phase 3 to its psm1.
scweeks Mar 15, 2026
3f8298b
Moved phase 4 to its psm1.
scweeks Mar 15, 2026
b5acec0
updated module import in NetClean.ps1
scweeks Mar 15, 2026
4dd0432
Fixing things that got broken when I split the phases out.
scweeks Mar 15, 2026
4da46b9
Fixing formatting
scweeks Mar 15, 2026
7291001
Fixing exports and imports
scweeks Mar 15, 2026
733ff90
fixed phase module exports. Added nested module section to psd1
scweeks Mar 15, 2026
c03debb
fixed GUID in psd1
scweeks Mar 15, 2026
6b51759
fixed hyphen parsing issue
scweeks Mar 15, 2026
a155fed
Fixed cmdlet binding and plural WiFiProfileNames to WiFiProfileName.
scweeks Mar 15, 2026
a0c7e60
fixed some other PSSA issues.
scweeks Mar 15, 2026
30217e7
Fixing test module import to manifest import
scweeks Mar 15, 2026
151718e
still trying to fix tests
scweeks Mar 15, 2026
f5271c8
fixing naming and module name resolution.
scweeks Mar 15, 2026
4596137
Fixing test files.
scweeks Mar 15, 2026
d8271b8
Changing module structure to work better while still maintaining modu…
scweeks Mar 15, 2026
a8673e6
Added unit, functional and integration test folders and initial files…
scweeks Mar 15, 2026
3081888
added phase 3 and 4 test cases.
scweeks Mar 15, 2026
3c96532
Updated tests, ci.yml, and coverage runner along with the integratrio…
scweeks Mar 15, 2026
c3161d3
changed it so PSSA won't fail on warnings, only errors.
scweeks Mar 15, 2026
bb7d134
added madrapp/jacoco support for PRs.
scweeks Mar 15, 2026
cd4f501
updated Run-NetClean-Coverage and then ran it. This also includes the…
scweeks Mar 15, 2026
90c48e9
Fixing typos and parameter usages.
scweeks Mar 17, 2026
3238679
Updates to functions and parameters
scweeks Jul 20, 2026
4ea24d8
Debugging and test updates
scweeks Jul 21, 2026
0fee368
More debugging and fixing tests
scweeks Jul 21, 2026
d492cdd
Even more debugging and adjusting tests.
scweeks Jul 21, 2026
9ebf8e1
More fixees, debugging, test correction and .gitignore updates
scweeks Jul 21, 2026
627e0f4
More debugging and test expansion.
scweeks Jul 21, 2026
36d7caa
debugging, fixes, test expansion, detection improvements
scweeks Jul 21, 2026
833cd1e
added detection functionality, more debugging, test expansions to inc…
scweeks Jul 21, 2026
0b946f5
updated adapter reset, set DNS to secure DNS config, additional debug…
scweeks Jul 21, 2026
75bfd61
disclose what the program will do to the user before it does it.
scweeks Jul 21, 2026
6e4128a
Update netclean.ps1
scweeks Jul 21, 2026
c0a9edc
Adding verification to phase 4 to ensure work said to be done is actu…
scweeks Jul 21, 2026
dea4507
improving verification checks, fixes
scweeks Jul 21, 2026
04503f2
more debugging, test expansion and improvements to functionality.
scweeks Jul 21, 2026
9c8a1f9
ci: ratchet coverage at measured baseline
scweeks Jul 21, 2026
c959049
ci: migrate test suite to Pester 6.0.1
scweeks Jul 22, 2026
7ce3536
test: add isolated registry system coverage
scweeks Jul 22, 2026
11ec901
test: expand fail-closed verification coverage
scweeks Jul 22, 2026
e1c9312
test: cover protection discovery boundaries
scweeks Jul 22, 2026
3fe25a1
test: cover launcher and summary workflows
scweeks Jul 22, 2026
6678b1b
test: cover cleanup and strict-mode boundaries
scweeks Jul 22, 2026
081ee6c
test: exceed 95 percent production coverage
scweeks Jul 22, 2026
16b4f17
ci: harden analyzer and compatibility checks
scweeks Jul 22, 2026
07e6a2a
fixed .ai gitignore
scweeks Jul 22, 2026
d28f10b
fix: distinguish Workplace registration from management
scweeks Jul 22, 2026
2be5b8d
perf: single-pass evidence collection with per-artifact removal decis…
scweeks Jul 22, 2026
c9be92d
Added AGENTS.md along with other fixes, optimizations, and tests.
scweeks Jul 23, 2026
2d84021
fix: close fail-open/fail-closed gaps in Protect and Clean phases
scweeks Jul 23, 2026
a5af8a9
feat: redesign Phase 4 to verify per-artifact against Phase 1/2 decis…
scweeks Jul 23, 2026
e7ec4ea
fix: launcher Wi-Fi Found/Remaining summary was empty on real runs
scweeks Jul 23, 2026
26b1b7d
refactor: consolidate Phase 2 JSON-export duplication
scweeks Jul 23, 2026
4d8abfe
docs: refresh coverage numbers, add changelog entries, enable PSUseAp…
scweeks Jul 23, 2026
ca1aebf
perf: swap registry provider cmdlets for raw .NET API in the read hel…
scweeks Jul 23, 2026
149ff87
updated ci.yml and readme to use and provide more badges.
scweeks Jul 23, 2026
29ef9a8
Updated the readme
scweeks Jul 23, 2026
69a2e31
fixing code coverage badge issues.
scweeks Jul 23, 2026
50bc38a
fixing CI run errors
scweeks Jul 23, 2026
96008e3
still trying to fix CI run errors.
scweeks Jul 23, 2026
0b42ba5
Fixing more CI run errors.
scweeks Jul 23, 2026
7a18ebf
Fixing a pester error in the CI run.
scweeks Jul 23, 2026
f9148fd
still trying to fix peseer CI run errors.
scweeks Jul 23, 2026
dfc3c7b
Fixing another test error.
scweeks Jul 23, 2026
e6a2f27
fix: PS5.1 module-path persistence, stale CI-text assertion, flaky ex…
scweeks Jul 23, 2026
4b1ca1d
fix: mock WriteAllLines in the rewritten Export-WiFiProfile test
scweeks Jul 24, 2026
2899a64
perf(ci): revert module-caching machinery, tighten timeouts, skip doc…
scweeks Jul 24, 2026
68b4843
ci: cache PSGallery modules at their native install path
scweeks Jul 24, 2026
aa965d8
Drop Windows PowerShell 5.1 support; require PS7.4+
scweeks Jul 24, 2026
454c35d
Add tests/Security suite; fix Wi-Fi profile name injection gap
scweeks Jul 24, 2026
5a5c7db
Make implementation-coupled tests verify real behavior, not mocks
scweeks Jul 24, 2026
2733952
Fix crash on real service registry keys with zero direct values
scweeks Jul 24, 2026
57d4123
Guard Get-AdapterRegistryCorrelation against missing registry values
scweeks Jul 24, 2026
582398f
Fix Get-ProtectionEvidence silently losing service-registry evidence
scweeks Jul 24, 2026
5ee93ee
Guard remaining unguarded registry-property reads from the audit
scweeks Jul 24, 2026
3c8f1cd
Fail closed with a clear message instead of a raw stack trace
scweeks Jul 24, 2026
c640155
Fix non-admin launch crash and non-functional scheduled-task example
scweeks Jul 24, 2026
7b306b7
Add real-machine registry fixture tooling for higher-fidelity testing
scweeks Jul 24, 2026
e17285e
Cut CHANGELOG 1.0.0 section; document this session's fixes
scweeks Jul 24, 2026
2e31903
Fix Wi-Fi profile detection silently finding nothing on non-English W…
scweeks Jul 24, 2026
a41862c
Consolidate Phase1 evidence-record construction into a shared helper
scweeks Jul 24, 2026
88181b5
Remove dead $canLog capability check across all 4 phase modules
scweeks Jul 24, 2026
7e1c0e3
Extract Invoke-NetCleanSingleCommandSafe from Clear-DnsCacheSafe/Clea…
scweeks Jul 24, 2026
d90861c
Remove leftover inline Write-NetCleanLog capability checks
scweeks Jul 25, 2026
a8b8a9e
Consolidate Phase4 verification-check construction into shared helpers
scweeks Jul 25, 2026
4238704
Extract Get-NetCleanSafeProperty helper for optional-property reads
scweeks Jul 25, 2026
f79e727
Fix Phase 4 artifact-verification false failures and missing visibility
scweeks Jul 26, 2026
98de4d5
Fix Export-NetCleanJsonArtifact failing when the data collection is e…
scweeks Jul 26, 2026
dc2dbae
Add release infrastructure: tag-triggered GitHub Release workflow
scweeks Jul 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,18 @@
### Testing and verification

Describe how this change was tested.

### Security and compliance

- [ ] This change does not weaken security controls or introduce unsafe behaviors.
- [ ] If the change modifies state-changing behavior, `ShouldProcess` support is included where applicable.

### CI checks (automatic)

- [ ] PSScriptAnalyzer: no warnings/errors.
- [ ] Pester tests: all tests pass.
- [ ] Any new public functions have tests and documentation updated.

### Reviewer notes

- Provide any special verification steps, permissions needed, or rationale for approving.
262 changes: 236 additions & 26 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,245 @@ name: CI

on:
push:
branches: [ main ]
branches:
- main
- 'ci/**'
- 'feature/**'
- 'bugfix/**'
paths-ignore:
- '**.md'
- 'LICENSE'
pull_request:
branches: [ main ]
paths-ignore:
- '**.md'
- 'LICENSE'
workflow_dispatch:

concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

env:
# Coverage floor (94) is duplicated in tests/Run-NetClean-Coverage.ps1's
# $MinimumCoverage default and in the comment-coverage job's
# min-coverage-overall below - update all three together when ratcheting.
COVERAGE_GATE: '94'

jobs:
build-and-test:
test-and-analyze:
name: PSSA + Pester + Coverage
runs-on: windows-latest
timeout-minutes: 15

defaults:
run:
shell: pwsh

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup PowerShell
uses: PowerShell/PowerShell@v3

- name: Install Pester v5 and PSScriptAnalyzer
shell: pwsh
run: |
Install-Module -Name Pester -Force -Scope CurrentUser -RequiredVersion 5.* -AllowClobber
Install-Module -Name PSScriptAnalyzer -Force -Scope CurrentUser -AllowClobber

- name: Run PSScriptAnalyzer
shell: pwsh
run: |
Import-Module PSScriptAnalyzer
Invoke-ScriptAnalyzer -Path . -SettingsPath .\PSScriptAnalyzerSettings.psd1 -Recurse -Severity Warning,Error

- name: Run Tests (Pester v5)
shell: pwsh
run: |
Import-Module Pester
Invoke-Pester -Script .\tests\Netclean.Tests.ps1 -PassThru
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1

- name: Show PowerShell environment
run: |
$PSVersionTable
Get-Module Pester -ListAvailable |
Sort-Object Version -Descending |
Select-Object -First 5 Name, Version, Path

- name: Resolve PowerShell 7 user module path
id: modpath
run: |
$path = Join-Path ([Environment]::GetFolderPath('MyDocuments')) 'PowerShell\Modules'
"path=$path" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append

- name: Cache PowerShell modules
uses: actions/cache@v4
with:
path: ${{ steps.modpath.outputs.path }}
# Cache is keyed on the exact pinned versions below - bump this key's
# version numbers whenever RequiredVersion changes in the step below,
# so a version bump naturally forces a fresh install instead of
# reusing a stale cached copy.
key: ps7-modules-Pester6.0.1-PSScriptAnalyzer1.25.0-v1

- name: Install PowerShell test and analysis tools
run: |
if (-not (Get-Module -ListAvailable -Name Pester | Where-Object Version -eq ([version]'6.0.1'))) {
Set-PSRepository -Name PSGallery -InstallationPolicy Trusted
Install-Module Pester -Scope CurrentUser -RequiredVersion 6.0.1 -Force -SkipPublisherCheck -ErrorAction Stop
}
if (-not (Get-Module -ListAvailable -Name PSScriptAnalyzer | Where-Object Version -eq ([version]'1.25.0'))) {
Set-PSRepository -Name PSGallery -InstallationPolicy Trusted
Install-Module PSScriptAnalyzer -Scope CurrentUser -RequiredVersion 1.25.0 -Force -ErrorAction Stop
}
Import-Module Pester -RequiredVersion 6.0.1 -Force -ErrorAction Stop
if ((Get-Module Pester).Version -ne [version]'6.0.1') {
throw 'CI requires Pester 6.0.1.'
}
Get-Module PSScriptAnalyzer -ListAvailable |
Sort-Object Version -Descending |
Select-Object -First 1 Name, Version, Path

- name: Validate module manifest
run: |
Test-ModuleManifest .\NetClean.psd1 | Out-Null
Write-Host 'Module manifest validated successfully.'

- name: Run PSScriptAnalyzer
run: |
.\tests\Invoke-NetCleanAnalyzer.ps1 | Format-List

- name: Run Pester with coverage
run: |
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass -Force
.\tests\Run-NetClean-Coverage.ps1 -MinimumCoverage $env:COVERAGE_GATE

- name: Locate coverage output (if present)
id: find_coverage
run: |
$candidates = Get-ChildItem -Path tests/TestResults -Recurse -Filter 'coverage*.xml' -ErrorAction SilentlyContinue |
Select-Object -First 1 -ExpandProperty FullName
if ($candidates) {
Write-Host "Found coverage file: $candidates"
"coverage_path=$candidates" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append
} else {
Write-Host "No coverage file found."
"coverage_path=" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append
}

- name: Upload test artifacts
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: netclean-test-results
path: |
tests/TestResults/**
if-no-files-found: warn
retention-days: 14

- name: Upload coverage artifact (for badge generation)
if: always() && steps.find_coverage.outputs.coverage_path != ''
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: coverage
path: ${{ steps.find_coverage.outputs.coverage_path }}
if-no-files-found: error
retention-days: 30

publish-coverage-badge:
name: Publish coverage badge
needs: test-and-analyze
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
runs-on: windows-latest
timeout-minutes: 10

permissions:
contents: read
pages: write
id-token: write

defaults:
run:
shell: pwsh

steps:
- name: Download coverage artifact
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
with:
name: coverage
path: coverage-artifact

- name: Generate GitHub Pages coverage badge payload
run: |
$coverageXmlPath = Join-Path $env:GITHUB_WORKSPACE 'coverage-artifact/coverage.xml'
if (-not (Test-Path -LiteralPath $coverageXmlPath)) {
throw "Coverage XML not found at $coverageXmlPath"
}

[xml]$doc = Get-Content -LiteralPath $coverageXmlPath
$lineCounter = $doc.SelectNodes('//counter') | Where-Object { $_.GetAttribute('type') -eq 'LINE' } | Select-Object -First 1
if (-not $lineCounter) {
throw 'No LINE counter found in coverage XML.'
}

$missed = [int]$lineCounter.GetAttribute('missed')
$covered = [int]$lineCounter.GetAttribute('covered')
$total = $missed + $covered
$percent = if ($total -gt 0) { [math]::Round(($covered / $total) * 100, 2) } else { 100 }
$message = '{0:N2}%' -f $percent
$color = if ($percent -ge 94) { 'brightgreen' } elseif ($percent -ge 90) { 'green' } elseif ($percent -ge 80) { 'yellow' } else { 'red' }

$sitePath = Join-Path $env:GITHUB_WORKSPACE 'pages-site'
New-Item -ItemType Directory -Path $sitePath -Force | Out-Null

$badge = [ordered]@{
schemaVersion = 1
label = 'coverage'
message = $message
color = $color
}

$badge | ConvertTo-Json -Compress | Set-Content -LiteralPath (Join-Path $sitePath 'coverage.json') -Encoding utf8
@(
'<!doctype html>',
'<html lang="en">',
'<head>',
' <meta charset="utf-8">',
' <meta name="viewport" content="width=device-width, initial-scale=1">',
' <title>NetClean coverage badge</title>',
'</head>',
'<body>',
' <p>NetClean coverage badge JSON is published at <a href="coverage.json">coverage.json</a>.</p>',
'</body>',
'</html>'
) -join [Environment]::NewLine | Set-Content -LiteralPath (Join-Path $sitePath 'index.html') -Encoding utf8

- name: Upload GitHub Pages site artifact
uses: actions/upload-pages-artifact@v3
with:
path: pages-site

- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4

comment-coverage:
name: Comment coverage on pull request
# Only run for same-repo PRs to avoid token permission issues on forks
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository
needs: test-and-analyze
runs-on: windows-latest
timeout-minutes: 10
permissions:
contents: read
pull-requests: write

steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1

- name: Download test and coverage artifacts (test results)
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
with:
name: netclean-test-results
path: tests/TestResults

- name: Download coverage artifact (for PR comment)
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
with:
name: coverage
path: tests/TestResults

- name: Comment PR with coverage summary
uses: madrapps/jacoco-report@e51ce1f46f7f8b5331593f935e59cbaf44b84920 # v1.8.0
with:
paths: |
${{ github.workspace }}/tests/TestResults/coverage.xml
token: ${{ secrets.GITHUB_TOKEN }}
min-coverage-overall: 94
min-coverage-changed-files: 95
title: NetClean Coverage Report
update-comment: true
49 changes: 0 additions & 49 deletions .github/workflows/powershell-check.yml

This file was deleted.

Loading
Loading