From 36605d1c8f94ec108828ee810bcf4edd7129c477 Mon Sep 17 00:00:00 2001 From: Raimund Andree Date: Mon, 5 Oct 2026 00:03:36 +0200 Subject: [PATCH] ci: keep pull request runs read-only and delay Dependabot proposals Resolves the review of this branch (one Major, three Minor findings): - Major: a Dependabot pull request runs the action versions it proposes before anyone reviews them, and the wiki job of that run held contents: write. The wiki job is now read-only and only previews the changed pages; the new publish-wiki job, the only one besides release with write access, publishes for master alone, after a merge. dependabot.yml waits 7 days (cooldown) before it proposes a release. - Minor: Repository.Tests.ps1 asserts that it found the 3 packages.config files, checks version 2 and the directory, accepts either quote style, and checks that the "*" pattern sits under groups (11 tests; the cooldown test failed before the change). Memory Bank: Decision 11 and techContext.md describe the two wiki jobs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: AI Assistant --- .github/dependabot.yml | 4 ++ .github/workflows/ci.yml | 37 +++++++++++++++++-- .memory-bank/decisions/0011-github-actions.md | 4 +- .memory-bank/techContext.md | 10 +++-- Tests/Repository.Tests.ps1 | 17 ++++++++- 5 files changed, 61 insertions(+), 11 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 8c05421..8733b05 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -7,6 +7,10 @@ updates: directory: / schedule: interval: weekly + # Waits a week before it proposes a new release, so that a compromised + # release is more likely to be found and withdrawn first. + cooldown: + default-days: 7 commit-message: prefix: ci groups: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ee5e7d6..fc25332 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -149,10 +149,10 @@ jobs: 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. + # Shows the pages that would change. Read-only: on pull requests, including + # those of Dependabot, this job runs code that nobody has reviewed yet. permissions: - contents: write + contents: read steps: - name: Check out the repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 @@ -179,10 +179,39 @@ jobs: @('### Wiki', '', 'The wiki is up to date.') } Add-Content -LiteralPath $env:GITHUB_STEP_SUMMARY -Value $summary + + publish-wiki: + name: Publish the wiki + needs: wiki + if: github.ref == 'refs/heads/master' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') + runs-on: ubuntu-latest + timeout-minutes: 10 + # This job can write, so it runs only for master, after the changes were + # reviewed and merged. + 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 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 }} diff --git a/.memory-bank/decisions/0011-github-actions.md b/.memory-bank/decisions/0011-github-actions.md index 741309a..e664e03 100644 --- a/.memory-bank/decisions/0011-github-actions.md +++ b/.memory-bank/decisions/0011-github-actions.md @@ -21,7 +21,9 @@ source: maintainer decision after work package 4 checks appear on the pull request without a third-party service. - Consequences: `Docs` stays the only source (Decision 9); the wiki is a generated mirror, and edits made in the wiki are overwritten. Only the - `wiki` job has `contents: write`; actions are pinned by commit SHA. Test + `publish-wiki` job, which runs for `master` alone, has `contents: write`; + the `wiki` job that previews pull requests, including Dependabot's, is + read-only (2026-10-04). Actions are pinned by commit SHA. Test results appear in the job summary and as the `test-results` artifact. - Rejected: a hand-maintained wiki next to `Docs`, publishing the wiki by hand at release time, and keeping AppVeyor for build and tests. diff --git a/.memory-bank/techContext.md b/.memory-bank/techContext.md index 7e299b5..9f97a6f 100644 --- a/.memory-bank/techContext.md +++ b/.memory-bank/techContext.md @@ -118,15 +118,17 @@ source: repository evidence `Get-MarkdownLink -BrokenOnly`; 03 regenerate the help file and fail on `git status --porcelain -- NTFSSecurity/en-US`; 04 `Invoke-Tests.ps1` in Windows PowerShell 5.1 and in PowerShell 7. Job `wiki` on `ubuntu-latest` - clones the wiki (`gh auth setup-git` with the built-in token), runs - `Export-WikiContent.ps1`, lists the changed pages in the job summary, and - publishes from `master` only. After the tests, `build` runs + (read-only) clones the wiki (`gh auth setup-git` with the built-in token), + runs `Export-WikiContent.ps1`, and lists the changed pages in the job + summary; job `publish-wiki` (`contents: write`) repeats that and publishes, + for `master` only. After the tests, `build` runs `New-ModulePackage.ps1` and uploads the artifact `packages` (nupkg and `NTFSSecurity.zip`). Job `release` runs only for tags matching `[0-9]+.[0-9]+.[0-9]+` or `[0-9]+.[0-9]+.[0-9]+-*`, in the environment `powershell-gallery` (secret `PSGALLERY_API_KEY`); see Decision 12. Actions are pinned by commit SHA: `actions/checkout` v7.0.1, - `actions/upload-artifact` v7.0.1, `actions/download-artifact` v8.0.1. + `actions/upload-artifact` v7.0.1, `actions/download-artifact` v8.0.1; + Dependabot proposes updates weekly, one week after a release. - Packaging needs PSResourceGet (`Compress-PSResource`, PowerShell 7.4 or later); its tests skip in Windows PowerShell. Dry run locally: run `New-ModulePackage.ps1` against `NTFSSecurity\bin\Release` into diff --git a/Tests/Repository.Tests.ps1 b/Tests/Repository.Tests.ps1 index 8eb4a27..4f519e0 100644 --- a/Tests/Repository.Tests.ps1 +++ b/Tests/Repository.Tests.ps1 @@ -29,6 +29,10 @@ Describe 'NuGet packages of the projects' { $hintPathVersions | Should -HaveCount 1 } + It 'Should find the packages.config of the three projects that reference AlphaFS' -ForEach @(@{ Configs = $packageConfigs }) { + $Configs | Should -HaveCount 3 + } + It 'Should list the AlphaFS version of the HintPaths in \packages.config' -ForEach $packageConfigs { $package = ([xml] (Get-Content -LiteralPath $Path -Raw)).packages.package | Where-Object -Property id -EQ -Value 'AlphaFS' @@ -41,6 +45,7 @@ Describe 'Dependabot configuration' { BeforeAll { $configPath = Join-Path -Path $PSScriptRoot -ChildPath '..\.github\dependabot.yml' $lines = if (Test-Path -LiteralPath $configPath) { Get-Content -LiteralPath $configPath } else { @() } + $raw = $lines -join "`n" $ecosystems = @($lines | Select-String -Pattern '^\s*-\s*package-ecosystem:\s*"?([\w-]+)"?\s*$' | ForEach-Object -Process { $_.Matches[0].Groups[1].Value }) } @@ -49,6 +54,11 @@ Describe 'Dependabot configuration' { $configPath | Should -Exist } + It 'Should use version 2 of the format and the root folder of the repository' { + $lines -match '^version:\s*2\s*$' | Should -HaveCount 1 + $lines -match '^\s+directory:\s*"?/"?\s*$' | Should -HaveCount 1 + } + It 'Should update only the actions of the CI workflow' { $ecosystems | Should -BeExactly @('github-actions') } @@ -57,8 +67,11 @@ Describe 'Dependabot configuration' { $lines -match '^\s+interval:\s*"?weekly"?\s*$' | Should -HaveCount 1 } + It 'Should wait at least a week before it proposes a new release' { + $raw | Should -Match '(?m)^\s+cooldown:\s*\n\s+default-days:\s*([7-9]|[1-9]\d+)\s*$' + } + It 'Should group all updates into one pull request' { - $lines -match '^\s+groups:\s*$' | Should -HaveCount 1 - $lines -match '^\s+-\s*"\*"\s*$' | Should -HaveCount 1 + $raw | Should -Match '(?m)^\s+groups:\s*\n\s+[\w-]+:\s*\n\s+patterns:\s*\n\s+-\s*["'']\*["'']\s*$' } }