Return write evidence from Gitea operations

This commit is contained in:
2026-11-01 18:02:05 +00:00
parent 02bd120aed
commit ddac9e3c73
4 changed files with 280 additions and 22 deletions

View File

@@ -146,7 +146,12 @@ func (c Client) uploadMissing(ctx context.Context, destination Destination, rele
if _, needsUpload := missing[item.Filename]; !needsUpload {
continue
}
status, uploadErr := c.uploadAsset(ctx, client, destination.Token, baseAPI, releaseID, item)
content, openErr := assetContent(item)
if openErr != nil {
return result, failure(FailureInvalid, "open local release asset", 0, openErr)
}
status, uploadErr := c.uploadAsset(ctx, client, destination.Token, baseAPI, releaseID, item.Filename, content)
_ = content.Close()
if uploadErr == nil {
result.Uploaded = append(result.Uploaded, identity(item))
result.Pending = removeIdentity(result.Pending, item.Filename)
@@ -198,36 +203,25 @@ func (c Client) uploadMissing(ctx context.Context, destination Destination, rele
return result, nil
}
func (c Client) uploadAsset(ctx context.Context, client *http.Client, token, apiRoot string, releaseID int64, asset artifact.ExpectedAsset) (int, error) {
func (c Client) uploadAsset(ctx context.Context, client *http.Client, token, apiRoot string, releaseID int64, filename string, content io.Reader) (int, error) {
if content == nil {
return 0, failure(FailureInvalid, "upload release asset", 0, errors.New("asset content reader is required"))
}
uploadURL := apiRoot + "/releases/" + strconv.FormatInt(releaseID, 10) + "/assets"
parsed, err := url.Parse(uploadURL)
if err != nil {
return 0, failure(FailureInvalid, "prepare asset upload", 0, err)
}
query := parsed.Query()
query.Set("name", asset.Filename)
query.Set("name", filename)
parsed.RawQuery = query.Encode()
reader, writer := io.Pipe()
multipartWriter := multipart.NewWriter(writer)
writeDone := make(chan error, 1)
go func() {
part, partErr := multipartWriter.CreateFormFile("attachment", asset.Filename)
part, partErr := multipartWriter.CreateFormFile("attachment", filename)
if partErr == nil {
var source io.Reader
if len(asset.Content) > 0 {
source = bytes.NewReader(asset.Content)
} else {
file, openErr := os.Open(asset.Path)
if openErr != nil {
partErr = openErr
} else {
defer file.Close()
source = file
}
}
if partErr == nil {
_, partErr = io.Copy(part, source)
}
_, partErr = io.Copy(part, content)
}
closeErr := multipartWriter.Close()
if partErr == nil {
@@ -261,7 +255,7 @@ func (c Client) uploadAsset(ctx context.Context, client *http.Client, token, api
if err := decodeJSON(response.Body, &uploaded); err != nil {
return response.StatusCode, failure(FailureMalformed, "decode uploaded asset", response.StatusCode, err)
}
if uploaded.ID <= 0 || uploaded.Name != asset.Filename {
if uploaded.ID <= 0 || uploaded.Name != filename {
return response.StatusCode, failure(FailureMalformed, "verify uploaded asset", response.StatusCode, errors.New("upload response does not identify the selected asset"))
}
if writeErr != nil {
@@ -270,6 +264,13 @@ func (c Client) uploadAsset(ctx context.Context, client *http.Client, token, api
return response.StatusCode, nil
}
func assetContent(asset artifact.ExpectedAsset) (io.ReadCloser, error) {
if len(asset.Content) > 0 {
return io.NopCloser(bytes.NewReader(asset.Content)), nil
}
return os.Open(asset.Path)
}
func orderedExpected(observations []AssetInspection) []artifact.ExpectedAsset {
result := make([]artifact.ExpectedAsset, 0, len(observations))
for _, observation := range observations {