PowerShell ColorScripts Enhanced

PowerShell ColorScripts Enhanced by Typpi / Nick2bad4u

View on GitHub

Publishing Guide

This guide documents the repository’s current release pipeline for ColorScripts-Enhanced. The PowerShell Gallery is the primary destination; NuGet.org is optional and uses OIDC trusted publishing. The workflow does not publish to GitHub Packages.

Release Contract

The current manifest version is 2026.8.17.2152.

Automated Publishing

.github/workflows/publish.yml is the source of truth. It can be invoked by:

The workflow:

  1. installs the pinned PowerShell and Node.js tooling;
  2. builds the module and runs release-note, verification, conversion, coverage, ScriptAnalyzer, and Pester checks;
  3. verifies that the requested version and release tag match the built manifest;
  4. creates and normalizes a .nupkg package;
  5. generates release notes with git-cliff;
  6. creates the GitHub release as a draft, uploads the normalized package, and only then publishes it as an immutable release;
  7. publishes to the PowerShell Gallery when PSGALLERYAPIKEY is available; and
  8. optionally transfers the verified package to a dedicated OIDC job and publishes it to NuGet.org when publishToNuGet is not false.

Manual Inputs

Input Default Effect
publishToNuGet true Enables the optional NuGet.org publish step
versionOverride empty Overrides the version passed to build.ps1
createRelease true Creates the immutable GitHub release

The workflow does not define a publishToGitHub input or push to GitHub Packages.

GitHub release assets fail the workflow if they cannot be uploaded. The release action uses immutableCreate, which creates a draft, attaches the package, and publishes only after the upload succeeds. This follows GitHub’s immutable-release guidance and avoids publishing an assetless release that cannot be repaired in place.

Publishing Credentials

Secret Purpose
PSGALLERYAPIKEY Publishes the normalized package to PowerShell Gallery

PSGALLERYAPIKEY is optional for reusable-workflow calls. A missing key causes the PowerShell Gallery publish step to skip; it does not turn validation into a failure. NuGet.org does not use a repository API-key secret.

NuGet.org Trusted Publishing

The dedicated publish-nuget job has id-token: write, downloads the exact normalized package produced by the validation job, and uses NuGet/login to exchange GitHub’s OIDC token for a one-hour NuGet.org API key immediately before the push. The build and GitHub-release job does not have OIDC permission.

The NuGet.org trusted-publishing policy must match these values:

Policy field Value
Package owner typpi
Repository owner Nick2bad4u
Repository PS-Color-Scripts-Enhanced
Workflow file publish.yml
Environment empty

Leave Environment empty while the workflow does not declare a GitHub Actions environment. If a protected environment is added later, use its exact name in both the workflow job and the NuGet.org policy. A reusable-workflow caller must allow id-token: write; permissions cannot be elevated by the called workflow.

After the first successful trusted publish, revoke any superseded NuGet.org API key and remove the old NUGETAPIKEY repository secret. The workflow no longer reads it.

Manual Dispatch

# Validate, package, create the release, and publish where keys are configured.
gh workflow run publish.yml --ref main

# Skip NuGet.org and use an explicit module version.
gh workflow run publish.yml --ref main `
    -f publishToNuGet=false `
    -f createRelease=true `
    -f versionOverride='2026.7.20.2250'

gh run list --workflow=publish.yml

Do not supply a version override that differs from the intended release tag. The workflow rejects mismatches.

Local Pre-Publish Validation

From the repository root:

Test-ModuleManifest -Path ./ColorScripts-Enhanced/ColorScripts-Enhanced.psd1
npm ci
npm run verify
npm run test
npm run lint
npm run release:verify

npm run build is the aggregate build and release-readiness command. It performs generated-file updates, so review the resulting diff before committing it.

To inspect command exports after validation:

Remove-Module ColorScripts-Enhanced -Force -ErrorAction SilentlyContinue
Import-Module ./ColorScripts-Enhanced/ColorScripts-Enhanced.psd1 -Force
Get-Command -Module ColorScripts-Enhanced | Sort-Object Name

Local Packaging and Publishing

The supported release path is the GitHub workflow. If local publishing is necessary, use a temporary PowerShell repository to create the package, then run the same metadata normalizer used in CI before pushing it.

$stagingPath = Join-Path $env:TEMP 'ColorScripts-Enhanced-packages'
New-Item -ItemType Directory -Path $stagingPath -Force | Out-Null

Register-PSRepository `
    -Name LocalModuleStaging `
    -SourceLocation $stagingPath `
    -PublishLocation $stagingPath `
    -InstallationPolicy Trusted

try {
    Publish-Module `
        -Path ./ColorScripts-Enhanced `
        -Repository LocalModuleStaging `
        -NuGetApiKey LocalRepositoryKey
}
finally {
    Unregister-PSRepository -Name LocalModuleStaging -ErrorAction SilentlyContinue
}

$package = Get-ChildItem -LiteralPath $stagingPath -Filter '*.nupkg' |
    Sort-Object LastWriteTimeUtc -Descending |
    Select-Object -First 1

pwsh -NoProfile -File ./scripts/Update-NuGetPackageMetadata.ps1 `
    -PackagePath $package.FullName

Push the normalized package only after inspecting it:

dotnet nuget push $package.FullName `
    --api-key $env:PSGALLERYAPIKEY `
    --source https://www.powershellgallery.com/api/v2/package `
    --skip-duplicate

# Optional second destination for a manual emergency publish. The automated
# workflow obtains its NuGet.org credential through trusted publishing instead.
dotnet nuget push $package.FullName `
    --api-key $env:NUGET_API_KEY `
    --source https://api.nuget.org/v3/index.json `
    --skip-duplicate

Avoid converting a secure string back to plaintext in managed memory merely to pass an API key. Prefer a short-lived environment variable supplied by the local secret manager or CI environment.

Release Checklist

Post-Publish Verification

Find-Module -Name ColorScripts-Enhanced -Repository PSGallery |
    Select-Object Name, Version, PublishedDate

$testInstallRoot = Join-Path $env:TEMP 'ColorScripts-Enhanced-install-test'
Save-Module -Name ColorScripts-Enhanced -Repository PSGallery -Path $testInstallRoot

Use an isolated PowerShell process or module path for installation checks so an already imported development checkout cannot mask a packaging problem.

Troubleshooting

References