Give delivery facade ownership of builds

This commit is contained in:
2026-10-06 18:23:55 +00:00
parent c9afc8dd12
commit a67a00a733
9 changed files with 605 additions and 38 deletions

View File

@@ -4,6 +4,8 @@ import (
"context"
"errors"
"fmt"
"io"
"os"
"path/filepath"
"strings"
@@ -11,6 +13,7 @@ import (
"gitea.maximumdirect.net/eric/ReleaseKit/internal/candidate"
"gitea.maximumdirect.net/eric/ReleaseKit/internal/git"
"gitea.maximumdirect.net/eric/ReleaseKit/internal/gitea"
"gitea.maximumdirect.net/eric/ReleaseKit/internal/tempdir"
"gitea.maximumdirect.net/eric/ReleaseKit/internal/versioncontract"
)
@@ -29,7 +32,9 @@ type Request struct {
Product string
Version string
Destination gitea.Destination
Build *internalbuild.Result
Build *internalbuild.Spec
Prebuilt *internalbuild.Result
Output io.Writer
}
type Result struct {
@@ -51,6 +56,9 @@ func Deliver(ctx context.Context, request Request) (Result, error) {
if strings.TrimSpace(request.Product) == "" {
return result, errors.New("product is required")
}
if request.Build != nil && request.Prebuilt != nil {
return result, errors.New("delivery cannot use both a managed build and prebuilt artifacts")
}
repositoryDir, err := filepath.Abs(request.RepositoryDir)
if err != nil {
return result, fmt.Errorf("resolve repository directory: %w", err)
@@ -66,21 +74,6 @@ func Deliver(ctx context.Context, request Request) (Result, error) {
if source.Head != source.TagCommit {
return result, fmt.Errorf("checkout HEAD %s does not match tag %s commit %s", source.Head, request.Version, source.TagCommit)
}
var assets []gitea.ExpectedAsset
if request.Build != nil {
assets, err = declaredBuildAssets(*request.Build)
if err != nil {
return result, err
}
}
if err := validateBuild(repositoryDir, source.TagCommit, request.Version, request.Build, assets); err != nil {
return result, err
}
if len(assets) > 0 {
if err := gitea.VerifyLocalAssets(assets); err != nil {
return result, fmt.Errorf("verify build assets: %w", err)
}
}
notePath := "docs/releases/" + request.Version + ".md"
note, err := git.ReadCommitFile(ctx, repositoryDir, source.TagCommit, notePath)
if err != nil {
@@ -90,6 +83,53 @@ func Deliver(ctx context.Context, request Request) (Result, error) {
return result, fmt.Errorf("release note %q: %w", notePath, err)
}
build := request.Prebuilt
if request.Build != nil && len(request.Build.Targets) != 0 {
temporaryDir, err := tempdir.Outside(repositoryDir, "releasekit-delivery-build-*")
if err != nil {
return result, fmt.Errorf("create temporary delivery build directory: %w", err)
}
defer os.RemoveAll(temporaryDir)
built, err := internalbuild.Build(ctx, internalbuild.Request{
RepositoryDir: repositoryDir,
Version: request.Version,
Spec: *request.Build,
OutputDir: filepath.Join(temporaryDir, "assets"),
Output: request.Output,
})
if err != nil {
return result, fmt.Errorf("build delivery assets: %w", err)
}
build = &built
}
var assets []gitea.ExpectedAsset
if build != nil {
assets, err = declaredBuildAssets(*build)
if err != nil {
return result, err
}
}
if err := validateBuild(repositoryDir, source.TagCommit, request.Version, build, assets); err != nil {
return result, err
}
if len(assets) > 0 {
if err := gitea.VerifyLocalAssets(assets); err != nil {
return result, fmt.Errorf("verify build assets: %w", err)
}
}
if build != nil && len(build.Targets) != 0 {
current, err := git.InspectTaggedSource(ctx, repositoryDir, request.Version)
if err != nil {
return result, fmt.Errorf("recheck tagged source after build: %w", err)
}
if current.Status != "" {
return result, fmt.Errorf("tagged checkout changed during build:\n%s", current.Status)
}
if current.Head != source.TagCommit || current.TagCommit != source.TagCommit {
return result, errors.New("tagged source changed during build")
}
}
releaseResult, err := (gitea.Client{}).EnsureRelease(ctx, gitea.Request{
Destination: request.Destination,
Version: request.Version,