Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
11 changes: 10 additions & 1 deletion .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ body:
attributes:
label: Pre-flight checklist
options:
- label: I have run `Update-Profile` and the issue persists
- label: I have checked the [troubleshooting table](https://github.com/26zl/PowerShellPerfect#troubleshooting)
- label: I have run `Clear-ProfileCache` and the issue persists
- label: I have searched existing issues for duplicates
required: true
Expand All @@ -33,6 +33,15 @@ body:
validations:
required: true

- type: textarea
id: psp-doctor
attributes:
label: psp-doctor output
description: 'Run `psp-doctor` and paste the output: it shows the profile version, the commit it was installed from, and the state of tools, caches and fonts. Paths include your user name; edit it out if you like. If the profile does not load, say so.'
render: text
validations:
required: true

- type: textarea
id: description
attributes:
Expand Down
13 changes: 11 additions & 2 deletions .github/ISSUE_TEMPLATE/tool_issue.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: Tool Issue
description: Report an issue with a managed tool (eza, zoxide, fzf, bat, ripgrep, Oh My Posh)
title: "[Tool] "
labels: ["tool-issue"]
labels: ["bug"]
body:
- type: dropdown
id: tool
Expand All @@ -21,7 +21,7 @@ body:
id: tool-version
attributes:
label: Tool version
description: "Run `Update-Tools` or check the tool's `--version` output"
description: "Run the tool with `--version` (for Oh My Posh, `oh-my-posh version`)"
placeholder: "e.g. eza 0.20.14"
validations:
required: true
Expand All @@ -37,6 +37,15 @@ body:
validations:
required: true

- type: textarea
id: psp-doctor
attributes:
label: psp-doctor output
description: 'Run `psp-doctor` and paste the output: it shows the profile version, the commit it was installed from, and where each tool was found. Paths include your user name; edit it out if you like.'
render: text
validations:
required: true

- type: textarea
id: description
attributes:
Expand Down
1 change: 0 additions & 1 deletion .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
- [ ] Bug fix: a regression case in `tests/unit.ps1` fails without the fix
- [ ] Tested on PowerShell 5.1 (if script behavior changed)
- [ ] Tested on PowerShell 7+ (if script behavior changed)
- [ ] User-visible change listed under **Unreleased** in `CHANGELOG.md`
- [ ] New downloads are pinned (version and SHA-256 where available); new third-party calls are mocked in CI and listed in `SECURITY.md`
- [ ] No hardcoded user paths (`C:\Users\`, `/home/`)
- [ ] No embedded secrets or tokens
Expand Down
17 changes: 17 additions & 0 deletions .github/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Groups the notes GitHub generates from merged pull requests (gh release create --generate-notes in workflows/release.yml).
changelog:
exclude:
labels:
- dependencies
authors:
- "dependabot[bot]"
categories:
- title: Features
labels:
- enhancement
- title: Fixes
labels:
- bug
- title: Other changes
labels:
- "*"
11 changes: 6 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ jobs:

- name: Run PSScriptAnalyzer (PSScriptAnalyzerSettings.psd1)
shell: pwsh
# tests/ is excluded: those files call profile aliases (gc, ls, cat, uptime, eventlog) by their short names to
# exercise the profile's own definitions, and hold fixtures that trip the secret and path scanners.
# tests/ is excluded: the harnesses call commands by alias and hold fixtures that trip the analyzer rules.
run: pwsh -NoProfile -File tests/lint.ps1 -NoInstall

- name: Smoke-test profile (PS7, sandboxed, load-time budget)
Expand Down Expand Up @@ -80,8 +79,7 @@ jobs:
'/home/'
'\\\\Users\\\\'
)
# tests/test.ps1 replicates this same check locally, so it contains the regex patterns
# we are searching for; excluded by name to avoid self-matching.
# tests/test.ps1 contains these patterns, so it is excluded by name.
$files = Get-ChildItem -Recurse -Include *.ps1 | Where-Object { $_.FullName -notlike '*\.git\*' -and $_.Name -ne 'test.ps1' }
$found = @()
foreach ($file in $files) {
Expand Down Expand Up @@ -314,7 +312,10 @@ jobs:
# Everything else setup.ps1 loads from the verified profile must exist there.
. ([scriptblock]::Create((Get-PspAssignmentSource -Path 'setup.ps1' -Variable '$script:SharedFunctionNames')))
try { $null = Get-PspFunctionSource -Path 'Microsoft.PowerShell_profile.ps1' -Name $script:SharedFunctionNames } catch { $problems += $_.Exception.Message }
if ($setup.IndexOf('$script:Bundle = Initialize-InstallBundle') -gt $setup.IndexOf('$installed = Invoke-SetupInstall')) { $problems += 'bundle verification does not come before installation' }
# A missing line (index -1) fails as well.
$verifyAt = $setup.IndexOf('$script:Bundle = Initialize-InstallBundle', [System.StringComparison]::Ordinal)
$installAt = $setup.IndexOf('$installed = Invoke-SetupInstall', [System.StringComparison]::Ordinal)
if ($verifyAt -lt 0 -or $installAt -lt 0 -or $verifyAt -gt $installAt) { $problems += 'bundle verification does not come before installation' }
if ($problems) { $problems | ForEach-Object { Write-Host "FAIL: $_" -ForegroundColor Red }; exit 1 }
Write-Host 'setup.ps1 structure OK' -ForegroundColor Green

Expand Down
26 changes: 16 additions & 10 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,18 @@ jobs:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
# Full history, so the next step can see whether the tagged commit is on main.
fetch-depth: 0

- name: Check that the tagged commit is on main
shell: bash
run: |
set -euo pipefail
# A tag on a commit that never reached main skipped review and CI, so it is not released.
if ! git merge-base --is-ancestor "${GITHUB_SHA}" origin/main; then
echo "::error::${GITHUB_SHA} is not on main. Tag a commit that is on main."
exit 1
fi

- name: Build release files from the tagged commit
shell: bash
Expand All @@ -47,17 +59,11 @@ jobs:
(cd dist && sha256sum $files > SHA256SUMS.txt)
hash() { sha256sum "dist/$1" | cut -d' ' -f1 | tr 'a-f' 'A-F'; }
bundle=$(printf 'profile:%s:theme:%s:terminal:%s' "$(hash Microsoft.PowerShell_profile.ps1)" "$(hash theme.json)" "$(hash terminal-config.json)" | sha256sum | cut -d' ' -f1 | tr 'a-f' 'A-F')
# Release notes: the CHANGELOG section for this version plus how to verify and install.
awk -v v="${version}" '$0 ~ "^## \\[" v "\\]" {found=1; next} found && /^## \[/ {exit} found {print}' CHANGELOG.md > notes.md
if [ ! -s notes.md ]; then
echo "::error::CHANGELOG.md has no section for ${version}"
exit 1
fi
# Release notes: how to verify and install, followed by the notes GitHub generates from the merged pull requests.
{
echo
echo "## Verify and install"
echo
echo "Each file's SHA-256 is in \`SHA256SUMS.txt\`; \`gh attestation verify <file> --repo ${GITHUB_REPOSITORY}\` checks that it was built here from this tag."
echo "Each file's SHA-256 is in \`SHA256SUMS.txt\`; \`gh attestation verify <file> --repo ${GITHUB_REPOSITORY} --source-ref refs/tags/${TAG} --signer-workflow ${GITHUB_REPOSITORY}/.github/workflows/release.yml\` checks that it was built by this workflow from this tag."
echo "\`setup.ps1 -Ref ${TAG}\` and \`Update-Profile -Ref ${TAG}\` check their downloads against \`SHA256SUMS.txt\` automatically."
echo "Install bundle hash (\`-ExpectedSha256\`): \`${bundle}\`"
echo
Expand All @@ -77,6 +83,6 @@ jobs:
TAG: ${{ github.ref_name }}
run: |
set -euo pipefail
# Upload the files to a draft first, so an immutable release is published complete.
gh release create "${TAG}" dist/* --repo "${GITHUB_REPOSITORY}" --draft --verify-tag --title "PowerShellPerfect ${TAG}" --notes-file notes.md
# Upload the files to a draft first, so the release is complete when it is published (required for immutable releases).
gh release create "${TAG}" dist/* --repo "${GITHUB_REPOSITORY}" --draft --verify-tag --title "PowerShellPerfect ${TAG}" --notes-file notes.md --generate-notes
gh release edit "${TAG}" --repo "${GITHUB_REPOSITORY}" --draft=false
8 changes: 8 additions & 0 deletions .github/workflows/scheduled.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,14 @@ jobs:
if (-not $entry) { throw 'empty response' }
} catch { $problems += "PSFzf $($pins.PSFzf) not found on the PowerShell Gallery" }
try { $null = Invoke-RestMethod "https://registry.npmjs.org/http-server/$($pins.HttpServer)" } catch { $problems += "http-server $($pins.HttpServer) not found on npm" }
# The portable oh-my-posh build pinned in the profile against that release's checksums.txt.
$ompSums = Join-Path $work 'omp-checksums.txt'
Invoke-WebRequest "https://github.com/JanDeDobbeleer/oh-my-posh/releases/download/v$($pins.OhMyPosh)/checksums.txt" -OutFile $ompSums
$omp = @{}
foreach ($line in Get-Content $ompSums) { if ($line -match '^([0-9a-fA-F]{64})\s+\*?(\S+)$') { $omp[$Matches[2]] = $Matches[1].ToUpperInvariant() } }
foreach ($asset in $pins.OhMyPoshSha256.Keys) {
if ($omp[$asset] -ne $pins.OhMyPoshSha256[$asset].ToUpperInvariant()) { $problems += "profile hash for $asset does not match oh-my-posh v$($pins.OhMyPosh)" }
}

# Newer upstream releases are reported, not failed.
foreach ($repo in 'ryanoasis/nerd-fonts', 'JanDeDobbeleer/oh-my-posh') {
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ Modules/
.vscode/
*.code-workspace
.idea/

# Local AI agent instructions (kept out of the repository)
CLAUDE.md
AGENTS.md
.claude/

# OS junk
Expand Down
1 change: 0 additions & 1 deletion .mailmap

This file was deleted.

36 changes: 0 additions & 36 deletions AGENTS.md

This file was deleted.

Loading
Loading