mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2026-05-12 22:10:25 +00:00
feat: replace repo based server-side hooks with centralised hooks (#10397)
This PR is replacing repository based hooks hooks with centralised files, this way the files don't need to be copied into every repository, only one line of config need to be added in the repository. Closes: #3523 Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10397 Reviewed-by: Gusted <gusted@noreply.codeberg.org>
This commit is contained in:
parent
f05ff7ec5b
commit
73b30acbd0
26 changed files with 418 additions and 439 deletions
0
tests/install.ini.tmpl
Normal file
0
tests/install.ini.tmpl
Normal file
|
|
@ -426,11 +426,11 @@ func TestAPICron(t *testing.T) {
|
|||
AddTokenAuth(token)
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
assert.Equal(t, "31", resp.Header().Get("X-Total-Count"))
|
||||
assert.Equal(t, "30", resp.Header().Get("X-Total-Count"))
|
||||
|
||||
var crons []api.Cron
|
||||
DecodeJSON(t, resp, &crons)
|
||||
assert.Len(t, crons, 31)
|
||||
assert.Len(t, crons, 30)
|
||||
})
|
||||
|
||||
t.Run("Execute", func(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ package integration
|
|||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
repo_model "forgejo.org/models/repo"
|
||||
|
|
@ -44,169 +45,169 @@ func getIssueConfig(t *testing.T, owner, repo string) api.IssueConfig {
|
|||
}
|
||||
|
||||
func TestAPIRepoGetIssueConfig(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
onApplicationRun(t, func(t *testing.T, _ *url.URL) {
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 49})
|
||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 49})
|
||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||
t.Run("Default", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
t.Run("Default", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
issueConfig := getIssueConfig(t, owner.Name, repo.Name)
|
||||
|
||||
issueConfig := getIssueConfig(t, owner.Name, repo.Name)
|
||||
assert.True(t, issueConfig.BlankIssuesEnabled)
|
||||
assert.Empty(t, issueConfig.ContactLinks)
|
||||
})
|
||||
|
||||
assert.True(t, issueConfig.BlankIssuesEnabled)
|
||||
assert.Empty(t, issueConfig.ContactLinks)
|
||||
})
|
||||
t.Run("DisableBlankIssues", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
t.Run("DisableBlankIssues", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
config := make(map[string]any)
|
||||
config["blank_issues_enabled"] = false
|
||||
|
||||
config := make(map[string]any)
|
||||
config["blank_issues_enabled"] = false
|
||||
createIssueConfig(t, owner, repo, config)
|
||||
|
||||
createIssueConfig(t, owner, repo, config)
|
||||
issueConfig := getIssueConfig(t, owner.Name, repo.Name)
|
||||
|
||||
issueConfig := getIssueConfig(t, owner.Name, repo.Name)
|
||||
assert.False(t, issueConfig.BlankIssuesEnabled)
|
||||
assert.Empty(t, issueConfig.ContactLinks)
|
||||
})
|
||||
|
||||
assert.False(t, issueConfig.BlankIssuesEnabled)
|
||||
assert.Empty(t, issueConfig.ContactLinks)
|
||||
})
|
||||
t.Run("ContactLinks", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
t.Run("ContactLinks", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
contactLink := make(map[string]string)
|
||||
contactLink["name"] = "TestName"
|
||||
contactLink["url"] = "https://example.com"
|
||||
contactLink["about"] = "TestAbout"
|
||||
|
||||
contactLink := make(map[string]string)
|
||||
contactLink["name"] = "TestName"
|
||||
contactLink["url"] = "https://example.com"
|
||||
contactLink["about"] = "TestAbout"
|
||||
config := make(map[string]any)
|
||||
config["contact_links"] = []map[string]string{contactLink}
|
||||
|
||||
config := make(map[string]any)
|
||||
config["contact_links"] = []map[string]string{contactLink}
|
||||
createIssueConfig(t, owner, repo, config)
|
||||
|
||||
createIssueConfig(t, owner, repo, config)
|
||||
issueConfig := getIssueConfig(t, owner.Name, repo.Name)
|
||||
|
||||
issueConfig := getIssueConfig(t, owner.Name, repo.Name)
|
||||
assert.True(t, issueConfig.BlankIssuesEnabled)
|
||||
assert.Len(t, issueConfig.ContactLinks, 1)
|
||||
|
||||
assert.True(t, issueConfig.BlankIssuesEnabled)
|
||||
assert.Len(t, issueConfig.ContactLinks, 1)
|
||||
assert.Equal(t, "TestName", issueConfig.ContactLinks[0].Name)
|
||||
assert.Equal(t, "https://example.com", issueConfig.ContactLinks[0].URL)
|
||||
assert.Equal(t, "TestAbout", issueConfig.ContactLinks[0].About)
|
||||
})
|
||||
|
||||
assert.Equal(t, "TestName", issueConfig.ContactLinks[0].Name)
|
||||
assert.Equal(t, "https://example.com", issueConfig.ContactLinks[0].URL)
|
||||
assert.Equal(t, "TestAbout", issueConfig.ContactLinks[0].About)
|
||||
})
|
||||
t.Run("Full", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
t.Run("Full", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
contactLink := make(map[string]string)
|
||||
contactLink["name"] = "TestName"
|
||||
contactLink["url"] = "https://example.com"
|
||||
contactLink["about"] = "TestAbout"
|
||||
|
||||
contactLink := make(map[string]string)
|
||||
contactLink["name"] = "TestName"
|
||||
contactLink["url"] = "https://example.com"
|
||||
contactLink["about"] = "TestAbout"
|
||||
config := make(map[string]any)
|
||||
config["blank_issues_enabled"] = false
|
||||
config["contact_links"] = []map[string]string{contactLink}
|
||||
|
||||
config := make(map[string]any)
|
||||
config["blank_issues_enabled"] = false
|
||||
config["contact_links"] = []map[string]string{contactLink}
|
||||
createIssueConfig(t, owner, repo, config)
|
||||
|
||||
createIssueConfig(t, owner, repo, config)
|
||||
issueConfig := getIssueConfig(t, owner.Name, repo.Name)
|
||||
|
||||
issueConfig := getIssueConfig(t, owner.Name, repo.Name)
|
||||
assert.False(t, issueConfig.BlankIssuesEnabled)
|
||||
assert.Len(t, issueConfig.ContactLinks, 1)
|
||||
|
||||
assert.False(t, issueConfig.BlankIssuesEnabled)
|
||||
assert.Len(t, issueConfig.ContactLinks, 1)
|
||||
|
||||
assert.Equal(t, "TestName", issueConfig.ContactLinks[0].Name)
|
||||
assert.Equal(t, "https://example.com", issueConfig.ContactLinks[0].URL)
|
||||
assert.Equal(t, "TestAbout", issueConfig.ContactLinks[0].About)
|
||||
assert.Equal(t, "TestName", issueConfig.ContactLinks[0].Name)
|
||||
assert.Equal(t, "https://example.com", issueConfig.ContactLinks[0].URL)
|
||||
assert.Equal(t, "TestAbout", issueConfig.ContactLinks[0].About)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestAPIRepoIssueConfigPaths(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
onApplicationRun(t, func(t *testing.T, _ *url.URL) {
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 49})
|
||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 49})
|
||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||
|
||||
templateConfigCandidates := []string{
|
||||
".forgejo/ISSUE_TEMPLATE/config",
|
||||
".forgejo/issue_template/config",
|
||||
".gitea/ISSUE_TEMPLATE/config",
|
||||
".gitea/issue_template/config",
|
||||
".github/ISSUE_TEMPLATE/config",
|
||||
".github/issue_template/config",
|
||||
"docs/issue_template/config",
|
||||
}
|
||||
|
||||
for _, candidate := range templateConfigCandidates {
|
||||
for _, extension := range []string{".yaml", ".yml"} {
|
||||
fullPath := candidate + extension
|
||||
t.Run(fullPath, func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
configMap := make(map[string]any)
|
||||
configMap["blank_issues_enabled"] = false
|
||||
|
||||
configData, err := yaml.Marshal(configMap)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = createFileInBranch(owner, repo, fullPath, repo.DefaultBranch, string(configData))
|
||||
require.NoError(t, err)
|
||||
|
||||
issueConfig := getIssueConfig(t, owner.Name, repo.Name)
|
||||
|
||||
assert.False(t, issueConfig.BlankIssuesEnabled)
|
||||
assert.Empty(t, issueConfig.ContactLinks)
|
||||
|
||||
err = deleteFileInBranch(owner, repo, fullPath, repo.DefaultBranch)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
templateConfigCandidates := []string{
|
||||
".forgejo/ISSUE_TEMPLATE/config",
|
||||
".forgejo/issue_template/config",
|
||||
".gitea/ISSUE_TEMPLATE/config",
|
||||
".gitea/issue_template/config",
|
||||
".github/ISSUE_TEMPLATE/config",
|
||||
".github/issue_template/config",
|
||||
"docs/issue_template/config",
|
||||
}
|
||||
}
|
||||
|
||||
for _, candidate := range templateConfigCandidates {
|
||||
for _, extension := range []string{".yaml", ".yml"} {
|
||||
fullPath := candidate + extension
|
||||
t.Run(fullPath, func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
configMap := make(map[string]any)
|
||||
configMap["blank_issues_enabled"] = false
|
||||
|
||||
configData, err := yaml.Marshal(configMap)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = createFileInBranch(owner, repo, fullPath, repo.DefaultBranch, string(configData))
|
||||
require.NoError(t, err)
|
||||
|
||||
issueConfig := getIssueConfig(t, owner.Name, repo.Name)
|
||||
|
||||
assert.False(t, issueConfig.BlankIssuesEnabled)
|
||||
assert.Empty(t, issueConfig.ContactLinks)
|
||||
|
||||
err = deleteFileInBranch(owner, repo, fullPath, repo.DefaultBranch)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestAPIRepoValidateIssueConfig(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
onApplicationRun(t, func(t *testing.T, _ *url.URL) {
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 49})
|
||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 49})
|
||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issue_config/validate", owner.Name, repo.Name)
|
||||
|
||||
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issue_config/validate", owner.Name, repo.Name)
|
||||
t.Run("Valid", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
t.Run("Valid", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
req := NewRequest(t, "GET", urlStr)
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
req := NewRequest(t, "GET", urlStr)
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
var issueConfigValidation api.IssueConfigValidation
|
||||
DecodeJSON(t, resp, &issueConfigValidation)
|
||||
|
||||
var issueConfigValidation api.IssueConfigValidation
|
||||
DecodeJSON(t, resp, &issueConfigValidation)
|
||||
assert.True(t, issueConfigValidation.Valid)
|
||||
assert.Empty(t, issueConfigValidation.Message)
|
||||
})
|
||||
|
||||
assert.True(t, issueConfigValidation.Valid)
|
||||
assert.Empty(t, issueConfigValidation.Message)
|
||||
})
|
||||
t.Run("Invalid", func(t *testing.T) {
|
||||
dirs := []string{".gitea", ".forgejo", "docs"}
|
||||
for _, dir := range dirs {
|
||||
t.Run(dir, func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
defer func() {
|
||||
deleteFileInBranch(owner, repo, fmt.Sprintf("%s/ISSUE_TEMPLATE/config.yaml", dir), repo.DefaultBranch)
|
||||
}()
|
||||
|
||||
t.Run("Invalid", func(t *testing.T) {
|
||||
dirs := []string{".gitea", ".forgejo", "docs"}
|
||||
for _, dir := range dirs {
|
||||
t.Run(dir, func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
defer func() {
|
||||
deleteFileInBranch(owner, repo, fmt.Sprintf("%s/ISSUE_TEMPLATE/config.yaml", dir), repo.DefaultBranch)
|
||||
}()
|
||||
config := make(map[string]any)
|
||||
config["blank_issues_enabled"] = "Test"
|
||||
|
||||
config := make(map[string]any)
|
||||
config["blank_issues_enabled"] = "Test"
|
||||
createIssueConfigInDirectory(t, owner, repo, dir, config)
|
||||
|
||||
createIssueConfigInDirectory(t, owner, repo, dir, config)
|
||||
req := NewRequest(t, "GET", urlStr)
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
req := NewRequest(t, "GET", urlStr)
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
var issueConfigValidation api.IssueConfigValidation
|
||||
DecodeJSON(t, resp, &issueConfigValidation)
|
||||
|
||||
var issueConfigValidation api.IssueConfigValidation
|
||||
DecodeJSON(t, resp, &issueConfigValidation)
|
||||
|
||||
assert.False(t, issueConfigValidation.Valid)
|
||||
assert.NotEmpty(t, issueConfigValidation.Message)
|
||||
})
|
||||
}
|
||||
assert.False(t, issueConfigValidation.Valid)
|
||||
assert.NotEmpty(t, issueConfigValidation.Message)
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import (
|
|||
"io"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
auth_model "forgejo.org/models/auth"
|
||||
|
|
@ -44,96 +45,96 @@ func TestEmptyRepo(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestEmptyRepoAddFile(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
onApplicationRun(t, func(t *testing.T, u *url.URL) {
|
||||
session := loginUser(t, "user30")
|
||||
req := NewRequest(t, "GET", "/user30/empty/_new/"+setting.Repository.DefaultBranch)
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
doc := NewHTMLParser(t, resp.Body).Find(`input[name="commit_choice"]`)
|
||||
assert.Empty(t, doc.AttrOr("checked", "_no_"))
|
||||
req = NewRequestWithValues(t, "POST", "/user30/empty/_new/"+setting.Repository.DefaultBranch, map[string]string{
|
||||
"commit_choice": "direct",
|
||||
"tree_path": "test-file.md",
|
||||
"content": "newly-added-test-file",
|
||||
"commit_mail_id": "32",
|
||||
})
|
||||
|
||||
session := loginUser(t, "user30")
|
||||
req := NewRequest(t, "GET", "/user30/empty/_new/"+setting.Repository.DefaultBranch)
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
doc := NewHTMLParser(t, resp.Body).Find(`input[name="commit_choice"]`)
|
||||
assert.Empty(t, doc.AttrOr("checked", "_no_"))
|
||||
req = NewRequestWithValues(t, "POST", "/user30/empty/_new/"+setting.Repository.DefaultBranch, map[string]string{
|
||||
"commit_choice": "direct",
|
||||
"tree_path": "test-file.md",
|
||||
"content": "newly-added-test-file",
|
||||
"commit_mail_id": "32",
|
||||
resp = session.MakeRequest(t, req, http.StatusSeeOther)
|
||||
redirect := test.RedirectURL(resp)
|
||||
assert.Equal(t, "/user30/empty/src/branch/"+setting.Repository.DefaultBranch+"/test-file.md", redirect)
|
||||
|
||||
req = NewRequest(t, "GET", redirect)
|
||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||
assert.Contains(t, resp.Body.String(), "newly-added-test-file")
|
||||
})
|
||||
|
||||
resp = session.MakeRequest(t, req, http.StatusSeeOther)
|
||||
redirect := test.RedirectURL(resp)
|
||||
assert.Equal(t, "/user30/empty/src/branch/"+setting.Repository.DefaultBranch+"/test-file.md", redirect)
|
||||
|
||||
req = NewRequest(t, "GET", redirect)
|
||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||
assert.Contains(t, resp.Body.String(), "newly-added-test-file")
|
||||
}
|
||||
|
||||
func TestEmptyRepoUploadFile(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
onApplicationRun(t, func(t *testing.T, u *url.URL) {
|
||||
session := loginUser(t, "user30")
|
||||
req := NewRequest(t, "GET", "/user30/empty/_new/"+setting.Repository.DefaultBranch)
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
doc := NewHTMLParser(t, resp.Body).Find(`input[name="commit_choice"]`)
|
||||
assert.Empty(t, doc.AttrOr("checked", "_no_"))
|
||||
|
||||
session := loginUser(t, "user30")
|
||||
req := NewRequest(t, "GET", "/user30/empty/_new/"+setting.Repository.DefaultBranch)
|
||||
resp := session.MakeRequest(t, req, http.StatusOK)
|
||||
doc := NewHTMLParser(t, resp.Body).Find(`input[name="commit_choice"]`)
|
||||
assert.Empty(t, doc.AttrOr("checked", "_no_"))
|
||||
body := &bytes.Buffer{}
|
||||
mpForm := multipart.NewWriter(body)
|
||||
file, _ := mpForm.CreateFormFile("file", "uploaded-file.txt")
|
||||
_, _ = io.Copy(file, bytes.NewBufferString("newly-uploaded-test-file"))
|
||||
_ = mpForm.Close()
|
||||
|
||||
body := &bytes.Buffer{}
|
||||
mpForm := multipart.NewWriter(body)
|
||||
file, _ := mpForm.CreateFormFile("file", "uploaded-file.txt")
|
||||
_, _ = io.Copy(file, bytes.NewBufferString("newly-uploaded-test-file"))
|
||||
_ = mpForm.Close()
|
||||
req = NewRequestWithBody(t, "POST", "/user30/empty/upload-file", body)
|
||||
req.Header.Add("Content-Type", mpForm.FormDataContentType())
|
||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||
respMap := map[string]string{}
|
||||
require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &respMap))
|
||||
filesFullpathKey := fmt.Sprintf("files_fullpath[%s]", respMap["uuid"])
|
||||
req = NewRequestWithValues(t, "POST", "/user30/empty/_upload/"+setting.Repository.DefaultBranch, map[string]string{
|
||||
"commit_choice": "direct",
|
||||
"files": respMap["uuid"],
|
||||
filesFullpathKey: "uploaded-file.txt",
|
||||
"tree_path": "",
|
||||
"commit_mail_id": "-1",
|
||||
})
|
||||
resp = session.MakeRequest(t, req, http.StatusSeeOther)
|
||||
redirect := test.RedirectURL(resp)
|
||||
assert.Equal(t, "/user30/empty/src/branch/"+setting.Repository.DefaultBranch+"/", redirect)
|
||||
|
||||
req = NewRequestWithBody(t, "POST", "/user30/empty/upload-file", body)
|
||||
req.Header.Add("Content-Type", mpForm.FormDataContentType())
|
||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||
respMap := map[string]string{}
|
||||
require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &respMap))
|
||||
filesFullpathKey := fmt.Sprintf("files_fullpath[%s]", respMap["uuid"])
|
||||
req = NewRequestWithValues(t, "POST", "/user30/empty/_upload/"+setting.Repository.DefaultBranch, map[string]string{
|
||||
"commit_choice": "direct",
|
||||
"files": respMap["uuid"],
|
||||
filesFullpathKey: "uploaded-file.txt",
|
||||
"tree_path": "",
|
||||
"commit_mail_id": "-1",
|
||||
req = NewRequest(t, "GET", redirect)
|
||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||
assert.Contains(t, resp.Body.String(), "uploaded-file.txt")
|
||||
})
|
||||
resp = session.MakeRequest(t, req, http.StatusSeeOther)
|
||||
redirect := test.RedirectURL(resp)
|
||||
assert.Equal(t, "/user30/empty/src/branch/"+setting.Repository.DefaultBranch+"/", redirect)
|
||||
|
||||
req = NewRequest(t, "GET", redirect)
|
||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||
assert.Contains(t, resp.Body.String(), "uploaded-file.txt")
|
||||
}
|
||||
|
||||
func TestEmptyRepoAddFileByAPI(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
onApplicationRun(t, func(t *testing.T, _ *url.URL) {
|
||||
session := loginUser(t, "user30")
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||
|
||||
session := loginUser(t, "user30")
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||
req := NewRequestWithJSON(t, "POST", "/api/v1/repos/user30/empty/contents/new-file.txt", &api.CreateFileOptions{
|
||||
FileOptions: api.FileOptions{
|
||||
NewBranchName: "new_branch",
|
||||
Message: "init",
|
||||
},
|
||||
ContentBase64: base64.StdEncoding.EncodeToString([]byte("newly-added-api-file")),
|
||||
}).AddTokenAuth(token)
|
||||
|
||||
req := NewRequestWithJSON(t, "POST", "/api/v1/repos/user30/empty/contents/new-file.txt", &api.CreateFileOptions{
|
||||
FileOptions: api.FileOptions{
|
||||
NewBranchName: "new_branch",
|
||||
Message: "init",
|
||||
},
|
||||
ContentBase64: base64.StdEncoding.EncodeToString([]byte("newly-added-api-file")),
|
||||
}).AddTokenAuth(token)
|
||||
resp := MakeRequest(t, req, http.StatusCreated)
|
||||
var fileResponse api.FileResponse
|
||||
DecodeJSON(t, resp, &fileResponse)
|
||||
expectedHTMLURL := setting.AppURL + "user30/empty/src/branch/new_branch/new-file.txt"
|
||||
assert.Equal(t, expectedHTMLURL, *fileResponse.Content.HTMLURL)
|
||||
|
||||
resp := MakeRequest(t, req, http.StatusCreated)
|
||||
var fileResponse api.FileResponse
|
||||
DecodeJSON(t, resp, &fileResponse)
|
||||
expectedHTMLURL := setting.AppURL + "user30/empty/src/branch/new_branch/new-file.txt"
|
||||
assert.Equal(t, expectedHTMLURL, *fileResponse.Content.HTMLURL)
|
||||
req = NewRequest(t, "GET", "/user30/empty/src/branch/new_branch/new-file.txt")
|
||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||
assert.Contains(t, resp.Body.String(), "newly-added-api-file")
|
||||
|
||||
req = NewRequest(t, "GET", "/user30/empty/src/branch/new_branch/new-file.txt")
|
||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||
assert.Contains(t, resp.Body.String(), "newly-added-api-file")
|
||||
|
||||
req = NewRequest(t, "GET", "/api/v1/repos/user30/empty").
|
||||
AddTokenAuth(token)
|
||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||
var apiRepo api.Repository
|
||||
DecodeJSON(t, resp, &apiRepo)
|
||||
assert.Equal(t, "new_branch", apiRepo.DefaultBranch)
|
||||
req = NewRequest(t, "GET", "/api/v1/repos/user30/empty").
|
||||
AddTokenAuth(token)
|
||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||
var apiRepo api.Repository
|
||||
DecodeJSON(t, resp, &apiRepo)
|
||||
assert.Equal(t, "new_branch", apiRepo.DefaultBranch)
|
||||
})
|
||||
}
|
||||
|
||||
func TestEmptyRepoAPIRequestsReturn404(t *testing.T) {
|
||||
|
|
|
|||
99
tests/integration/git_hooks_test.go
Normal file
99
tests/integration/git_hooks_test.go
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
// Copyright 2026 The Forgejo Authors c/o Codeberg e.V.. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
package integration
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
"forgejo.org/models/auth"
|
||||
repo_model "forgejo.org/models/repo"
|
||||
"forgejo.org/models/unittest"
|
||||
user_model "forgejo.org/models/user"
|
||||
"forgejo.org/modules/git"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestCustomGitHooks(t *testing.T) {
|
||||
onApplicationRun(t, func(t *testing.T, u *url.URL) {
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||
|
||||
httpContext := NewAPITestContext(t, owner.Name, repo.Name, auth.AccessTokenScopeReadRepository)
|
||||
|
||||
dstPath := t.TempDir()
|
||||
|
||||
u.Path = httpContext.GitPath()
|
||||
u.User = url.UserPassword(owner.Name, userPassword)
|
||||
|
||||
doGitClone(dstPath, u)(t)
|
||||
|
||||
customHooksDir := path.Join(repo.RepoPath(), "hooks")
|
||||
|
||||
hookNames := []string{"pre-receive", "update", "post-receive"}
|
||||
|
||||
for _, hookName := range hookNames {
|
||||
customPath := path.Join(customHooksDir, hookName+".d")
|
||||
err := os.MkdirAll(customPath, 0x755)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = os.WriteFile(path.Join(customPath, "append-proof"), customGitHookTpl(hookName), 0x755)
|
||||
require.NoError(t, err)
|
||||
|
||||
// The legacy, already existing gitea script might be there in the hooks directory in old installations,
|
||||
// here it's ensured that these scripts filtered out when custom hooks run
|
||||
err = os.WriteFile(path.Join(customPath, "gitea"), customGitHookGiteaTpl(), 0x755)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
fd, err := os.Create(path.Join(dstPath, "hooks-test.txt"))
|
||||
require.NoError(t, err)
|
||||
|
||||
err = fd.Close()
|
||||
require.NoError(t, err)
|
||||
|
||||
_, _, err = git.NewCommand(git.DefaultContext, "checkout", "master").RunStdString(&git.RunOpts{Dir: dstPath})
|
||||
require.NoError(t, err)
|
||||
|
||||
err = os.WriteFile(path.Join(dstPath, "hooks-test.txt"), []byte("test"), 0x644)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, _, err = git.NewCommand(git.DefaultContext, "add", "hooks-test.txt").RunStdString(&git.RunOpts{Dir: dstPath})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, _, err = git.NewCommand(git.DefaultContext, "commit", "-m", "Add hooks-test.txt").RunStdString(&git.RunOpts{Dir: dstPath})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, _, err = git.NewCommand(git.DefaultContext, "push", "origin", "master").RunStdString(&git.RunOpts{Dir: dstPath})
|
||||
require.NoError(t, err)
|
||||
|
||||
data, err := os.ReadFile(path.Join(customHooksDir, "hooks-proof.txt"))
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, `pre-receive
|
||||
update
|
||||
post-receive
|
||||
`, string(data))
|
||||
})
|
||||
}
|
||||
|
||||
func customGitHookTpl(hookName string) []byte {
|
||||
hookStr := fmt.Sprintf(`#!/usr/bin/env sh
|
||||
echo "%s" >> $(dirname $0)/../hooks-proof.txt
|
||||
`, hookName)
|
||||
|
||||
return []byte(hookStr)
|
||||
}
|
||||
|
||||
func customGitHookGiteaTpl() []byte {
|
||||
hookStr := `#!/usr/bin/env sh
|
||||
echo "legacy gitea script shouldn't be called!"
|
||||
exit 1
|
||||
`
|
||||
|
||||
return []byte(hookStr)
|
||||
}
|
||||
|
|
@ -201,6 +201,7 @@ func standardCommitAndPushTest(t *testing.T, dstPath string) (little, big string
|
|||
func lfsCommitAndPushTest(t *testing.T, dstPath string) (littleLFS, bigLFS string) {
|
||||
t.Run("LFS", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
defer git.NewCommand(git.DefaultContext, "lfs").AddArguments("uninstall").Run(&git.RunOpts{Dir: dstPath})
|
||||
prefix := "lfs-data-file-"
|
||||
err := git.NewCommand(git.DefaultContext, "lfs").AddArguments("install").Run(&git.RunOpts{Dir: dstPath})
|
||||
require.NoError(t, err)
|
||||
|
|
|
|||
|
|
@ -5,29 +5,29 @@ package integration
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"forgejo.org/tests"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestRepoMergeCommitRevert(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
session := loginUser(t, "user2")
|
||||
onApplicationRun(t, func(t *testing.T, _ *url.URL) {
|
||||
session := loginUser(t, "user2")
|
||||
|
||||
req := NewRequestWithValues(t, "POST", "/user2/test_commit_revert/_cherrypick/deebcbc752e540bab4ce3ee713d3fc8fdc35b2f7/main", map[string]string{
|
||||
"last_commit": "deebcbc752e540bab4ce3ee713d3fc8fdc35b2f7",
|
||||
"page_has_posted": "true",
|
||||
"revert": "true",
|
||||
"commit_summary": "reverting test commit",
|
||||
"commit_message": "test message",
|
||||
"commit_choice": "direct",
|
||||
"new_branch_name": "test-revert-branch-1",
|
||||
"commit_mail_id": "-1",
|
||||
req := NewRequestWithValues(t, "POST", "/user2/test_commit_revert/_cherrypick/deebcbc752e540bab4ce3ee713d3fc8fdc35b2f7/main", map[string]string{
|
||||
"last_commit": "deebcbc752e540bab4ce3ee713d3fc8fdc35b2f7",
|
||||
"page_has_posted": "true",
|
||||
"revert": "true",
|
||||
"commit_summary": "reverting test commit",
|
||||
"commit_message": "test message",
|
||||
"commit_choice": "direct",
|
||||
"new_branch_name": "test-revert-branch-1",
|
||||
"commit_mail_id": "-1",
|
||||
})
|
||||
resp := session.MakeRequest(t, req, http.StatusSeeOther)
|
||||
|
||||
// A successful revert redirects to the main branch
|
||||
assert.Equal(t, "/user2/test_commit_revert/src/branch/main", resp.Header().Get("Location"))
|
||||
})
|
||||
resp := session.MakeRequest(t, req, http.StatusSeeOther)
|
||||
|
||||
// A successful revert redirects to the main branch
|
||||
assert.Equal(t, "/user2/test_commit_revert/src/branch/main", resp.Header().Get("Location"))
|
||||
}
|
||||
|
|
|
|||
2
tests/unittest.ini.tmpl
Normal file
2
tests/unittest.ini.tmpl
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
[security]
|
||||
INSTALL_LOCK = true
|
||||
Loading…
Add table
Add a link
Reference in a new issue