Skip to content

Releases.Tests.ps1: scope tag names with run ID and add AfterAll cleanup of releases and tags #592

@MariusStorhaug

Description

Releases.Tests.ps1 creates releases and tags on the shared test repository using hardcoded tag names (v1.0, v1.1, v1.2, v1.3, v1.4). No AfterAll cleanup removes these releases or their underlying git tags after the test context finishes.

Request

Current experience

Two categories of problem arise from the current design:

Sequential run collisions. Run N creates tag v1.0 on the shared repository. Run N+1 hits New-GitHubRelease -Tag 'v1.0' and fails because the tag already exists. The test New-GitHubRelease - Throws when tag already exists depends on a clean-slate repo where the tag was just created within this run — not a leftover from a previous run. On a persistent shared repository (the direction described in #590), this collision is guaranteed without cleanup.

Concurrent run collisions. Two concurrent workflow runs (e.g., two open PRs) both target the same persistent shared repository and race to create v1.0. The loser fails. Even without persistent repos, if GITHUB_RUN_ID were ever the same (impossible today, but a design fragility), the collision is identical.

No cleanup. The AfterAll block at the Context 'As <Type> using <Case> on <Target>' level currently only disconnects the GitHub account. It does not remove releases or git tags created during the test run. Releases and tags accumulate on the shared repository indefinitely, drifting its state across runs.

What is expected

  • Tags created during a test run are scoped so they cannot collide with tags from another run.
  • All releases (including drafts) and their underlying git tags created during a test run are removed by AfterAll, leaving the shared repository in the same state it was found in.
  • The test New-GitHubRelease - Throws when tag already exists continues to function correctly, asserting against the run-scoped tag created moments earlier in the same context.

Acceptance criteria

  • All tag strings in Releases.Tests.ps1 are suffixed with the run ID: "v1.0-$id", "v1.1-$id", "v1.2-$id", "v1.3-$id", "v1.4-$id".
  • The AfterAll at the auth-case Context level removes all releases on $repo and then removes all git tags whose names end with -$id, leaving no test artefacts on the shared repository.
  • Two concurrent runs targeting the same shared repository do not interfere with each other's release or tag operations.
  • The test New-GitHubRelease - Throws when tag already exists remains passing.

Environment

Regression

This issue was latent before #541. Each run previously created a uniquely named repository (containing the GITHUB_RUN_ID), so tag collisions between runs were impossible. With #541 consolidating to shared repositories, the risk became real. Moving to persistent repositories (#590) makes it a guaranteed failure on every sequential run.


Technical decisions

Tag scoping pattern: Append -$id to each hardcoded tag. This follows the same run-scoping convention used for secret names, variable names, and environment names elsewhere in the test suite. The $id variable is already set at the file BeforeAll level: $id = $env:GITHUB_RUN_ID.

Release cleanup: Get-GitHubRelease -Owner $Owner -Repository $repo -All | Remove-GitHubRelease -Confirm:$false. Removing all releases on a test-dedicated repository between test contexts is safe — no other test file writes releases, and the release sub-context assertions are self-contained within a single context run.

Tag cleanup: GitHub's REST API for deleting a release does not delete the underlying git tag. Tags must be deleted separately. Whether Remove-GitHubTag (or an equivalent function) exists in the module needs to be confirmed; if not, the direct Git refs API endpoint DELETE /repos/{owner}/{repo}/git/refs/tags/{tag} must be called. In either case, the cleanup filter is tags whose name ends with -$id to avoid touching any pre-existing tags on the repository.

Cleanup placement: AfterAll at the Context 'As <Type> using <Case> on <Target>' scope, after the existing account-disconnect step. This mirrors the pattern used in Secrets.Tests.ps1 and Variables.Tests.ps1 for their respective resource cleanup.


Implementation plan

Core changes

  • Suffix all five hardcoded tag literals with -$id throughout Releases.Tests.ps1: v1.0"v1.0-$id", v1.1"v1.1-$id", v1.2"v1.2-$id", v1.3"v1.3-$id", v1.4"v1.4-$id"
  • Add release cleanup to AfterAll: Get-GitHubRelease -Owner $Owner -Repository $repo -All -ErrorAction SilentlyContinue | Remove-GitHubRelease -Confirm:$false
  • Add tag cleanup to AfterAll: remove all git tags matching *-$id on $repo (using Remove-GitHubTag if available, otherwise direct refs API)

Verification

  • Confirm Remove-GitHubTag (or equivalent) exists in the module; if not, track a separate issue to add it
  • Run the release tests twice in sequence against the same repository and confirm the second run passes cleanly
  • Confirm the New-GitHubRelease - Throws when tag already exists test still passes with the scoped tag name

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    Status

    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions