Skip to content

Maintenance canary

Maintenance canary #1

Workflow file for this run

name: Maintenance canary
on:
schedule:
- cron: '17 7 * * 1'
workflow_dispatch:
inputs:
proposed_version:
description: Optional module version for the canary PR (for example, 0.7.0)
required: false
type: string
permissions:
contents: read
concurrency:
group: dependency-canary
cancel-in-progress: true
jobs:
resolve:
name: Resolve maintenance candidates
runs-on: windows-latest
outputs:
changed: ${{ steps.resolve.outputs.changed }}
version: ${{ steps.resolve.outputs.version }}
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Remove preinstalled build dependencies
shell: pwsh -NoLogo -NoProfile -ExecutionPolicy Bypass -Command "& '{0}'"
run: ./tools/Remove-BuildDependencies.ps1
- name: Resolve dependencies, refresh SQLite assets, and create candidate
id: resolve
shell: pwsh -NoLogo -NoProfile -ExecutionPolicy Bypass -Command "& '{0}'"
env:
PROPOSED_VERSION: ${{ inputs.proposed_version }}
run: |
$parameters = @{}
if (-not [string]::IsNullOrWhiteSpace($env:PROPOSED_VERSION)) {
$parameters.ProposedVersion = [version]$env:PROPOSED_VERSION
}
$result = ./tools/Update-DependencyPins.ps1 @parameters
"changed=$($result.Changed.ToString().ToLowerInvariant())" |
Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append
"version=$($result.ProposedVersion)" |
Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append
git diff --check
if ($LASTEXITCODE -ne 0) {
throw 'The dependency candidate contains whitespace errors.'
}
$patchPath = Join-Path $env:RUNNER_TEMP 'dependency-canary.patch'
git diff --binary "--output=$patchPath"
if ($LASTEXITCODE -ne 0) {
throw 'Unable to create the dependency candidate patch.'
}
$result |
ConvertTo-Json -Depth 5 |
Set-Content -LiteralPath (Join-Path $env:RUNNER_TEMP 'dependency-canary.json') -Encoding utf8
if (-not $result.Changed) {
@(
'### Dependency canary'
''
'Build dependencies and bundled SQLite runtimes already match the latest stable versions. No validation or pull request is required.'
) | Out-File -FilePath $env:GITHUB_STEP_SUMMARY -Encoding utf8 -Append
}
- name: Upload exact dependency candidate
if: steps.resolve.outputs.changed == 'true'
uses: actions/upload-artifact@v7
with:
name: dependency-canary
path: |
${{ runner.temp }}/dependency-canary.patch
${{ runner.temp }}/dependency-canary.json
if-no-files-found: error
validate:
name: Validate (${{ matrix.name }})
needs: resolve
if: needs.resolve.outputs.changed == 'true'
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
include:
- name: PowerShell 7
edition: powershell-7
- name: Windows PowerShell 5.1
edition: windows-powershell
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Download exact dependency candidate
uses: actions/download-artifact@v8
with:
name: dependency-canary
path: ${{ runner.temp }}/dependency-canary
- name: Apply dependency candidate
shell: pwsh -NoLogo -NoProfile -ExecutionPolicy Bypass -Command "& '{0}'"
run: |
$patchPath = Join-Path $env:RUNNER_TEMP 'dependency-canary/dependency-canary.patch'
if ((Get-Item -LiteralPath $patchPath).Length -gt 0) {
git apply --check $patchPath
git apply $patchPath
}
- name: Validate with PowerShell 7
if: matrix.edition == 'powershell-7'
shell: pwsh -NoLogo -NoProfile -ExecutionPolicy Bypass -Command "& '{0}'"
run: |
./tools/Remove-BuildDependencies.ps1
./tools/Test-DependencyCanary.ps1
./tools/Test-SqliteRuntimeUpdater.ps1
- name: Validate with Windows PowerShell 5.1
if: matrix.edition == 'windows-powershell'
shell: powershell -NoLogo -NoProfile -ExecutionPolicy Bypass -Command "& '{0}'"
run: |
./tools/Remove-BuildDependencies.ps1
./tools/Test-DependencyCanary.ps1
promote:
name: Open dependency canary PR
needs: [resolve, validate]
if: needs.resolve.outputs.changed == 'true' && needs.validate.result == 'success'
runs-on: windows-latest
permissions:
contents: write
pull-requests: write
steps:
- name: Checkout validated revision
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Download exact dependency candidate
uses: actions/download-artifact@v8
with:
name: dependency-canary
path: ${{ runner.temp }}/dependency-canary
- name: Commit candidate and create or update PR
shell: pwsh -NoLogo -NoProfile -ExecutionPolicy Bypass -Command "& '{0}'"
env:
GH_TOKEN: ${{ github.token }}
PROPOSED_VERSION: ${{ needs.resolve.outputs.version }}
run: |
$artifactPath = Join-Path $env:RUNNER_TEMP 'dependency-canary'
$patchPath = Join-Path $artifactPath 'dependency-canary.patch'
$metadataPath = Join-Path $artifactPath 'dependency-canary.json'
$branch = "chore/dependency-canary-$env:PROPOSED_VERSION"
$title = $branch
git apply --check $patchPath
git apply $patchPath
git checkout -b $branch
git config user.name 'github-actions[bot]'
git config user.email '41898282+github-actions[bot]@users.noreply.github.com'
git add --update
git commit -m "chore(deps): validate dependencies for v$env:PROPOSED_VERSION"
$remoteBranch = @(git ls-remote --heads origin "refs/heads/$branch")
if ($LASTEXITCODE -ne 0) {
throw "Unable to inspect the remote $branch branch."
}
if ($remoteBranch.Count -gt 0) {
git fetch origin "+refs/heads/$branch:refs/remotes/origin/$branch"
$expectedRemote = git rev-parse "refs/remotes/origin/$branch"
git push origin "HEAD:refs/heads/$branch" `
"--force-with-lease=refs/heads/$branch`:$expectedRemote"
} else {
git push --set-upstream origin "HEAD:refs/heads/$branch"
}
if ($LASTEXITCODE -ne 0) {
throw "Unable to push $branch."
}
$metadata = Get-Content -Raw -LiteralPath $metadataPath | ConvertFrom-Json
$dependencyVersions = @{}
foreach ($dependency in $metadata.InitializedDependencies.PSObject.Properties) {
$dependencyVersions[$dependency.Name] = $dependency.Value
}
foreach ($dependency in $metadata.RuntimeDependencies.PSObject.Properties) {
$dependencyVersions[$dependency.Name] = $dependency.Value
}
$dependencyRows = @(
$dependencyVersions.GetEnumerator() |
Sort-Object Key |
ForEach-Object { "| $($_.Key) | $($_.Value) |" }
)
$bodyPath = Join-Path $env:RUNNER_TEMP 'dependency-canary-pr.md'
@"
Automated maintenance canary for module version ``$env:PROPOSED_VERSION``.
The exact changes in this PR passed on clean GitHub-hosted Windows runners under:
- Windows PowerShell 5.1
- PowerShell 7
- Refreshed System.Data.SQLite and native SQLite assets for every supported runtime
- The generated module test suite, when the project exports ``New-LathModule``
| Dependency | Validated version |
| --- | --- |
$($dependencyRows -join "`n")
Merging this PR triggers the normal ``push`` workflow on the default branch. The publishing helper will publish only when ``ModuleVersion`` is newer than PSGallery.
"@ | Set-Content -LiteralPath $bodyPath -Encoding utf8
$existingPr = gh pr list --head $branch --state open --json number --jq '.[0].number'
if ($existingPr) {
gh pr edit $existingPr --title $title --body-file $bodyPath
} else {
gh pr create `
--base '${{ github.event.repository.default_branch }}' `
--head $branch `
--title $title `
--body-file $bodyPath
}