Skip to content

CI: automate release with GitHub Actions + build provenance attestation #1

@backmind

Description

@backmind

Why

PSAliasFinder ships as a binary module (compiled .NET 8 DLL). For users with supply-chain hygiene, that's an opaque artifact published by a relatively unknown maintainer — they can't easily verify what the DLL does or that it matches the source on this repo.

Mitigation: move the build + publish to GitHub Actions and emit a build provenance attestation so anyone can verify cryptographically that the DLL on the PowerShell Gallery was produced by Actions on this repo at a specific tagged commit. Also moves the PSGallery API key off the maintainer's local machine into a GitHub Secret, removing a manual-handling failure mode.

Outcome

  • Pushing a tag like 2.0.2 triggers a workflow that:
    1. Builds the DLL via the existing build.ps1.
    2. Generates a build provenance attestation against the DLL.
    3. Stages a clean ship layout (no src/, no tests/, no demo gif).
    4. Publishes to PSGallery using a stored API key.
    5. Creates a GitHub Release with auto-generated notes and the DLL attached.
  • End users can verify locally:
    Save-Module PSAliasFinder -RequiredVersion 2.0.2 -Path .
    gh attestation verify ./PSAliasFinder/2.0.2/bin/PSAliasFinder.dll --repo backmind/PSAliasFinder

One-time setup (manual, before the workflow runs)

a) Generate a scoped PSGallery API key

  1. Sign in to https://www.powershellgallery.com/account/apikeys.
  2. Create, with:
    • Key Name: PSAliasFinder-CI
    • Expires: 365 days (max).
    • Scopes: Push only new package versions of existing packages (sufficient because 2.0.x is already published; new keys can also pick Push new packages and package versions if needed).
    • Glob Pattern: PSAliasFinder (limits the key to this module).
  3. Copy the key (only shown once).

b) Add the key as a repo secret

  1. Go to https://github.com/backmind/PSAliasFinder/settings/secrets/actions.
  2. New repository secret:
    • Name: PSGALLERY_API_KEY
    • Value: paste the key from (a).

Workflow file

Save as .github/workflows/release.yml:

name: Release

on:
  push:
    tags:
      - '[0-9]+.[0-9]+.[0-9]+'

permissions:
  contents: write       # for GitHub Release creation
  id-token: write       # required by attest-build-provenance
  attestations: write   # required by attest-build-provenance

jobs:
  build-and-publish:
    runs-on: windows-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-dotnet@v4
        with:
          dotnet-version: '8.0.x'

      - name: Build
        shell: pwsh
        run: ./build.ps1

      - name: Generate build provenance attestation
        uses: actions/attest-build-provenance@v1
        with:
          subject-path: bin/PSAliasFinder.dll

      - name: Stage clean ship layout
        shell: pwsh
        run: |
          $ship = Join-Path $env:RUNNER_TEMP 'ship/PSAliasFinder'
          New-Item -ItemType Directory -Path "$ship/bin" -Force | Out-Null
          Copy-Item PSAliasFinder.psd1, PSAliasFinder.psm1, README.md, LICENSE $ship
          Copy-Item bin/PSAliasFinder.dll "$ship/bin/"
          "SHIP_PATH=$ship" | Out-File $env:GITHUB_ENV -Append

      - name: Publish to PowerShell Gallery
        shell: pwsh
        env:
          PSGALLERY_API_KEY: ${{ secrets.PSGALLERY_API_KEY }}
        run: |
          Publish-Module -Path $env:SHIP_PATH -NuGetApiKey $env:PSGALLERY_API_KEY

      - name: Create GitHub Release
        uses: softprops/action-gh-release@v2
        with:
          name: PSAliasFinder ${{ github.ref_name }}
          generate_release_notes: true
          files: bin/PSAliasFinder.dll

Steps to land this

  1. Manual setup (a) and (b) above. ~5 minutes.
  2. Create the workflow file in a feature branch, push, open a PR.
  3. Test by tagging a 0.0.0-prefixed tag on the branch — actually no, tags trigger the workflow only on default branch. To test the workflow without publishing, comment out the Publish-Module step temporarily and push a 99.99.99-test tag.
  4. Once the dry-run is clean, remove the comment and push a real 2.0.2 tag (next time there's something to release).
  5. Update README to mention the attestation: add a "Verifying the build" section pointing at gh attestation verify.

References

Out of scope

  • Authenticode code signing (separate higher-cost path; Microsoft Trusted Signing or a commercial cert from DigiCert/Sectigo). Could be added later if a corporate user requests it.
  • Sigstore signing (emerging, not yet integrated with PSGallery verification).
  • Strong-name signing the assembly (legacy .NET concept; not relevant for this module).

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions