Thank you for your interest in contributing! This document provides guidelines and best practices for contributing to this project.
- Code of Conduct
- How to Contribute
- Development Setup
- Coding Standards
- Submitting Changes
- Releasing to PSGallery
- Reporting Issues
This project follows the Contributor Covenant Code of Conduct. By participating, you are expected to uphold this code.
- Search existing issues to avoid duplicates
- Open a new issue using the Bug Report template
- Include:
- PowerShell version (
$PSVersionTable) - Windows version (
[System.Environment]::OSVersion) - Steps to reproduce
- Expected vs. actual behavior
- Relevant entries from
EventMonitor/Telemetry/Logs.txt
- PowerShell version (
- Open an issue using the Feature Request template
- Describe:
- The problem or use case
- Your proposed solution
- Alternative approaches you've considered
- Fork navalerakesh/EventMonitor.Windows
- Create a feature branch from
main:git checkout -b feature/my-feature - Make your changes following the Coding Standards
- Test your changes (see Testing)
- Commit with a clear message (see Commit Messages)
- Push to your fork and open a Pull Request
- Windows 10/11 or Windows Server 2016+
- PowerShell 7.4+
- Administrator privileges (for scheduled task testing)
- Azure Application Insights resource (optional — telemetry sinks are pluggable)
# Clone the repo (or your fork)
git clone https://github.com/navalerakesh/EventMonitor.Windows.git
cd EventMonitor.Windows
# Import the module for development
Import-Module .\EventMonitor.Windows.psd1
# Install development dependencies
Install-Module -Name Pester -MinimumVersion 5.0 -Force
Install-Module -Name PSScriptAnalyzer -Force# Run PSScriptAnalyzer for code quality
Invoke-ScriptAnalyzer -Path . -Recurse -Severity Warning
# Run Pester tests (safe local runner — no code coverage, has timeout)
.\Run-Tests.ps1
# Or with less output:
.\Run-Tests.ps1 -Verbosity NormalNote: Do not run
Invoke-Pesterwith code coverage enabled locally — it can cause VS Code to become unresponsive. Code coverage runs automatically in CI. Always useRun-Tests.ps1for local testing.
- Use PascalCase for function names following the
Verb-Nounconvention - Use approved PowerShell verbs (
Get-Verbto see the list) - Use
[CmdletBinding()]and[Parameter()]attributes for all public functions - Include comment-based help (
.SYNOPSIS,.DESCRIPTION,.PARAMETER,.EXAMPLE) for all exported functions - Use
$ErrorActionPreference = "Stop"in scripts that need strict error handling - Prefer
Write-Verbose/Write-WarningoverWrite-Hostfor non-interactive output
- Never commit secrets, connection strings, or credentials to the repository
- Never log secrets or connection strings in plain text
- Use
-ForcewithRemove-Itemcautiously - Validate all external input parameters
- Root module is
EventMonitor/WindowsEventMonitor.psm1— it dot-sources all.ps1files Core/— Infrastructure:EventWatcher.ps1,WatchdogService.ps1,MonitoringConfig.ps1,EventJournal.ps1EventProcessors/— One file per event category (14 processor files +EventProcessorBase.ps1)TelemetryClient.ps1— Pluggable sink dispatcher (not App Insights-specific)EventDispatch.ps1— Write-EMLog + event enrichmentSessionDetection.ps1— quser, netstat, user enumerationTaskManagement.ps1— Scheduled task lifecycle + orchestrationStart-EventMonitorService.ps1— Event-driven entry point (primary)Invoke-EventMonitor— Exported function for diagnostic one-shot scan- New event categories should get their own
.ps1file inEventProcessors/and be dot-sourced from the root module
Use clear, descriptive commit messages:
<type>: <short description>
<optional body explaining the change>
Types: feat, fix, docs, refactor, test, chore
Examples:
feat: add Event 4625 failed logon trackingfix: handle missing OpenSSH log gracefullydocs: add KQL query examples to README
- Ensure your PR targets the
mainbranch - Fill in the PR template completely
- Ensure PSScriptAnalyzer passes with no errors
- Add or update tests for your changes
- Update documentation if behavior changes
- One approval is required before merging
- Squash commits into a single meaningful commit on merge
The release pipeline is fully automated via GitHub Actions. You just need to set up the secret once, then tag-and-push to release.
-
Get your API key from PSGallery:
- Sign in at https://www.powershellgallery.com
- Go to Account → API Keys → Create
- Set a descriptive name (e.g.
EventMonitor.Windows-CI) - Scope: Push new packages and package versions
- Glob pattern:
EventMonitor.Windows - Set expiration (max 365 days — set a calendar reminder to rotate)
- Copy the key immediately (it won't be shown again)
-
Store the key as a GitHub secret:
- Go to your repo → Settings → Secrets and variables → Actions
- Click New repository secret
- Name:
PSGALLERY_API_KEY - Value: paste the API key
- Click Add secret
-
Create a GitHub Environment (recommended for protection rules):
- Go to Settings → Environments → New environment
- Name:
PSGallery - Optionally add protection rules (required reviewers, wait timer)
- The release workflow references this environment for the publish job
# 1. Update the version in EventMonitor.Windows.psd1
# ModuleVersion = '1.1.0'
# 2. Update CHANGELOG.md — move items from [Unreleased] to [1.1.0] - YYYY-MM-DD
# 3. Update ReleaseNotes in the manifest PrivateData.PSData section
# 4. Commit and push
git add -A
git commit -m 'chore: prepare release v1.1.0'
git push origin main
# 5. Tag and push — this triggers the release pipeline
git tag v1.1.0
git push origin v1.1.0The pipeline will automatically:
- Run PSScriptAnalyzer (lint)
- Run all Pester tests
- Validate the manifest, version consistency, and changelog entry
- Check that the version isn't already published on PSGallery
- Stage and publish the module to PSGallery
- Create a GitHub Release with changelog notes
You can also trigger a release manually from the Actions tab → Release to PSGallery → Run workflow. Use this if a tag push failed or you need to re-publish.
PSGallery API keys expire. When yours is about to expire:
- Create a new key on PSGallery
- Update the
PSGALLERY_API_KEYsecret in GitHub - Delete the old key from PSGallery
If you have questions about contributing, open a Discussion or reach out via an issue.
Thank you for helping make EventMonitor.Windows better!