Files
ReleaseKit/delivery.go

126 lines
4.3 KiB
Go

package releasekit
import (
"context"
"fmt"
internaldelivery "gitea.maximumdirect.net/eric/ReleaseKit/internal/delivery"
"gitea.maximumdirect.net/eric/ReleaseKit/internal/gitea"
)
// DeliveryState describes the result of one delivery invocation.
type DeliveryState string
const (
// DeliveryNotAttempted means this invocation made no remote write.
DeliveryNotAttempted DeliveryState = "not_attempted"
// DeliveryComplete means the release page and all declared assets match.
DeliveryComplete DeliveryState = "complete"
// DeliveryPartial means a page or some assets were delivered, with work pending.
DeliveryPartial DeliveryState = "partial"
// DeliveryConflict means existing hosted content differs from the declaration.
DeliveryConflict DeliveryState = "conflict"
// DeliveryUnknown means a remote write may have succeeded but could not be resolved.
DeliveryUnknown DeliveryState = "unknown"
)
// GiteaDestination supplies the hosted repository and explicit access token.
type GiteaDestination struct {
BaseURL string
Owner string
Repository string
Token string
}
// DeliveryAsset identifies a hosted asset by filename and SHA-256 digest.
type DeliveryAsset struct {
Filename string
SHA256 string
}
// DeliveryRequest identifies a local tagged checkout and its explicit Gitea
// destination. Build is nil for page-only delivery.
type DeliveryRequest struct {
RepositoryDir string
Product string
Version string
Destination GiteaDestination
Build *BuildResult
}
// DeliveryResult reports hosted content and the state reached by this
// invocation. A partial result may accompany an error.
type DeliveryResult struct {
Version string
CandidateCommit string
ReleaseURL string
State DeliveryState
Matching []DeliveryAsset
Uploaded []DeliveryAsset
Pending []DeliveryAsset
Conflicting []DeliveryAsset
Uncertain []DeliveryAsset
}
// Deliver verifies the selected local tag and hosted source, then creates or
// finds its release page and adds any missing declared build assets.
func Deliver(ctx context.Context, request DeliveryRequest) (DeliveryResult, error) {
result := DeliveryResult{Version: request.Version, State: DeliveryNotAttempted}
var build *internaldelivery.BuildIdentity
var assets []gitea.ExpectedAsset
if request.Build != nil {
if len(request.Build.Targets) == 0 {
if len(request.Build.Artifacts) != 0 {
return result, fmt.Errorf("page-only build result contains artifacts")
}
} else {
var err error
assets, err = declaredBuildAssets(*request.Build)
if err != nil {
return result, err
}
targets := make([]string, 0, len(request.Build.Targets))
for _, target := range request.Build.Targets {
targets = append(targets, target.OS+"/"+target.Arch)
}
build = &internaldelivery.BuildIdentity{
RepositoryDir: request.Build.RepositoryDir,
CandidateCommit: request.Build.CandidateCommit,
Version: request.Build.Version,
MainPackage: request.Build.MainPackage,
BinaryName: request.Build.BinaryName,
Targets: targets,
}
}
}
destination := gitea.Destination{
BaseURL: request.Destination.BaseURL, Owner: request.Destination.Owner,
Repository: request.Destination.Repository, Token: request.Destination.Token,
}
internalResult, err := internaldelivery.Deliver(ctx, internaldelivery.Request{
RepositoryDir: request.RepositoryDir,
Product: request.Product,
Version: request.Version,
Destination: destination,
Build: build,
Assets: assets,
})
result.CandidateCommit = internalResult.CandidateCommit
result.ReleaseURL = internalResult.ReleaseURL
result.State = DeliveryState(internalResult.State)
result.Matching = deliveryAssets(internalResult.Matching)
result.Uploaded = deliveryAssets(internalResult.Uploaded)
result.Pending = deliveryAssets(internalResult.Pending)
result.Conflicting = deliveryAssets(internalResult.Conflicting)
result.Uncertain = deliveryAssets(internalResult.Uncertain)
return result, err
}
func deliveryAssets(assets []gitea.AssetIdentity) []DeliveryAsset {
result := make([]DeliveryAsset, 0, len(assets))
for _, asset := range assets {
result = append(result, DeliveryAsset{Filename: asset.Filename, SHA256: asset.SHA256})
}
return result
}