Files
ReleaseKit/docs/roadmap/race.md

5.8 KiB

Roadmap: synchronize delivery test fixtures

Status: complete; fixture synchronization and race-enabled verification passed.

The concurrency audit records the wider review, additional findings, corrections, and final verification evidence.

Objective and evidence

Make the delivery HTTP fixtures safe for concurrent access by test goroutines and request handlers while preserving their existing behavioral assertions. The PromptKit bug report supplies the original diagnostics and consumer context.

Upstream investigation reproduced TestReleaseKitSourceDeliveryWorkflowFromTaggedCheckout under the race detector with Go 1.26.8. The diagnostics identified commit, remoteCommit, and releaseCreates accesses shared between the workflow test and HTTP handlers. The workflow test and relevant unsynchronized accesses predate v0.4.0. Subprocess completion supplies no synchronization for this shared Go state.

The ordinary Woodpecker and multi-module workflow tests passed their focused race-enabled runs during investigation. Source inspection nevertheless found the same unsynchronized state pattern in their fixtures. A passing run alone does not establish safe access under other scheduling.

Scope

The correction belongs in test infrastructure:

Production behavior, public API contracts, and release requirements retain their current definitions. Use the standard library and small fixture-local helpers, following the agent and testing policies.

Implementation

  1. Synchronize the shared delivery fixture. Give mutable fixture state a sync.Mutex. Protect handler reads and writes, test-side configuration changes, assertion reads, counters, page state, note content, and asset-map operations with the same mutex. Initialize immutable configuration before serving requests where practical; synchronize later initialization such as the source commit assigned after profile creation. Review captured handler values and response helpers as part of this boundary.

  2. Update every shared-fixture consumer. Use simple locked setters and snapshot accessors for test configuration and assertions. Snapshot plain values separately from the mutex, copying maps and mutable byte slices when they will be inspected outside the lock. Include failure diagnostics that format fixture state. Keep lock ownership clear in handler helpers and release locks before executing CLI workflows or closing the server.

  3. Apply the same discipline to the mapped fixture. Protect its commit, request and creation counters, page fields, uploads, and asset map, together with all corresponding test accesses. Keep each fixture's synchronization local and proportionate to its existing responsibilities.

  4. Preserve behavioral coverage. Retain rejection of mismatched hosted tags before release creation, exact source-tag preservation, complete note bodies, idempotent page and asset delivery, expected asset counts, mapped module identity, retries using tagged configuration, and existing failure outcomes. Use these workflows as the regression coverage for the reported race. Add further coverage only for a concrete gap discovered during the correction.

Verification and completion

With dependencies prepared, run the affected workflows from the repository root using the local toolchain and offline module settings:

GOTOOLCHAIN=local GOWORK=off GOPROXY=off GOSUMDB=off \
  go test -race -mod=readonly -count=1 ./cmd/releasekit \
  -run '^(TestReleaseKitSourceDeliveryWorkflowFromTaggedCheckout|TestWoodpeckerTagDeliveryTemplate|TestMultiModuleWoodpeckerDelivery)$'

Then run the full race-enabled suite once to verify the other shared-fixture users and catch remaining cross-goroutine access:

GOTOOLCHAIN=local GOWORK=off GOPROXY=off GOSUMDB=off \
  go test -race -mod=readonly -count=1 ./...

Review the fixture accesses as well as the test results: successful execution complements the synchronization review. Keep local Git repositories, HTTP servers, and synthetic module caches isolated as described in development.

Completion means both fixtures and their consumers use synchronized state, the existing assertions remain effective, and the focused and full race-enabled suites pass. Record completion and verification here and update the bug report's status with the remediation outcome. Commit the completed correction under the repository's ordinary change workflow.

This verification addresses the reported defect. Future release validation continues to follow the release procedure. The correction is suitable for a subsequent patch release; preparation and publication are separate work under that procedure, preserving the published v0.4.0 contents.

Completed: Both delivery fixtures and all their consumers use mutex-protected updates and independent snapshots. Existing mismatch, note, asset, retry, and source-preservation assertions remain in place. Focused workflow checks and the full offline race-enabled suite passed with Go 1.26.8; the compiled API/dependency check passed. The audit also corrected public delivery fixture ownership, Gitea scalar observations, HTTP assertion handling, and server cleanup.