Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
3eba878
Reproduce publication without source-bound preflight
MariusStorhaug Oct 31, 2026
2607da2
Bind immutable publication claims to source and tested bytes
MariusStorhaug Oct 31, 2026
6b5ffcd
Verify publication resources and create version claims atomically
MariusStorhaug Oct 31, 2026
ee65fa7
Preflight Gallery writes and preserve release-side ownership rechecks
MariusStorhaug Oct 31, 2026
c3b9ff4
Stop version resolution on unverifiable Gallery reads
MariusStorhaug Oct 31, 2026
84fcb9c
Isolate artifact fixtures for shuffled action tests
MariusStorhaug Oct 31, 2026
4cf52d8
Document source-bound publication and immutable retry requirements
MariusStorhaug Oct 31, 2026
cb56b27
Reject invalid producing context and changed claims before release mu…
MariusStorhaug Oct 31, 2026
20578d1
Require verified prerelease enumeration metadata before choosing a co…
MariusStorhaug Oct 31, 2026
3405467
Preserve malformed JSON array shape and literal artifact filenames
MariusStorhaug Oct 31, 2026
aa86256
Reserve immutable module versions independently of release tag prefixes
MariusStorhaug Oct 31, 2026
dc78ee2
Document shared package ownership and tested version binding
MariusStorhaug Oct 31, 2026
6254d34
Reproduce lost release tags during shared publication reservation
MariusStorhaug Oct 31, 2026
474d094
Reject observed tag changes during shared module version reservation
MariusStorhaug Oct 31, 2026
2afb929
Reproduce coerced provenance and inconsistent release archive proof
MariusStorhaug Oct 31, 2026
131c30b
Reproduce original event context projection before publisher validation
MariusStorhaug Oct 31, 2026
e59ac33
Reject projected provenance and inconsistent release archive claims
MariusStorhaug Oct 31, 2026
3faf9fb
Reproduce terminal provenance, raw metadata and module ref compatibil…
MariusStorhaug Oct 31, 2026
8ed2377
Require terminal ownership proof and typed publication metadata
MariusStorhaug Oct 31, 2026
bf242f2
Reproduce unverified draft metadata before publication
MariusStorhaug Oct 31, 2026
eb3eb0c
Require explicit published release status before publication writes
MariusStorhaug Oct 31, 2026
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
28 changes: 26 additions & 2 deletions .github/actions/Publish-PSModule/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
# Publish-PSModule

Publishes a pre-versioned PowerShell module artifact to the PowerShell Gallery. GitHub Release creation is intentionally handled by the separate [Release-PSModule](../Release-PSModule/README.md) action.
Publishes a pre-versioned, tested PowerShell module artifact to the PowerShell Gallery after source-bound ownership preflight. GitHub Release creation is handled by the separate [Release-PSModule](../Release-PSModule/README.md) action.

The publisher verifies the original source, exact resolved tag/version, producing repository/PR or direct-release context, and tested bytes before an external versioned-artifact mutation. An absent Gallery module/version is reserved at `PSModule-Publication/<escaped-lowercase-module>/<lowercase-version>`, independently of the configured release-tag prefix. Module-name dots are encoded as `%2e` so valid dotted names cannot produce Git-invalid `..` or `.lock` components. The shared coordinate and release tag reference the same immutable annotated source/context/file-tree/ZIP claim. Existing tags are never updated or deleted; the package ownership coordinate is retained for immutable Gallery proof.

An observed release tag must remain unchanged through shared coordinate creation. If it disappears or is replaced during that reservation, the attempt fails instead of recreating it. A valid partial shared claim can still create an absent release tag that has never been observed in the attempt.

An existing Gallery package is retained only when its raw nupkg payload matches that proof and the tested artifact. Package code is never imported to establish ownership. Unknown legacy proof, foreign tags/releases/assets, changed claims, authentication errors, and API failures stop publication explicitly.

Provenance must contain one original JSON object with scalar proof fields; arrays are not projected into valid identities. The ZIP's exact bytes and canonical payload digest are verified together against the tested file tree before a claim or Gallery write. Original event PR context is validated before normalized fields are selected.

GitHub resource responses must have valid object/scalar shapes, while verified empty tag collections remain valid absence. An existing PR-produced stable or prerelease release requires its producing-context footer; unreadable terminal markers are errors even when indented or inline. Unknown legacy PR release context is not inferred from a matching tag.

Existing releases must explicitly return scalar boolean `draft: false`. Missing, null, string, or array status is unknown published-release proof and stops before Gallery publication or a resumed asset upload.

## Inputs

Expand All @@ -10,6 +22,10 @@ Publishes a pre-versioned PowerShell module artifact to the PowerShell Gallery.
| `ModulePath` | Path containing the built `<Name>/` module directory. | No | `.PSModule/module` |
| `ArtifactName` | Name of the module artifact to download. | No | `module` |
| `PSGALLERY_API_KEY` | PowerShell Gallery API key. | Yes | N/A |
| `ReleaseTag` | Exact tag already resolved as `Publish.Module.Resolution.FullVersion`. | Yes | N/A |
| `VersionPrefix` | Existing resolver prefix used to bind `ReleaseTag` to the tested module version. | No | `v` |
| `CommitSha` | Immutable commit that produced the tested artifact. | No | Original workflow `GITHUB_SHA` |
| `PullRequest` | Normalized producing-PR context; empty for a direct stable release. | No | Empty |
| `WhatIf` | Logs publishing operations without publishing the module. | No | `false` |
| `WorkingDirectory` | Directory where the publishing script runs. | No | `.` |

Expand All @@ -27,6 +43,14 @@ This action does not provide outputs.
ModulePath: .PSModule/module
ArtifactName: module
PSGALLERY_API_KEY: ${{ secrets.PSGALLERY_API_KEY }}
ReleaseTag: ${{ fromJson(inputs.Settings).Publish.Module.Resolution.FullVersion }}
VersionPrefix: ${{ fromJson(inputs.Settings).Publish.Module.VersionPrefix }}
CommitSha: ${{ fromJson(inputs.Settings).Context.CommitSha }}
PullRequest: ${{ toJson(fromJson(inputs.Settings).Context.PullRequest) }}
```

Use [Release-PSModule](../Release-PSModule/README.md) in a separate workflow step to create the GitHub release from the same artifact.
Provide `GH_TOKEN` with contents-write access scoped to the consumer repository. The reusable workflow supplies its existing GitHub App token and resolved context internally.

NuGet-reserved container metadata paths are rejected in the tested candidate before a claim or upload, using the same path classification as raw package verification. A published package without its shared module/version coordinate is unproven; the publisher does not fabricate that ownership record on retry.

Use [Release-PSModule](../Release-PSModule/README.md) in a separate step to create the GitHub release from the same source and tested artifact. A retry must retain the original coordinates and bytes; unproven legacy publication requires reviewed forward-only recovery, not numeric guessing, retagging, or metadata changes.
14 changes: 14 additions & 0 deletions .github/actions/Publish-PSModule/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,17 @@ inputs:
description: Normalized pull request context JSON from Get-PSModuleSettings.
required: false
default: ''
ReleaseTag:
description: Exact GitHub tag already resolved for the tested module artifact.
required: true
VersionPrefix:
description: Configured prefix used by the existing resolver; verifies the tag against the tested module version.
required: false
default: v
CommitSha:
description: Immutable commit that produced the tested module artifact; defaults to the original workflow SHA.
required: false
default: ''
WhatIf:
description: If specified, the action will only log the changes it would make, but will not publish the module.
required: false
Expand Down Expand Up @@ -55,5 +66,8 @@ runs:
PSMODULE_PUBLISH_PSMODULE_INPUT_ModulePath: ${{ inputs.ModulePath }}
PSMODULE_PUBLISH_PSMODULE_INPUT_PSGALLERY_API_KEY: ${{ inputs.PSGALLERY_API_KEY }}
PSMODULE_PUBLISH_PSMODULE_INPUT_PullRequest: ${{ inputs.PullRequest }}
PSMODULE_PUBLISH_PSMODULE_INPUT_ReleaseTag: ${{ inputs.ReleaseTag }}
PSMODULE_PUBLISH_PSMODULE_INPUT_VersionPrefix: ${{ inputs.VersionPrefix }}
PSMODULE_PUBLISH_PSMODULE_INPUT_CommitSha: ${{ inputs.CommitSha || github.sha }}
PSMODULE_PUBLISH_PSMODULE_INPUT_WhatIf: ${{ inputs.WhatIf }}
run: ${{ github.action_path }}/src/publish.ps1
Loading
Loading