feat(release): server-side packaging — attach full-repo + entry_point subtree zips on release [#809] #814
Reference in New Issue
Block a user
Delete Branch "feature/release-packaging-hook"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Adds a server-side on-release packaging hook (#809). On publish, MokoGIT now
attaches build artifacts to the release automatically:
<repo>-<tag>.zip— full-repository archive (always).<repo>-<tag>-source.zip— entry-point subtree archive, generated onlywhen the repo metadata (
repo_manifest.entry_point) declares a non-rootentry point (
""/"."/"/"are treated as root and skipped).How it works
services/release/packaging.go→GenerateReleaseArtifacts(ctx, rel).repo_model.GetRepoMetadata(ctx, rel.RepoID).gitrepo.CreateArchive(ctx, rel.Repo, "zip", w, false, rel.Sha1, paths)(full repo =
paths == nil; subtree =[]string{cleanedEntryPoint}), streamingthe zip through an
io.Pipestraight intoattachment_service.NewAttachmentwith
ReleaseID = rel.IDandsize = -1— the archive is never buffered in RAM.before re-attaching, so a draft→publish transition (or any re-run) replaces
rather than duplicates.
GenerateReleaseChecksums, so each generated zip receives a.sha256sidecar automatically from the existing checksum pass.checksum.go: per-artifact failures are logged and donot abort the release; only setup failures (metadata/attachment enumeration)
are returned.
Call sites (
services/release/release.go)CreateRelease— invoked before the checksum call, guarded by!rel.IsDraft.UpdateRelease— invoked in the publish path before the checksum call, guardedby
!rel.IsDraft(drafts skipped, matching thenotify_serviceguard).Both checksum guards were widened to also fire when artifacts are generated
(
|| !rel.IsDraft) so the new zips get sidecars even when no user attachmentswere uploaded.
Refs #809, #812, EPIC #367.
Logic review + data-safety fixes
A read-only logic review (no compiler available here) found the io.Pipe/goroutine handling correct (no leak —
pr.CloseWithErroron the early-return path unblocks the exec copy goroutine and reapsgit archive) andsize=-1streaming valid on both Local and Minio backends. It also found two HIGH data-safety bugs and some LOWs, all now fixed in19d498f:deleteExistingArtifactsmatched by name only -> could delete a user-uploaded asset sharing the generated nameUploaderID = ActionsUserID (-2); delete only matches name AND marker. Human uploads use positiveDoer.ID; legacy uploads are0, never negative -> collision-freegloballock.LockAndDoaround delete+attachrepo-release/1.0.zip)sanitizeNameSegment(/,\,NUL ->-), matchingGetArchiveName()entry_point(/packages/x) rejected by git archive/, empty -> root/skip)MEDIUM (documented follow-up, not fixed): a non-draft release edit re-hashes all attachments via the widened checksum guard — O(total asset bytes) on unrelated edits.
Still required before merge: this was authored WITHOUT a Go toolchain —
gofmt/go vet/go builddid not run. Compile-check + review the archive/attachment signatures against the deployed forge version, then rebuild + redeploy the forge. Not built, not deployed.Authored-by: Moko Consulting