Return write evidence from Gitea operations
This commit is contained in:
@@ -2,6 +2,7 @@ package gitea
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"net/http"
|
||||
@@ -75,6 +76,92 @@ func (b *Backend) Preflight(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Backend) CreateRelease(ctx context.Context, request forge.CreateReleaseRequest) (forge.Release, forge.WriteEvidence, error) {
|
||||
if strings.TrimSpace(request.Tag) == "" || !validObjectID(request.Commit) {
|
||||
return forge.Release{}, forge.WriteEvidence{Disposition: forge.WriteNotAttempted}, &forge.Failure{
|
||||
Kind: forge.FailureInvalid, Err: errors.New("a full tag and lowercase Git commit ID are required"),
|
||||
}
|
||||
}
|
||||
_, apiRoot, err := b.destinationAPI("create release")
|
||||
if err != nil {
|
||||
return forge.Release{}, forge.WriteEvidence{Disposition: forge.WriteNotAttempted}, err
|
||||
}
|
||||
body, err := json.Marshal(createReleaseRequest{
|
||||
TagName: request.Tag, TargetCommitish: request.Commit,
|
||||
Name: request.Title, Body: request.Body,
|
||||
Draft: request.Draft, Prerelease: request.Prerelease,
|
||||
})
|
||||
if err != nil {
|
||||
return forge.Release{}, forge.WriteEvidence{Disposition: forge.WriteNotAttempted}, &forge.Failure{Kind: forge.FailureInvalid, Err: err}
|
||||
}
|
||||
created, status, err := b.client.postRelease(ctx, b.client.httpClient(), b.destination.Token, apiRoot+"/releases", body)
|
||||
if err == nil && created.ID <= 0 {
|
||||
err = failure(FailureMalformed, "verify created release", status, errors.New("release response does not contain a positive ID"))
|
||||
}
|
||||
evidence := writeEvidence(status, err)
|
||||
if err != nil {
|
||||
return forge.Release{}, evidence, neutralFailure(err)
|
||||
}
|
||||
return forge.Release{
|
||||
URL: created.URL,
|
||||
Tag: created.TagName,
|
||||
Title: created.Title,
|
||||
Body: created.Body,
|
||||
Draft: created.Draft,
|
||||
Prerelease: created.Prerelease,
|
||||
Handle: releaseHandle{id: created.ID},
|
||||
}, evidence, nil
|
||||
}
|
||||
|
||||
func (b *Backend) UploadAsset(ctx context.Context, handle any, filename string, content io.Reader) (forge.WriteEvidence, error) {
|
||||
release, ok := handle.(releaseHandle)
|
||||
if !ok || release.id <= 0 {
|
||||
return forge.WriteEvidence{Disposition: forge.WriteNotAttempted}, &forge.Failure{Kind: forge.FailureInvalid, Err: errors.New("release handle was not created by the Gitea backend")}
|
||||
}
|
||||
if strings.TrimSpace(filename) == "" || content == nil {
|
||||
return forge.WriteEvidence{Disposition: forge.WriteNotAttempted}, &forge.Failure{Kind: forge.FailureInvalid, Err: errors.New("asset filename and content reader are required")}
|
||||
}
|
||||
_, apiRoot, err := b.destinationAPI("upload release asset")
|
||||
if err != nil {
|
||||
return forge.WriteEvidence{Disposition: forge.WriteNotAttempted}, err
|
||||
}
|
||||
status, err := b.client.uploadAsset(ctx, b.client.httpClient(), b.destination.Token, apiRoot, release.id, filename, content)
|
||||
evidence := writeEvidence(status, err)
|
||||
if err != nil {
|
||||
return evidence, neutralFailure(err)
|
||||
}
|
||||
return evidence, nil
|
||||
}
|
||||
|
||||
func writeEvidence(status int, err error) forge.WriteEvidence {
|
||||
evidence := forge.WriteEvidence{Attempted: status != 0, Disposition: forge.WriteNotAttempted}
|
||||
var backendFailure *Failure
|
||||
if err != nil && errors.As(err, &backendFailure) && backendFailure.Kind == FailureTransport {
|
||||
evidence.Attempted = true
|
||||
}
|
||||
if !evidence.Attempted {
|
||||
return evidence
|
||||
}
|
||||
if err == nil {
|
||||
evidence.Disposition = forge.WriteAccepted
|
||||
return evidence
|
||||
}
|
||||
if status == http.StatusConflict {
|
||||
evidence.Disposition = forge.WriteConflict
|
||||
return evidence
|
||||
}
|
||||
if status >= http.StatusInternalServerError || errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {
|
||||
evidence.Disposition = forge.WriteUncertain
|
||||
return evidence
|
||||
}
|
||||
if errors.As(err, &backendFailure) && (backendFailure.Kind == FailureTransport || backendFailure.Kind == FailureMalformed) {
|
||||
evidence.Disposition = forge.WriteUncertain
|
||||
return evidence
|
||||
}
|
||||
evidence.Disposition = forge.WriteRejected
|
||||
return evidence
|
||||
}
|
||||
|
||||
func (repository repositoryResponse) matches(destination Destination) bool {
|
||||
if repository.ID <= 0 || !strings.EqualFold(repository.Name, destination.Repository) {
|
||||
return false
|
||||
@@ -237,3 +324,5 @@ func neutralFailure(err error) error {
|
||||
}
|
||||
return &forge.Failure{Kind: kind, Err: err}
|
||||
}
|
||||
|
||||
var _ forge.Backend = (*Backend)(nil)
|
||||
|
||||
Reference in New Issue
Block a user