summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorFuXiaoHei <fuxiaohei@vip.qq.com>2023-05-19 21:37:57 +0800
committerGitHub <noreply@github.com>2023-05-19 21:37:57 +0800
commitc757765a9e5c2d4f73b1a7c3debe3548c735bd54 (patch)
treeffed7692321760ea4f9c72670ed31437b52ff0e0 /tests
parent7985cde84df5ee93bfb37b20681d69e67d3f32fc (diff)
downloadgitea-c757765a9e5c2d4f73b1a7c3debe3548c735bd54.tar.gz
gitea-c757765a9e5c2d4f73b1a7c3debe3548c735bd54.zip
Implement actions artifacts (#22738)
Implement action artifacts server api. This change is used for supporting https://github.com/actions/upload-artifact and https://github.com/actions/download-artifact in gitea actions. It can run sample workflow from doc https://docs.github.com/en/actions/using-workflows/storing-workflow-data-as-artifacts. The api design is inspired by https://github.com/nektos/act/blob/master/pkg/artifacts/server.go and includes some changes from gitea internal structs and methods. Actions artifacts contains two parts: - Gitea server api and storage (this pr implement basic design without some complex cases supports) - Runner communicate with gitea server api (in comming) Old pr https://github.com/go-gitea/gitea/pull/22345 is outdated after actions merged. I create new pr from main branch. ![897f7694-3e0f-4f7c-bb4b-9936624ead45](https://user-images.githubusercontent.com/2142787/219382371-eb3cf810-e4e0-456b-a8ff-aecc2b1a1032.jpeg) Add artifacts list in actions workflow page.
Diffstat (limited to 'tests')
-rw-r--r--tests/integration/api_actions_artifact_test.go143
-rw-r--r--tests/mssql.ini.tmpl3
-rw-r--r--tests/mysql.ini.tmpl3
-rw-r--r--tests/mysql8.ini.tmpl3
-rw-r--r--tests/pgsql.ini.tmpl3
-rw-r--r--tests/sqlite.ini.tmpl3
6 files changed, 158 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 0000000000..5f3884d9d6
--- /dev/null
+++ b/tests/integration/api_actions_artifact_test.go
@@ -0,0 +1,143 @@
+// 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"
+)
+
+func TestActionsArtifactUpload(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+
+ type uploadArtifactResponse struct {
+ FileContainerResourceURL string `json:"fileContainerResourceUrl"`
+ }
+
+ type getUploadArtifactRequest struct {
+ Type string
+ Name string
+ }
+
+ // acquire artifact upload url
+ req := NewRequestWithJSON(t, "POST", "/api/actions_pipeline/_apis/pipelines/workflows/791/artifacts", getUploadArtifactRequest{
+ Type: "actions_storage",
+ Name: "artifact",
+ })
+ req = addTokenAuthHeader(req, "Bearer 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))
+ req = addTokenAuthHeader(req, "Bearer 8061e833a55f6fc0157c98b883e91fcfeeb1a71a")
+ req.Header.Add("Content-Range", "bytes 0-1023/1024")
+ req.Header.Add("x-tfs-filelength", "1024")
+ req.Header.Add("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")
+ req = addTokenAuthHeader(req, "Bearer 8061e833a55f6fc0157c98b883e91fcfeeb1a71a")
+ MakeRequest(t, req, http.StatusOK)
+}
+
+func TestActionsArtifactUploadNotExist(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+
+ // artifact id 54321 not exist
+ url := "/api/actions_pipeline/_apis/pipelines/workflows/791/artifacts/54321/upload?itemPath=artifact/abc.txt"
+ body := strings.Repeat("A", 1024)
+ req := NewRequestWithBody(t, "PUT", url, strings.NewReader(body))
+ req = addTokenAuthHeader(req, "Bearer 8061e833a55f6fc0157c98b883e91fcfeeb1a71a")
+ req.Header.Add("Content-Range", "bytes 0-1023/1024")
+ req.Header.Add("x-tfs-filelength", "1024")
+ req.Header.Add("x-actions-results-md5", "1HsSe8LeLWh93ILaw1TEFQ==") // base64(md5(body))
+ MakeRequest(t, req, http.StatusNotFound)
+}
+
+func TestActionsArtifactConfirmUpload(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+
+ req := NewRequest(t, "PATCH", "/api/actions_pipeline/_apis/pipelines/workflows/791/artifacts")
+ req = addTokenAuthHeader(req, "Bearer 8061e833a55f6fc0157c98b883e91fcfeeb1a71a")
+ resp := MakeRequest(t, req, http.StatusOK)
+ assert.Contains(t, resp.Body.String(), "success")
+}
+
+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)
+}
+
+func TestActionsArtifactDownload(t *testing.T) {
+ defer tests.PrepareTestEnv(t)()
+
+ type (
+ listArtifactsResponseItem struct {
+ Name string `json:"name"`
+ FileContainerResourceURL string `json:"fileContainerResourceUrl"`
+ }
+ listArtifactsResponse struct {
+ Count int64 `json:"count"`
+ Value []listArtifactsResponseItem `json:"value"`
+ }
+ )
+
+ req := NewRequest(t, "GET", "/api/actions_pipeline/_apis/pipelines/workflows/791/artifacts")
+ req = addTokenAuthHeader(req, "Bearer 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")
+
+ type (
+ downloadArtifactResponseItem struct {
+ Path string `json:"path"`
+ ItemType string `json:"itemType"`
+ ContentLocation string `json:"contentLocation"`
+ }
+ downloadArtifactResponse struct {
+ Value []downloadArtifactResponseItem `json:"value"`
+ }
+ )
+
+ idx := strings.Index(listResp.Value[0].FileContainerResourceURL, "/api/actions_pipeline/_apis/pipelines/")
+ url := listResp.Value[0].FileContainerResourceURL[idx+1:]
+ req = NewRequest(t, "GET", url)
+ req = addTokenAuthHeader(req, "Bearer 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)
+ req = addTokenAuthHeader(req, "Bearer 8061e833a55f6fc0157c98b883e91fcfeeb1a71a")
+ resp = MakeRequest(t, req, http.StatusOK)
+ body := strings.Repeat("A", 1024)
+ assert.Equal(t, resp.Body.String(), body)
+}
diff --git a/tests/mssql.ini.tmpl b/tests/mssql.ini.tmpl
index 09e75acb01..10e70d35fc 100644
--- a/tests/mssql.ini.tmpl
+++ b/tests/mssql.ini.tmpl
@@ -108,3 +108,6 @@ PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mssql/data/lfs
[packages]
ENABLED = true
+
+[actions]
+ENABLED = true
diff --git a/tests/mysql.ini.tmpl b/tests/mysql.ini.tmpl
index 6fcb2792c3..9d6bbd65e6 100644
--- a/tests/mysql.ini.tmpl
+++ b/tests/mysql.ini.tmpl
@@ -117,3 +117,6 @@ PASSWORD = debug
USE_TLS = true
SKIP_TLS_VERIFY = true
REPLY_TO_ADDRESS = incoming+%{token}@localhost
+
+[actions]
+ENABLED = true
diff --git a/tests/mysql8.ini.tmpl b/tests/mysql8.ini.tmpl
index e37052da8c..6336441741 100644
--- a/tests/mysql8.ini.tmpl
+++ b/tests/mysql8.ini.tmpl
@@ -105,3 +105,6 @@ PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mysql8/data/lfs
[packages]
ENABLED = true
+
+[actions]
+ENABLED = true
diff --git a/tests/pgsql.ini.tmpl b/tests/pgsql.ini.tmpl
index 0f538797c2..dd45ab717a 100644
--- a/tests/pgsql.ini.tmpl
+++ b/tests/pgsql.ini.tmpl
@@ -129,3 +129,6 @@ MINIO_CHECKSUM_ALGORITHM = md5
[packages]
ENABLED = true
+
+[actions]
+ENABLED = true
diff --git a/tests/sqlite.ini.tmpl b/tests/sqlite.ini.tmpl
index 24aff9af43..969c15698d 100644
--- a/tests/sqlite.ini.tmpl
+++ b/tests/sqlite.ini.tmpl
@@ -114,3 +114,6 @@ FILE_EXTENSIONS = .html
RENDER_COMMAND = `go run build/test-echo.go`
IS_INPUT_FILE = false
RENDER_CONTENT_MODE=sanitized
+
+[actions]
+ENABLED = true