Connect neutral delivery to the Gitea CLI
This commit is contained in:
@@ -12,8 +12,8 @@ import (
|
||||
"go.maximumdirect.net/releasekit/internal/artifact"
|
||||
internalbuild "go.maximumdirect.net/releasekit/internal/build"
|
||||
"go.maximumdirect.net/releasekit/internal/candidate"
|
||||
"go.maximumdirect.net/releasekit/internal/forge"
|
||||
"go.maximumdirect.net/releasekit/internal/git"
|
||||
"go.maximumdirect.net/releasekit/internal/gitea"
|
||||
"go.maximumdirect.net/releasekit/internal/gotool"
|
||||
"go.maximumdirect.net/releasekit/internal/releaseidentity"
|
||||
"go.maximumdirect.net/releasekit/internal/tempdir"
|
||||
@@ -36,7 +36,7 @@ type Request struct {
|
||||
Product string
|
||||
Version string
|
||||
ExpectedTag string
|
||||
Destination gitea.Destination
|
||||
Backend forge.Backend
|
||||
Build *internalbuild.Spec
|
||||
Prebuilt *internalbuild.Result
|
||||
Output io.Writer
|
||||
@@ -50,11 +50,11 @@ type Result struct {
|
||||
CandidateCommit string
|
||||
ReleaseURL string
|
||||
State State
|
||||
Matching []gitea.AssetIdentity
|
||||
Uploaded []gitea.AssetIdentity
|
||||
Pending []gitea.AssetIdentity
|
||||
Conflicting []gitea.AssetIdentity
|
||||
Uncertain []gitea.AssetIdentity
|
||||
Matching []AssetIdentity
|
||||
Uploaded []AssetIdentity
|
||||
Pending []AssetIdentity
|
||||
Conflicting []AssetIdentity
|
||||
Uncertain []AssetIdentity
|
||||
}
|
||||
|
||||
func Deliver(ctx context.Context, request Request) (Result, error) {
|
||||
@@ -68,6 +68,9 @@ func Deliver(ctx context.Context, request Request) (Result, error) {
|
||||
if request.Build != nil && request.Prebuilt != nil {
|
||||
return result, errors.New("delivery cannot use both a managed build and prebuilt artifacts")
|
||||
}
|
||||
if request.Backend == nil {
|
||||
return result, errors.New("delivery backend is required")
|
||||
}
|
||||
repositoryDir, err := git.RepositoryRoot(ctx, request.RepositoryDir)
|
||||
if err != nil {
|
||||
return result, fmt.Errorf("resolve repository directory: %w", err)
|
||||
@@ -112,6 +115,14 @@ func Deliver(ctx context.Context, request Request) (Result, error) {
|
||||
if err := candidate.ValidateReleaseNote(note, request.Product, request.Version); err != nil {
|
||||
return result, fmt.Errorf("release note %q: %w", identity.NotePath, err)
|
||||
}
|
||||
if request.Prebuilt != nil {
|
||||
if err := validateBuildIdentity(identity, commit, request.Prebuilt); err != nil {
|
||||
return result, err
|
||||
}
|
||||
}
|
||||
if err := request.Backend.Preflight(ctx); err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
||||
build := request.Prebuilt
|
||||
if request.Build != nil && len(request.Build.Targets) != 0 {
|
||||
@@ -144,11 +155,11 @@ func Deliver(ctx context.Context, request Request) (Result, error) {
|
||||
}
|
||||
if len(assets) > 0 {
|
||||
if err := artifact.VerifyLocalAssets(assets); err != nil {
|
||||
kind := gitea.FailureInvalid
|
||||
kind := forge.FailureInvalid
|
||||
if errors.Is(err, artifact.ErrAssetConflict) {
|
||||
kind = gitea.FailureConflict
|
||||
kind = forge.FailureConflict
|
||||
}
|
||||
return result, &gitea.Failure{Kind: kind, Operation: "verify build assets", Err: err}
|
||||
return result, &forge.Failure{Kind: kind, Err: fmt.Errorf("verify build assets: %w", err)}
|
||||
}
|
||||
}
|
||||
if build != nil && len(build.Settings.Targets) != 0 {
|
||||
@@ -164,38 +175,33 @@ func Deliver(ctx context.Context, request Request) (Result, error) {
|
||||
}
|
||||
}
|
||||
|
||||
releaseResult, err := (gitea.Client{}).EnsureRelease(ctx, gitea.Request{
|
||||
Destination: request.Destination,
|
||||
Tag: identity.Tag,
|
||||
Commit: commit,
|
||||
Note: string(note),
|
||||
})
|
||||
release, pageEvidence, err := coordinateRelease(ctx, request.Backend, identity.Tag, commit, string(note))
|
||||
if err != nil {
|
||||
result.State = stateForError(err, false)
|
||||
return result, err
|
||||
}
|
||||
result.ReleaseURL = releaseResult.Release.URL
|
||||
result.ReleaseURL = release.URL
|
||||
if len(assets) == 0 {
|
||||
result.State = Complete
|
||||
return result, nil
|
||||
}
|
||||
inspection, err := (gitea.Client{}).InspectAssets(ctx, request.Destination, releaseResult.Release.ID, assets)
|
||||
inspection, err := inspectRemoteAssets(ctx, request.Backend, release.Handle, assets)
|
||||
if err != nil {
|
||||
result.State = NotAttempted
|
||||
if releaseResult.WriteAttempted {
|
||||
if pageEvidence.Attempted {
|
||||
result.State = Partial
|
||||
}
|
||||
result.Uncertain = assetIdentities(assets)
|
||||
return result, err
|
||||
}
|
||||
uploadResult, uploadErr := (gitea.Client{}).UploadVerifiedMissing(ctx, request.Destination, releaseResult.Release.ID, inspection)
|
||||
uploadResult, uploadErr := uploadMissingAssets(ctx, request.Backend, release.Handle, inspection)
|
||||
result.Matching = uploadResult.Matching
|
||||
result.Uploaded = uploadResult.Uploaded
|
||||
result.Pending = uploadResult.Pending
|
||||
result.Conflicting = uploadResult.Conflicting
|
||||
result.Uncertain = uploadResult.Uncertain
|
||||
result.State = State(uploadResult.State)
|
||||
if result.State == NotAttempted && releaseResult.WriteAttempted {
|
||||
if result.State == NotAttempted && pageEvidence.Attempted {
|
||||
result.State = Partial
|
||||
}
|
||||
return result, uploadErr
|
||||
@@ -208,6 +214,22 @@ func validateBuild(identity releaseidentity.Identity, commit string, build *inte
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if err := validateBuildIdentity(identity, commit, build); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(build.Settings.Targets) == 0 {
|
||||
if len(assets) != 0 {
|
||||
return errors.New("page-only delivery cannot include binary assets")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if len(assets) != len(build.Settings.Targets)+1 || assets[len(assets)-1].Filename != artifact.ManifestFilename {
|
||||
return errors.New("build result does not contain the selected artifacts and complete checksum manifest")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateBuildIdentity(identity releaseidentity.Identity, commit string, build *internalbuild.Result) error {
|
||||
buildRepository, err := filepath.Abs(build.RepositoryDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("resolve build repository: %w", err)
|
||||
@@ -220,27 +242,24 @@ func validateBuild(identity releaseidentity.Identity, commit string, build *inte
|
||||
return errors.New("build result does not identify the selected tagged module")
|
||||
}
|
||||
if len(build.Settings.Targets) == 0 {
|
||||
if len(assets) != 0 {
|
||||
return errors.New("page-only delivery cannot include binary assets")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if !build.SourceVerified {
|
||||
return errors.New("build source was not verified as clean and unchanged during compilation")
|
||||
}
|
||||
if strings.TrimSpace(build.Settings.MainPackage) == "" || strings.TrimSpace(build.Settings.BinaryName) == "" || len(assets) != len(build.Settings.Targets)+1 || assets[len(assets)-1].Filename != artifact.ManifestFilename {
|
||||
if strings.TrimSpace(build.Settings.MainPackage) == "" || strings.TrimSpace(build.Settings.BinaryName) == "" {
|
||||
return errors.New("build result does not contain the selected artifacts and complete checksum manifest")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func stateForError(err error, pageCreated bool) State {
|
||||
var failure *gitea.Failure
|
||||
var failure *forge.Failure
|
||||
if errors.As(err, &failure) {
|
||||
switch failure.Kind {
|
||||
case gitea.FailureConflict:
|
||||
case forge.FailureConflict:
|
||||
return Conflict
|
||||
case gitea.FailureUnknown:
|
||||
case forge.FailureUnknown:
|
||||
return Unknown
|
||||
}
|
||||
}
|
||||
@@ -250,10 +269,10 @@ func stateForError(err error, pageCreated bool) State {
|
||||
return NotAttempted
|
||||
}
|
||||
|
||||
func assetIdentities(assets []artifact.ExpectedAsset) []gitea.AssetIdentity {
|
||||
result := make([]gitea.AssetIdentity, 0, len(assets))
|
||||
func assetIdentities(assets []artifact.ExpectedAsset) []AssetIdentity {
|
||||
result := make([]AssetIdentity, 0, len(assets))
|
||||
for _, asset := range assets {
|
||||
result = append(result, gitea.AssetIdentity{Filename: asset.Filename, SHA256: asset.SHA256})
|
||||
result = append(result, AssetIdentity{Filename: asset.Filename, SHA256: asset.SHA256})
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user