summaryrefslogtreecommitdiffstats
path: root/tests/integration/api_actions_artifact_test.go
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--tests/integration/api_actions_artifact_test.go378
1 files changed, 378 insertions, 0 deletions
diff --git a/tests/integration/api_actions_artifact_test.go b/tests/integration/api_actions_artifact_test.go
new file mode 100644
index 0000000..2798024
--- /dev/null
+++ b/tests/integration/api_actions_artifact_test.go
@@ -0,0 +1,378 @@
+// Copyright 2023 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package integration
+
+import (
+ "net/http"
+ "strings"
+ "testing"
+
+ "code.gitea.io/gitea/tests"
+
+ "github.com/stretchr/testify/assert"
+)
+
+type uploadArtifactResponse struct {
+ FileContainerResourceURL string `json:"fileContainerResourceUrl"`
+}
+
+type getUploadArtifactRequest struct {
+ Type string
+ Name string
+ RetentionDays int64
+}
+
+func TestActionsArtifactUploadSingleFile(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+
+ // acquire artifact upload url
+ req := NewRequestWithJSON(t, "POST", "/api/actions_pipeline/_apis/pipelines/workflows/791/artifacts", getUploadArtifactRequest{
+ Type: "actions_storage",
+ Name: "artifact",
+ }).AddTokenAuth("8061e833a55f6fc0157c98b883e91fcfeeb1a71a")
+ resp := MakeRequest(t, req, http.StatusOK)
+ var uploadResp uploadArtifactResponse
+ DecodeJSON(t, resp, &uploadResp)
+ assert.Contains(t, uploadResp.FileContainerResourceURL, "/api/actions_pipeline/_apis/pipelines/workflows/791/artifacts")
+
+ // get upload url
+ idx := strings.Index(uploadResp.FileContainerResourceURL, "/api/actions_pipeline/_apis/pipelines/")
+ url := uploadResp.FileContainerResourceURL[idx:] + "?itemPath=artifact/abc.txt"
+
+ // upload artifact chunk
+ body := strings.Repeat("A", 1024)
+ req = NewRequestWithBody(t, "PUT", url, strings.NewReader(body)).
+ AddTokenAuth("8061e833a55f6fc0157c98b883e91fcfeeb1a71a").
+ SetHeader("Content-Range", "bytes 0-1023/1024").
+ SetHeader("x-tfs-filelength", "1024").
+ SetHeader("x-actions-results-md5", "1HsSe8LeLWh93ILaw1TEFQ==") // base64(md5(body))
+ MakeRequest(t, req, http.StatusOK)
+
+ t.Logf("Create artifact confirm")
+
+ // confirm artifact upload
+ req = NewRequest(t, "PATCH", "/api/actions_pipeline/_apis/pipelines/workflows/791/artifacts?artifactName=artifact").
+ AddTokenAuth("8061e833a55f6fc0157c98b883e91fcfeeb1a71a")
+ MakeRequest(t, req, http.StatusOK)
+}
+
+func TestActionsArtifactUploadInvalidHash(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+
+ // artifact id 54321 not exist
+ url := "/api/actions_pipeline/_apis/pipelines/workflows/791/artifacts/8e5b948a454515dbabfc7eb718ddddddd/upload?itemPath=artifact/abc.txt"
+ body := strings.Repeat("A", 1024)
+ req := NewRequestWithBody(t, "PUT", url, strings.NewReader(body)).
+ AddTokenAuth("8061e833a55f6fc0157c98b883e91fcfeeb1a71a").
+ SetHeader("Content-Range", "bytes 0-1023/1024").
+ SetHeader("x-tfs-filelength", "1024").
+ SetHeader("x-actions-results-md5", "1HsSe8LeLWh93ILaw1TEFQ==") // base64(md5(body))
+ resp := MakeRequest(t, req, http.StatusBadRequest)
+ assert.Contains(t, resp.Body.String(), "Invalid artifact hash")
+}
+
+func TestActionsArtifactConfirmUploadWithoutName(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+
+ req := NewRequest(t, "PATCH", "/api/actions_pipeline/_apis/pipelines/workflows/791/artifacts").
+ AddTokenAuth("8061e833a55f6fc0157c98b883e91fcfeeb1a71a")
+ resp := MakeRequest(t, req, http.StatusBadRequest)
+ assert.Contains(t, resp.Body.String(), "artifact name is empty")
+}
+
+func TestActionsArtifactUploadWithoutToken(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+
+ req := NewRequestWithJSON(t, "POST", "/api/actions_pipeline/_apis/pipelines/workflows/1/artifacts", nil)
+ MakeRequest(t, req, http.StatusUnauthorized)
+}
+
+type (
+ listArtifactsResponseItem struct {
+ Name string `json:"name"`
+ FileContainerResourceURL string `json:"fileContainerResourceUrl"`
+ }
+ listArtifactsResponse struct {
+ Count int64 `json:"count"`
+ Value []listArtifactsResponseItem `json:"value"`
+ }
+ downloadArtifactResponseItem struct {
+ Path string `json:"path"`
+ ItemType string `json:"itemType"`
+ ContentLocation string `json:"contentLocation"`
+ }
+ downloadArtifactResponse struct {
+ Value []downloadArtifactResponseItem `json:"value"`
+ }
+)
+
+func TestActionsArtifactDownload(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+
+ req := NewRequest(t, "GET", "/api/actions_pipeline/_apis/pipelines/workflows/791/artifacts").
+ AddTokenAuth("8061e833a55f6fc0157c98b883e91fcfeeb1a71a")
+ resp := MakeRequest(t, req, http.StatusOK)
+ var listResp listArtifactsResponse
+ DecodeJSON(t, resp, &listResp)
+ assert.Equal(t, int64(1), listResp.Count)
+ assert.Equal(t, "artifact", listResp.Value[0].Name)
+ assert.Contains(t, listResp.Value[0].FileContainerResourceURL, "/api/actions_pipeline/_apis/pipelines/workflows/791/artifacts")
+
+ idx := strings.Index(listResp.Value[0].FileContainerResourceURL, "/api/actions_pipeline/_apis/pipelines/")
+ url := listResp.Value[0].FileContainerResourceURL[idx+1:] + "?itemPath=artifact"
+ req = NewRequest(t, "GET", url).
+ AddTokenAuth("8061e833a55f6fc0157c98b883e91fcfeeb1a71a")
+ resp = MakeRequest(t, req, http.StatusOK)
+ var downloadResp downloadArtifactResponse
+ DecodeJSON(t, resp, &downloadResp)
+ assert.Len(t, downloadResp.Value, 1)
+ assert.Equal(t, "artifact/abc.txt", downloadResp.Value[0].Path)
+ assert.Equal(t, "file", downloadResp.Value[0].ItemType)
+ assert.Contains(t, downloadResp.Value[0].ContentLocation, "/api/actions_pipeline/_apis/pipelines/workflows/791/artifacts")
+
+ idx = strings.Index(downloadResp.Value[0].ContentLocation, "/api/actions_pipeline/_apis/pipelines/")
+ url = downloadResp.Value[0].ContentLocation[idx:]
+ req = NewRequest(t, "GET", url).
+ AddTokenAuth("8061e833a55f6fc0157c98b883e91fcfeeb1a71a")
+ resp = MakeRequest(t, req, http.StatusOK)
+ body := strings.Repeat("A", 1024)
+ assert.Equal(t, resp.Body.String(), body)
+}
+
+func TestActionsArtifactUploadMultipleFile(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+
+ const testArtifactName = "multi-files"
+
+ // acquire artifact upload url
+ req := NewRequestWithJSON(t, "POST", "/api/actions_pipeline/_apis/pipelines/workflows/791/artifacts", getUploadArtifactRequest{
+ Type: "actions_storage",
+ Name: testArtifactName,
+ }).AddTokenAuth("8061e833a55f6fc0157c98b883e91fcfeeb1a71a")
+ resp := MakeRequest(t, req, http.StatusOK)
+ var uploadResp uploadArtifactResponse
+ DecodeJSON(t, resp, &uploadResp)
+ assert.Contains(t, uploadResp.FileContainerResourceURL, "/api/actions_pipeline/_apis/pipelines/workflows/791/artifacts")
+
+ type uploadingFile struct {
+ Path string
+ Content string
+ MD5 string
+ }
+
+ files := []uploadingFile{
+ {
+ Path: "abc.txt",
+ Content: strings.Repeat("A", 1024),
+ MD5: "1HsSe8LeLWh93ILaw1TEFQ==",
+ },
+ {
+ Path: "xyz/def.txt",
+ Content: strings.Repeat("B", 1024),
+ MD5: "6fgADK/7zjadf+6cB9Q1CQ==",
+ },
+ }
+
+ for _, f := range files {
+ // get upload url
+ idx := strings.Index(uploadResp.FileContainerResourceURL, "/api/actions_pipeline/_apis/pipelines/")
+ url := uploadResp.FileContainerResourceURL[idx:] + "?itemPath=" + testArtifactName + "/" + f.Path
+
+ // upload artifact chunk
+ req = NewRequestWithBody(t, "PUT", url, strings.NewReader(f.Content)).
+ AddTokenAuth("8061e833a55f6fc0157c98b883e91fcfeeb1a71a").
+ SetHeader("Content-Range", "bytes 0-1023/1024").
+ SetHeader("x-tfs-filelength", "1024").
+ SetHeader("x-actions-results-md5", f.MD5) // base64(md5(body))
+ MakeRequest(t, req, http.StatusOK)
+ }
+
+ t.Logf("Create artifact confirm")
+
+ // confirm artifact upload
+ req = NewRequest(t, "PATCH", "/api/actions_pipeline/_apis/pipelines/workflows/791/artifacts?artifactName="+testArtifactName).
+ AddTokenAuth("8061e833a55f6fc0157c98b883e91fcfeeb1a71a")
+ MakeRequest(t, req, http.StatusOK)
+}
+
+func TestActionsArtifactDownloadMultiFiles(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+
+ const testArtifactName = "multi-files"
+
+ req := NewRequest(t, "GET", "/api/actions_pipeline/_apis/pipelines/workflows/791/artifacts").
+ AddTokenAuth("8061e833a55f6fc0157c98b883e91fcfeeb1a71a")
+ resp := MakeRequest(t, req, http.StatusOK)
+ var listResp listArtifactsResponse
+ DecodeJSON(t, resp, &listResp)
+ assert.Equal(t, int64(2), listResp.Count)
+
+ var fileContainerResourceURL string
+ for _, v := range listResp.Value {
+ if v.Name == testArtifactName {
+ fileContainerResourceURL = v.FileContainerResourceURL
+ break
+ }
+ }
+ assert.Contains(t, fileContainerResourceURL, "/api/actions_pipeline/_apis/pipelines/workflows/791/artifacts")
+
+ idx := strings.Index(fileContainerResourceURL, "/api/actions_pipeline/_apis/pipelines/")
+ url := fileContainerResourceURL[idx+1:] + "?itemPath=" + testArtifactName
+ req = NewRequest(t, "GET", url).
+ AddTokenAuth("8061e833a55f6fc0157c98b883e91fcfeeb1a71a")
+ resp = MakeRequest(t, req, http.StatusOK)
+ var downloadResp downloadArtifactResponse
+ DecodeJSON(t, resp, &downloadResp)
+ assert.Len(t, downloadResp.Value, 2)
+
+ downloads := [][]string{{"multi-files/abc.txt", "A"}, {"multi-files/xyz/def.txt", "B"}}
+ for _, v := range downloadResp.Value {
+ var bodyChar string
+ var path string
+ for _, d := range downloads {
+ if v.Path == d[0] {
+ path = d[0]
+ bodyChar = d[1]
+ break
+ }
+ }
+ value := v
+ assert.Equal(t, path, value.Path)
+ assert.Equal(t, "file", value.ItemType)
+ assert.Contains(t, value.ContentLocation, "/api/actions_pipeline/_apis/pipelines/workflows/791/artifacts")
+
+ idx = strings.Index(value.ContentLocation, "/api/actions_pipeline/_apis/pipelines/")
+ url = value.ContentLocation[idx:]
+ req = NewRequest(t, "GET", url).
+ AddTokenAuth("8061e833a55f6fc0157c98b883e91fcfeeb1a71a")
+ resp = MakeRequest(t, req, http.StatusOK)
+ body := strings.Repeat(bodyChar, 1024)
+ assert.Equal(t, resp.Body.String(), body)
+ }
+}
+
+func TestActionsArtifactUploadWithRetentionDays(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+
+ // acquire artifact upload url
+ req := NewRequestWithJSON(t, "POST", "/api/actions_pipeline/_apis/pipelines/workflows/791/artifacts", getUploadArtifactRequest{
+ Type: "actions_storage",
+ Name: "artifact-retention-days",
+ RetentionDays: 9,
+ }).AddTokenAuth("8061e833a55f6fc0157c98b883e91fcfeeb1a71a")
+ resp := MakeRequest(t, req, http.StatusOK)
+ var uploadResp uploadArtifactResponse
+ DecodeJSON(t, resp, &uploadResp)
+ assert.Contains(t, uploadResp.FileContainerResourceURL, "/api/actions_pipeline/_apis/pipelines/workflows/791/artifacts")
+ assert.Contains(t, uploadResp.FileContainerResourceURL, "?retentionDays=9")
+
+ // get upload url
+ idx := strings.Index(uploadResp.FileContainerResourceURL, "/api/actions_pipeline/_apis/pipelines/")
+ url := uploadResp.FileContainerResourceURL[idx:] + "&itemPath=artifact-retention-days/abc.txt"
+
+ // upload artifact chunk
+ body := strings.Repeat("A", 1024)
+ req = NewRequestWithBody(t, "PUT", url, strings.NewReader(body)).
+ AddTokenAuth("8061e833a55f6fc0157c98b883e91fcfeeb1a71a").
+ SetHeader("Content-Range", "bytes 0-1023/1024").
+ SetHeader("x-tfs-filelength", "1024").
+ SetHeader("x-actions-results-md5", "1HsSe8LeLWh93ILaw1TEFQ==") // base64(md5(body))
+ MakeRequest(t, req, http.StatusOK)
+
+ t.Logf("Create artifact confirm")
+
+ // confirm artifact upload
+ req = NewRequest(t, "PATCH", "/api/actions_pipeline/_apis/pipelines/workflows/791/artifacts?artifactName=artifact-retention-days").
+ AddTokenAuth("8061e833a55f6fc0157c98b883e91fcfeeb1a71a")
+ MakeRequest(t, req, http.StatusOK)
+}
+
+func TestActionsArtifactOverwrite(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+
+ {
+ // download old artifact uploaded by tests above, it should 1024 A
+ req := NewRequest(t, "GET", "/api/actions_pipeline/_apis/pipelines/workflows/791/artifacts").
+ AddTokenAuth("8061e833a55f6fc0157c98b883e91fcfeeb1a71a")
+ resp := MakeRequest(t, req, http.StatusOK)
+ var listResp listArtifactsResponse
+ DecodeJSON(t, resp, &listResp)
+
+ idx := strings.Index(listResp.Value[0].FileContainerResourceURL, "/api/actions_pipeline/_apis/pipelines/")
+ url := listResp.Value[0].FileContainerResourceURL[idx+1:] + "?itemPath=artifact"
+ req = NewRequest(t, "GET", url).
+ AddTokenAuth("8061e833a55f6fc0157c98b883e91fcfeeb1a71a")
+ resp = MakeRequest(t, req, http.StatusOK)
+ var downloadResp downloadArtifactResponse
+ DecodeJSON(t, resp, &downloadResp)
+
+ idx = strings.Index(downloadResp.Value[0].ContentLocation, "/api/actions_pipeline/_apis/pipelines/")
+ url = downloadResp.Value[0].ContentLocation[idx:]
+ req = NewRequest(t, "GET", url).
+ AddTokenAuth("8061e833a55f6fc0157c98b883e91fcfeeb1a71a")
+ resp = MakeRequest(t, req, http.StatusOK)
+ body := strings.Repeat("A", 1024)
+ assert.Equal(t, resp.Body.String(), body)
+ }
+
+ {
+ // upload same artifact, it uses 4096 B
+ req := NewRequestWithJSON(t, "POST", "/api/actions_pipeline/_apis/pipelines/workflows/791/artifacts", getUploadArtifactRequest{
+ Type: "actions_storage",
+ Name: "artifact",
+ }).AddTokenAuth("8061e833a55f6fc0157c98b883e91fcfeeb1a71a")
+ resp := MakeRequest(t, req, http.StatusOK)
+ var uploadResp uploadArtifactResponse
+ DecodeJSON(t, resp, &uploadResp)
+
+ idx := strings.Index(uploadResp.FileContainerResourceURL, "/api/actions_pipeline/_apis/pipelines/")
+ url := uploadResp.FileContainerResourceURL[idx:] + "?itemPath=artifact/abc.txt"
+ body := strings.Repeat("B", 4096)
+ req = NewRequestWithBody(t, "PUT", url, strings.NewReader(body)).
+ AddTokenAuth("8061e833a55f6fc0157c98b883e91fcfeeb1a71a").
+ SetHeader("Content-Range", "bytes 0-4095/4096").
+ SetHeader("x-tfs-filelength", "4096").
+ SetHeader("x-actions-results-md5", "wUypcJFeZCK5T6r4lfqzqg==") // base64(md5(body))
+ MakeRequest(t, req, http.StatusOK)
+
+ // confirm artifact upload
+ req = NewRequest(t, "PATCH", "/api/actions_pipeline/_apis/pipelines/workflows/791/artifacts?artifactName=artifact").
+ AddTokenAuth("8061e833a55f6fc0157c98b883e91fcfeeb1a71a")
+ MakeRequest(t, req, http.StatusOK)
+ }
+
+ {
+ // download artifact again, it should 4096 B
+ req := NewRequest(t, "GET", "/api/actions_pipeline/_apis/pipelines/workflows/791/artifacts").
+ AddTokenAuth("8061e833a55f6fc0157c98b883e91fcfeeb1a71a")
+ resp := MakeRequest(t, req, http.StatusOK)
+ var listResp listArtifactsResponse
+ DecodeJSON(t, resp, &listResp)
+
+ var uploadedItem listArtifactsResponseItem
+ for _, item := range listResp.Value {
+ if item.Name == "artifact" {
+ uploadedItem = item
+ break
+ }
+ }
+ assert.Equal(t, "artifact", uploadedItem.Name)
+
+ idx := strings.Index(uploadedItem.FileContainerResourceURL, "/api/actions_pipeline/_apis/pipelines/")
+ url := uploadedItem.FileContainerResourceURL[idx+1:] + "?itemPath=artifact"
+ req = NewRequest(t, "GET", url).
+ AddTokenAuth("8061e833a55f6fc0157c98b883e91fcfeeb1a71a")
+ resp = MakeRequest(t, req, http.StatusOK)
+ var downloadResp downloadArtifactResponse
+ DecodeJSON(t, resp, &downloadResp)
+
+ idx = strings.Index(downloadResp.Value[0].ContentLocation, "/api/actions_pipeline/_apis/pipelines/")
+ url = downloadResp.Value[0].ContentLocation[idx:]
+ req = NewRequest(t, "GET", url).
+ AddTokenAuth("8061e833a55f6fc0157c98b883e91fcfeeb1a71a")
+ resp = MakeRequest(t, req, http.StatusOK)
+ body := strings.Repeat("B", 4096)
+ assert.Equal(t, resp.Body.String(), body)
+ }
+}