Thank you for your interest in contributing to setup-crmsdk!
- Windows (PowerShell 5.1+)
- Git
git clone https://github.com/marcus-hooper/setup-crmsdk.git
cd setup-crmsdk
# Install latest version
.\scripts\Install-CrmSdk.ps1
# Or install a specific version
$env:INPUT_VERSION = '9.1.0.184'
.\scripts\Install-CrmSdk.ps1# Run Pester tests
Invoke-Pester -Path ./tests -Output DetailedBefore pushing, run the same checks as CI:
# Lint check (must pass)
Invoke-ScriptAnalyzer -Path ./scripts -Recurse -Settings PSGallery
# Format check (must pass)
$scripts = Get-ChildItem -Path ./scripts -Include *.ps1,*.psm1 -Recurse
foreach ($script in $scripts) {
$content = Get-Content $script.FullName -Raw
$formatted = Invoke-Formatter -ScriptDefinition $content
if ($content -ne $formatted) {
Write-Host "Formatting issues in: $($script.Name)"
}
}
# Unit tests (must pass)
Invoke-Pester -Path ./tests -Output Detailed# All-in-one CI check
Invoke-ScriptAnalyzer -Path ./scripts -Recurse -Settings PSGallery; if ($?) { Invoke-Pester -Path ./tests -Output Detailed }Use Conventional Commits format:
<type>: <description>
[optional body]
[optional footer]
| Type | Description |
|---|---|
feat |
New feature |
fix |
Bug fix |
docs |
Documentation only |
refactor |
Code change that neither fixes a bug nor adds a feature |
test |
Adding or updating tests |
ci |
CI/workflow changes |
deps |
Dependency updates |
security |
Security improvements |
chore |
Other maintenance tasks |
perf |
Performance improvement |
feat: add support for specifying SDK version
fix: handle missing LOCALAPPDATA environment variable
docs: update usage examples in README
test: add tests for Set-CrmSdkEnvironmentVariable
ci: add CodeQL security scanning
deps: update actions/checkout to v6
security: pin GitHub Actions to commit SHAs
For breaking changes, use ! after the type or add a BREAKING CHANGE: footer:
feat!: change installation directory structure
SDK tools now install to $LOCALAPPDATA\CrmSdk\ instead of $LOCALAPPDATA\Programs\
Or with a footer:
feat: change installation directory structure
BREAKING CHANGE: SDK tools now install to $LOCALAPPDATA\CrmSdk\ instead of $LOCALAPPDATA\Programs\
-
Create a branch from
main:git checkout -b feature/your-feature-name
-
Run CI locally (see above)
-
Add tests for new functionality
-
Update CHANGELOG.md under
[Unreleased]
All PRs must pass these checks before merge:
| Check | Command | Threshold |
|---|---|---|
| Lint | Invoke-ScriptAnalyzer -Path ./scripts -Recurse -Settings PSGallery |
No errors |
| Format | See format check in Running CI Locally | No changes |
| Tests | Invoke-Pester -Path ./tests |
All pass |
| Coverage | Collected automatically | Reported only (not enforced) |
Use the PR template. Include:
- Summary of changes
- Related issue (if any)
- Type of change
- Testing performed
- All PRs require at least one approval
- Address review feedback promptly
- Resolve all conversations before merge
- Squash merge to
main
| Job | Runner | Notes |
|---|---|---|
| Lint & Format | ubuntu-latest |
PSScriptAnalyzer works cross-platform |
| Unit Tests | ubuntu-latest |
Pester tests with mocked dependencies |
| Integration | windows-latest |
Requires Windows for actual SDK installation |
# Run all tests
Invoke-Pester -Path ./tests -Output Detailed
# Run tests with coverage
$config = New-PesterConfiguration
$config.Run.Path = './tests'
$config.CodeCoverage.Enabled = $true
$config.CodeCoverage.Path = @('./scripts/Install-CrmSdk.ps1', './scripts/Install-CrmSdk.psm1')
Invoke-Pester -Configuration $config| Change Type | Test Requirement |
|---|---|
| New function | Add unit tests covering happy path and error cases |
| Bug fix | Add regression test that fails without the fix |
| Refactor | Ensure existing tests still pass |
Tests are located in tests/Install-CrmSdk.Tests.ps1. See existing tests for patterns on mocking external dependencies like Invoke-WebRequest and nuget.exe.
# Use Test-Path for existence checks, $env:VAR for truthy checks
if (Test-Path env:CRM_SDK_PATH) {
# Variable exists (even if empty)
}
if ($env:CI) {
# Variable is set and non-empty (truthy)
}
# Mock external dependencies in tests (use -ModuleName for module-scoped mocks)
Mock Invoke-WebRequest { } -ModuleName Install-CrmSdk
Mock Invoke-NuGetInstall { return 0 } -ModuleName Install-CrmSdk# Use ErrorAction Stop for critical operations
Invoke-WebRequest -Uri $url -OutFile $file -ErrorAction Stop
# Use try/finally for cleanup
try {
Push-Location $tempDir
# ... work
} finally {
Pop-Location
}
# Check exit codes after external commands
& nuget.exe install $package
if ($LASTEXITCODE -ne 0) {
throw "NuGet install failed"
}
# Environment variable checks: existence vs truthy
if (Test-Path env:CRM_SDK_PATH) { } # Exists (even if empty)
if ($env:CI) { } # Truthy (set and non-empty)
# Add SupportsShouldProcess for state-changing functions
function Set-Something {
[CmdletBinding(SupportsShouldProcess)]
param(...)
}- Use
Write-Messagefor consistent logging - Use
Invoke-Safelyfor error handling with context - Export functions via module manifest
- Add comment-based help for public functions
When adding functions to Install-CrmSdk.psm1:
- Add the function implementation
- Add it to
Export-ModuleMember -Functionat the bottom of the module - Add corresponding Pester tests in
tests/Install-CrmSdk.Tests.ps1
Keep .ps1 entry points minimal—put testable logic in the .psm1 module.
Use the bug report template. Include:
- Operating system and PowerShell version
- Steps to reproduce
- Expected vs actual behavior
- Relevant error messages
Use the feature request template. Include:
- Problem statement
- Proposed solution
- Alternatives considered
Releases are managed by maintainers:
- All CI checks pass on
main - CHANGELOG.md updated with version and date
- Tag created:
git tag -a v1.0.0 -m "Release v1.0.0" - Tag pushed:
git push origin v1.0.0 - GitHub Actions creates release and updates major version tag
- Questions: Open a Discussion
- Bugs: Open an Issue
- Security: See SECURITY.md
By contributing, you agree that your contributions will be licensed under the MIT License.