mirror of https://github.com/raandree/NTFSSecurity
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
299 lines
13 KiB
299 lines
13 KiB
# Builds the NTFSSecurity module from source, checks that the cmdlet
|
|
# documentation in Docs/Cmdlets and the help file generated from it match the
|
|
# cmdlets of that build, runs the Pester tests in Windows PowerShell 5.1 and
|
|
# PowerShell 7, and builds the packages. From master, it publishes Docs to the
|
|
# GitHub wiki. For a version tag, such as 5.0.0 or 5.0.0-rc1, it publishes the
|
|
# package to the PowerShell Gallery and creates the GitHub release; see
|
|
# Docs/Contributing/05-Releasing.md.
|
|
name: CI
|
|
|
|
on:
|
|
pull_request:
|
|
push:
|
|
branches:
|
|
- master
|
|
tags:
|
|
- '[0-9]+.[0-9]+.[0-9]+'
|
|
- '[0-9]+.[0-9]+.[0-9]+-*'
|
|
workflow_dispatch:
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
concurrency:
|
|
group: ci-${{ github.ref }}
|
|
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
|
|
|
jobs:
|
|
build:
|
|
name: Build and test
|
|
runs-on: windows-2025
|
|
timeout-minutes: 30
|
|
steps:
|
|
- name: Keep Windows line endings in the working tree
|
|
run: git config --global core.autocrlf true
|
|
|
|
- name: Check out the repository
|
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Install platyPS, MarkdownLinkCheck, and Pester
|
|
shell: powershell
|
|
run: |
|
|
[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12
|
|
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force | Out-Null
|
|
# Installed for all users, so that PowerShell 7 finds the modules, too
|
|
Install-Module -Name platyPS -RequiredVersion 0.14.2 -Scope AllUsers -Force
|
|
Install-Module -Name MarkdownLinkCheck -RequiredVersion 0.2.0 -Scope AllUsers -Force
|
|
# The image includes Pester 3.4.0, which is signed by a different publisher.
|
|
Install-Module -Name Pester -RequiredVersion 5.7.1 -Scope AllUsers -Force -SkipPublisherCheck
|
|
|
|
- name: Restore the NuGet packages
|
|
shell: powershell
|
|
run: |
|
|
nuget restore NTFSSecurity\packages.config -PackagesDirectory packages -NonInteractive
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "NuGet failed with exit code $LASTEXITCODE."
|
|
}
|
|
nuget restore Security2\packages.config -PackagesDirectory packages -NonInteractive
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "NuGet failed with exit code $LASTEXITCODE."
|
|
}
|
|
# Provides the .NET Framework 4.5.2 reference assemblies, so the build does
|
|
# not depend on a targeting pack installed on the runner.
|
|
nuget install Microsoft.NETFramework.ReferenceAssemblies.net452 -Version 1.0.3 -OutputDirectory packages -NonInteractive
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "NuGet failed with exit code $LASTEXITCODE."
|
|
}
|
|
|
|
- name: Build the module
|
|
id: build
|
|
shell: powershell
|
|
run: |
|
|
# MSBuild isn't on the path of the runner; vswhere finds the one of Visual Studio.
|
|
$vswhere = Join-Path -Path ${env:ProgramFiles(x86)} -ChildPath 'Microsoft Visual Studio\Installer\vswhere.exe'
|
|
$msbuild = & $vswhere -latest -requires Microsoft.Component.MSBuild -find 'MSBuild\**\Bin\MSBuild.exe' | Select-Object -First 1
|
|
if (-not $msbuild) {
|
|
throw 'MSBuild was not found.'
|
|
}
|
|
$referenceAssemblies = "$env:GITHUB_WORKSPACE\packages\Microsoft.NETFramework.ReferenceAssemblies.net452.1.0.3\build"
|
|
& $msbuild NTFSSecurity\NTFSSecurity.csproj /nologo /verbosity:minimal /p:Configuration=Release "/p:TargetFrameworkRootPath=$referenceAssemblies" "/p:FrameworkPathOverride=$referenceAssemblies\.NETFramework\v4.5.2"
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "MSBuild failed with exit code $LASTEXITCODE."
|
|
}
|
|
|
|
- name: Check the documentation against the build
|
|
shell: powershell
|
|
run: |
|
|
Import-Module -Name platyPS -RequiredVersion 0.14.2
|
|
Import-Module -Name MarkdownLinkCheck -RequiredVersion 0.2.0
|
|
Import-Module -Name .\NTFSSecurity\bin\Release\NTFSSecurity.psd1 -Force
|
|
|
|
# 01. Test that the documentation matches the cmdlets built from source
|
|
Update-MarkdownHelp -Path ./Docs/Cmdlets | Out-Null
|
|
$diff = git diff -- Docs/Cmdlets
|
|
if ($diff) {
|
|
throw "Help is not up-to-date, run Update-MarkdownHelp: $diff"
|
|
}
|
|
|
|
# 02. Verify hyperlinks
|
|
$brokenLinks = Get-MarkdownLink -Path .\Docs\ -BrokenOnly
|
|
if ($brokenLinks) {
|
|
throw "Found broken hyperlinks $brokenLinks"
|
|
}
|
|
|
|
# 03. Test that the help file of the module matches the documentation
|
|
New-ExternalHelp -Path ./Docs/Cmdlets -OutputPath ./NTFSSecurity/en-US -Force | Out-Null
|
|
$helpChanges = git status --porcelain -- NTFSSecurity/en-US
|
|
if ($helpChanges) {
|
|
throw "The help file is not up-to-date, run New-ExternalHelp -Path .\Docs\Cmdlets -OutputPath .\NTFSSecurity\en-US -Force: $helpChanges"
|
|
}
|
|
|
|
# 04. Run the Pester tests against the build, also when the documentation check failed
|
|
- name: Run the tests in Windows PowerShell 5.1
|
|
if: ${{ !cancelled() && steps.build.outcome == 'success' }}
|
|
shell: powershell
|
|
run: .\.github\scripts\Invoke-Tests.ps1 -ResultPath TestResults\WindowsPowerShell.xml -Title 'Windows PowerShell 5.1'
|
|
|
|
- name: Run the tests in PowerShell 7
|
|
if: ${{ !cancelled() && steps.build.outcome == 'success' }}
|
|
shell: pwsh
|
|
run: ./.github/scripts/Invoke-Tests.ps1 -ResultPath TestResults/PowerShell7.xml -Title 'PowerShell 7'
|
|
|
|
- name: Upload the test results
|
|
if: ${{ !cancelled() }}
|
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
with:
|
|
name: test-results
|
|
path: TestResults/
|
|
if-no-files-found: ignore
|
|
|
|
# Only the files of the FileList, without debug symbols or other build output
|
|
- name: Build the packages
|
|
shell: pwsh
|
|
run: ./.github/scripts/New-ModulePackage.ps1 -BuildPath ./NTFSSecurity/bin/Release -DestinationPath ./out | Format-List
|
|
|
|
- name: Upload the packages
|
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
with:
|
|
name: packages
|
|
path: |
|
|
out/*.nupkg
|
|
out/NTFSSecurity.zip
|
|
if-no-files-found: error
|
|
|
|
wiki:
|
|
name: Wiki
|
|
needs: build
|
|
if: github.ref_type != 'tag'
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 10
|
|
# This job can write: it publishes the wiki from master. On pull requests,
|
|
# it shows the pages that would change.
|
|
permissions:
|
|
contents: write
|
|
steps:
|
|
- name: Check out the repository
|
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Generate the wiki pages
|
|
shell: pwsh
|
|
env:
|
|
GH_TOKEN: ${{ github.token }}
|
|
run: |
|
|
gh auth setup-git
|
|
$wiki = Join-Path -Path $env:RUNNER_TEMP -ChildPath 'wiki'
|
|
git clone --quiet --depth 1 "$env:GITHUB_SERVER_URL/$env:GITHUB_REPOSITORY.wiki.git" $wiki
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "Cloning the wiki failed with exit code $LASTEXITCODE."
|
|
}
|
|
./.github/scripts/Export-WikiContent.ps1 -Path ./Docs -DestinationPath $wiki -RepositoryUrl "$env:GITHUB_SERVER_URL/$env:GITHUB_REPOSITORY"
|
|
git -C $wiki add --all
|
|
$changes = @(git -C $wiki diff --cached --name-status)
|
|
$summary = if ($changes) {
|
|
@('### Wiki', '', 'Changed pages (A added, M modified, D deleted):', '', '```text') + $changes + @('```')
|
|
} else {
|
|
@('### Wiki', '', 'The wiki is up to date.')
|
|
}
|
|
Add-Content -LiteralPath $env:GITHUB_STEP_SUMMARY -Value $summary
|
|
Add-Content -LiteralPath $env:GITHUB_ENV -Value "WIKI_PATH=$wiki"
|
|
|
|
- name: Publish the wiki
|
|
if: ${{ github.ref == 'refs/heads/master' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') }}
|
|
shell: pwsh
|
|
env:
|
|
GH_TOKEN: ${{ github.token }}
|
|
run: |
|
|
git -C $env:WIKI_PATH diff --cached --quiet
|
|
if ($LASTEXITCODE -eq 0) {
|
|
'The wiki is up to date.'
|
|
exit 0
|
|
}
|
|
git -C $env:WIKI_PATH -c user.name='github-actions[bot]' -c user.email='41898282+github-actions[bot]@users.noreply.github.com' commit --quiet --message "Update from $env:GITHUB_SHA"
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "Committing the wiki failed with exit code $LASTEXITCODE."
|
|
}
|
|
git -C $env:WIKI_PATH push --quiet
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "Publishing the wiki failed with exit code $LASTEXITCODE."
|
|
}
|
|
|
|
release:
|
|
name: Release
|
|
needs: build
|
|
if: github.ref_type == 'tag'
|
|
runs-on: windows-2025
|
|
timeout-minutes: 15
|
|
# The API key of the PowerShell Gallery is a secret of this environment, so
|
|
# only this job can read it. The job can write to create the GitHub release.
|
|
environment: powershell-gallery
|
|
permissions:
|
|
contents: write
|
|
steps:
|
|
- name: Check out the repository
|
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
with:
|
|
fetch-depth: 0
|
|
persist-credentials: false
|
|
|
|
- name: Download the packages
|
|
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
with:
|
|
name: packages
|
|
path: out
|
|
|
|
- name: Check the release
|
|
id: release
|
|
shell: pwsh
|
|
run: |
|
|
$release = ./.github/scripts/Get-ReleaseInfo.ps1 -ManifestPath ./NTFSSecurity/NTFSSecurity.psd1 -ChangelogPath ./CHANGELOG.md
|
|
if ($env:GITHUB_REF_NAME -cne $release.Version) {
|
|
throw "The tag $env:GITHUB_REF_NAME doesn't match the version $($release.Version) in the module manifest."
|
|
}
|
|
git merge-base --is-ancestor $env:GITHUB_SHA origin/master
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "The tag $env:GITHUB_REF_NAME doesn't point to a commit on master."
|
|
}
|
|
$package = "out/NTFSSecurity.$($release.Version).nupkg"
|
|
if (-not (Test-Path -LiteralPath $package) -or -not (Test-Path -LiteralPath 'out/NTFSSecurity.zip')) {
|
|
throw "The packages of $($release.Version) are missing."
|
|
}
|
|
$today = (Get-Date).ToUniversalTime().Date
|
|
if (-not $release.IsPrerelease -and $release.Date -ne $today) {
|
|
"::warning::CHANGELOG.md dates $($release.Version) $($release.Date.ToString('yyyy-MM-dd')), but it is released on $($today.ToString('yyyy-MM-dd'))."
|
|
}
|
|
$notes = Join-Path -Path $env:RUNNER_TEMP -ChildPath 'release-notes.md'
|
|
Set-Content -LiteralPath $notes -Value $release.Notes -Encoding utf8NoBOM
|
|
Add-Content -LiteralPath $env:GITHUB_OUTPUT -Value @(
|
|
"version=$($release.Version)"
|
|
"prerelease=$($release.IsPrerelease.ToString().ToLowerInvariant())"
|
|
"package=$package"
|
|
"notes=$notes"
|
|
)
|
|
|
|
# Publishes the package that the build job built and tested. A rerun skips
|
|
# a version that the PowerShell Gallery already has.
|
|
- name: Publish to the PowerShell Gallery
|
|
shell: pwsh
|
|
env:
|
|
PSGALLERY_API_KEY: ${{ secrets.PSGALLERY_API_KEY }}
|
|
RELEASE_VERSION: ${{ steps.release.outputs.version }}
|
|
RELEASE_PACKAGE: ${{ steps.release.outputs.package }}
|
|
run: |
|
|
if (-not $env:PSGALLERY_API_KEY) {
|
|
throw 'The secret PSGALLERY_API_KEY of the environment powershell-gallery is not set.'
|
|
}
|
|
$published = Find-PSResource -Name NTFSSecurity -Version $env:RELEASE_VERSION -Prerelease -Repository PSGallery -ErrorAction SilentlyContinue
|
|
if ($published) {
|
|
"NTFSSecurity $env:RELEASE_VERSION is already in the PowerShell Gallery."
|
|
exit 0
|
|
}
|
|
Publish-PSResource -NupkgPath $env:RELEASE_PACKAGE -Repository PSGallery -ApiKey $env:PSGALLERY_API_KEY
|
|
|
|
- name: Create the GitHub release
|
|
shell: pwsh
|
|
env:
|
|
GH_TOKEN: ${{ github.token }}
|
|
RELEASE_VERSION: ${{ steps.release.outputs.version }}
|
|
RELEASE_PRERELEASE: ${{ steps.release.outputs.prerelease }}
|
|
RELEASE_NOTES: ${{ steps.release.outputs.notes }}
|
|
run: |
|
|
gh release view $env:RELEASE_VERSION --repo $env:GITHUB_REPOSITORY *> $null
|
|
if ($LASTEXITCODE -eq 0) {
|
|
"The GitHub release $env:RELEASE_VERSION exists."
|
|
exit 0
|
|
}
|
|
$arguments = @(
|
|
'release', 'create', $env:RELEASE_VERSION, 'out/NTFSSecurity.zip', '--repo', $env:GITHUB_REPOSITORY,
|
|
'--title', $env:RELEASE_VERSION, '--notes-file', $env:RELEASE_NOTES, '--verify-tag'
|
|
)
|
|
if ($env:RELEASE_PRERELEASE -eq 'true') {
|
|
$arguments += '--prerelease'
|
|
}
|
|
gh @arguments
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "Creating the GitHub release failed with exit code $LASTEXITCODE."
|
|
}
|
|
|