forgejo/tests/integration/mirror_push_test.go

404 lines
15 KiB
Go
Raw Normal View History

// Copyright 2021 The Gitea Authors. All rights reserved.
// Copyright 2024 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package integration
import (
"fmt"
"net"
"net/http"
"net/url"
"os"
"os/exec"
"path/filepath"
2021-12-21 04:12:27 +01:00
"strconv"
"testing"
"time"
asymkey_model "forgejo.org/models/asymkey"
"forgejo.org/models/db"
repo_model "forgejo.org/models/repo"
"forgejo.org/models/unit"
"forgejo.org/models/unittest"
user_model "forgejo.org/models/user"
"forgejo.org/modules/git"
"forgejo.org/modules/gitrepo"
"forgejo.org/modules/optional"
"forgejo.org/modules/setting"
"forgejo.org/modules/test"
gitea_context "forgejo.org/services/context"
doctor "forgejo.org/services/doctor"
"forgejo.org/services/migrations"
mirror_service "forgejo.org/services/mirror"
repo_service "forgejo.org/services/repository"
"forgejo.org/tests"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestMirrorPush(t *testing.T) {
onGiteaRun(t, testMirrorPush)
}
func testMirrorPush(t *testing.T, u *url.URL) {
defer tests.PrepareTestEnv(t)()
defer test.MockVariableValue(&setting.Migrations.AllowLocalNetworks, true)()
require.NoError(t, migrations.Init())
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
srcRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
mirrorRepo, err := repo_service.CreateRepositoryDirectly(db.DefaultContext, user, user, repo_service.CreateRepoOptions{
Name: "test-push-mirror",
})
require.NoError(t, err)
ctx := NewAPITestContext(t, user.LowerName, srcRepo.Name)
doCreatePushMirror(ctx, fmt.Sprintf("%s%s/%s", u.String(), url.PathEscape(ctx.Username), url.PathEscape(mirrorRepo.Name)), user.LowerName, userPassword)(t)
doCreatePushMirror(ctx, fmt.Sprintf("%s%s/%s", u.String(), url.PathEscape(ctx.Username), url.PathEscape("does-not-matter")), user.LowerName, userPassword)(t)
mirrors, _, err := repo_model.GetPushMirrorsByRepoID(db.DefaultContext, srcRepo.ID, db.ListOptions{})
require.NoError(t, err)
assert.Len(t, mirrors, 2)
ok := mirror_service.SyncPushMirror(t.Context(), mirrors[0].ID)
assert.True(t, ok)
srcGitRepo, err := gitrepo.OpenRepository(git.DefaultContext, srcRepo)
require.NoError(t, err)
defer srcGitRepo.Close()
srcCommit, err := srcGitRepo.GetBranchCommit("master")
require.NoError(t, err)
mirrorGitRepo, err := gitrepo.OpenRepository(git.DefaultContext, mirrorRepo)
require.NoError(t, err)
defer mirrorGitRepo.Close()
mirrorCommit, err := mirrorGitRepo.GetBranchCommit("master")
require.NoError(t, err)
assert.Equal(t, srcCommit.ID, mirrorCommit.ID)
2021-12-21 04:12:27 +01:00
// Test that we can "repair" push mirrors where the remote doesn't exist in git's state.
// To do that, we artificially remove the remote...
cmd := git.NewCommand(db.DefaultContext, "remote", "rm").AddDynamicArguments(mirrors[0].RemoteName)
_, _, err = cmd.RunStdString(&git.RunOpts{Dir: srcRepo.RepoPath()})
require.NoError(t, err)
// ...then ensure that trying to get its remote address fails
_, err = repo_model.GetPushMirrorRemoteAddress(srcRepo.OwnerName, srcRepo.Name, mirrors[0].RemoteName)
require.Error(t, err)
// ...and that we can fix it.
err = doctor.FixPushMirrorsWithoutGitRemote(db.DefaultContext, nil, true)
require.NoError(t, err)
// ...and after fixing, we only have one remote
mirrors, _, err = repo_model.GetPushMirrorsByRepoID(db.DefaultContext, srcRepo.ID, db.ListOptions{})
require.NoError(t, err)
assert.Len(t, mirrors, 1)
// ...one we can get the address of, and it's not the one we removed
remoteAddress, err := repo_model.GetPushMirrorRemoteAddress(srcRepo.OwnerName, srcRepo.Name, mirrors[0].RemoteName)
require.NoError(t, err)
assert.Contains(t, remoteAddress, "does-not-matter")
2021-12-21 04:12:27 +01:00
// Cleanup
doRemovePushMirror(ctx, fmt.Sprintf("%s%s/%s", u.String(), url.PathEscape(ctx.Username), url.PathEscape(mirrorRepo.Name)), user.LowerName, userPassword, int(mirrors[0].ID))(t)
mirrors, _, err = repo_model.GetPushMirrorsByRepoID(db.DefaultContext, srcRepo.ID, db.ListOptions{})
require.NoError(t, err)
assert.Empty(t, mirrors)
}
func doCreatePushMirror(ctx APITestContext, address, username, password string) func(t *testing.T) {
return func(t *testing.T) {
csrf := GetCSRF(t, ctx.Session, fmt.Sprintf("/%s/%s/settings", url.PathEscape(ctx.Username), url.PathEscape(ctx.Reponame)))
req := NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/%s/settings", url.PathEscape(ctx.Username), url.PathEscape(ctx.Reponame)), map[string]string{
"_csrf": csrf,
"action": "push-mirror-add",
"push_mirror_address": address,
"push_mirror_username": username,
"push_mirror_password": password,
"push_mirror_interval": "0",
})
ctx.Session.MakeRequest(t, req, http.StatusSeeOther)
flashCookie := ctx.Session.GetCookie(gitea_context.CookieNameFlash)
assert.NotNil(t, flashCookie)
assert.Contains(t, flashCookie.Value, "success")
}
}
2021-12-21 04:12:27 +01:00
func doRemovePushMirror(ctx APITestContext, address, username, password string, pushMirrorID int) func(t *testing.T) {
return func(t *testing.T) {
csrf := GetCSRF(t, ctx.Session, fmt.Sprintf("/%s/%s/settings", url.PathEscape(ctx.Username), url.PathEscape(ctx.Reponame)))
req := NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/%s/settings", url.PathEscape(ctx.Username), url.PathEscape(ctx.Reponame)), map[string]string{
"_csrf": csrf,
"action": "push-mirror-remove",
"push_mirror_id": strconv.Itoa(pushMirrorID),
"push_mirror_address": address,
"push_mirror_username": username,
"push_mirror_password": password,
"push_mirror_interval": "0",
})
ctx.Session.MakeRequest(t, req, http.StatusSeeOther)
2021-12-21 04:12:27 +01:00
flashCookie := ctx.Session.GetCookie(gitea_context.CookieNameFlash)
2021-12-21 04:12:27 +01:00
assert.NotNil(t, flashCookie)
assert.Contains(t, flashCookie.Value, "success")
}
}
func TestSSHPushMirror(t *testing.T) {
_, err := exec.LookPath("ssh")
if err != nil {
t.Skip("SSH executable not present")
}
onGiteaRun(t, func(t *testing.T, _ *url.URL) {
defer test.MockVariableValue(&setting.Migrations.AllowLocalNetworks, true)()
defer test.MockVariableValue(&setting.Mirror.Enabled, true)()
defer test.MockVariableValue(&setting.SSH.RootPath, t.TempDir())()
require.NoError(t, migrations.Init())
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
srcRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
assert.False(t, srcRepo.HasWiki())
sess := loginUser(t, user.Name)
pushToRepo, _, f := tests.CreateDeclarativeRepoWithOptions(t, user, tests.DeclarativeRepoOptions{
Name: optional.Some("push-mirror-test"),
AutoInit: optional.Some(false),
EnabledUnits: optional.Some([]unit.Type{unit.TypeCode}),
})
defer f()
sshURL := fmt.Sprintf("ssh://%s@%s/%s.git", setting.SSH.User, net.JoinHostPort(setting.SSH.ListenHost, strconv.Itoa(setting.SSH.ListenPort)), pushToRepo.FullName())
t.Run("Mutual exclusive", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
req := NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/settings", srcRepo.FullName()), map[string]string{
"_csrf": GetCSRF(t, sess, fmt.Sprintf("/%s/settings", srcRepo.FullName())),
"action": "push-mirror-add",
"push_mirror_address": sshURL,
"push_mirror_username": "username",
"push_mirror_password": "password",
"push_mirror_use_ssh": "true",
"push_mirror_interval": "0",
})
resp := sess.MakeRequest(t, req, http.StatusOK)
htmlDoc := NewHTMLParser(t, resp.Body)
errMsg := htmlDoc.Find(".ui.negative.message").Text()
assert.Contains(t, errMsg, "Cannot use public key and password based authentication in combination.")
})
inputSelector := `input[id="push_mirror_use_ssh"]`
t.Run("SSH not available", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
defer test.MockVariableValue(&git.HasSSHExecutable, false)()
req := NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/settings", srcRepo.FullName()), map[string]string{
"_csrf": GetCSRF(t, sess, fmt.Sprintf("/%s/settings", srcRepo.FullName())),
"action": "push-mirror-add",
"push_mirror_address": sshURL,
"push_mirror_use_ssh": "true",
"push_mirror_interval": "0",
})
resp := sess.MakeRequest(t, req, http.StatusOK)
htmlDoc := NewHTMLParser(t, resp.Body)
errMsg := htmlDoc.Find(".ui.negative.message").Text()
assert.Contains(t, errMsg, "SSH authentication isn't available.")
htmlDoc.AssertElement(t, inputSelector, false)
})
t.Run("SSH available", func(t *testing.T) {
req := NewRequest(t, "GET", fmt.Sprintf("/%s/settings", srcRepo.FullName()))
resp := sess.MakeRequest(t, req, http.StatusOK)
htmlDoc := NewHTMLParser(t, resp.Body)
htmlDoc.AssertElement(t, inputSelector, true)
})
t.Run("Normal", func(t *testing.T) {
var pushMirror *repo_model.PushMirror
t.Run("Adding", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
req := NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/settings", srcRepo.FullName()), map[string]string{
"_csrf": GetCSRF(t, sess, fmt.Sprintf("/%s/settings", srcRepo.FullName())),
"action": "push-mirror-add",
"push_mirror_address": sshURL,
"push_mirror_use_ssh": "true",
"push_mirror_interval": "0",
})
sess.MakeRequest(t, req, http.StatusSeeOther)
flashCookie := sess.GetCookie(gitea_context.CookieNameFlash)
assert.NotNil(t, flashCookie)
assert.Contains(t, flashCookie.Value, "success")
pushMirror = unittest.AssertExistsAndLoadBean(t, &repo_model.PushMirror{RepoID: srcRepo.ID})
assert.NotEmpty(t, pushMirror.PrivateKey)
assert.NotEmpty(t, pushMirror.PublicKey)
})
publickey := ""
t.Run("Publickey", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
req := NewRequest(t, "GET", fmt.Sprintf("/%s/settings", srcRepo.FullName()))
resp := sess.MakeRequest(t, req, http.StatusOK)
htmlDoc := NewHTMLParser(t, resp.Body)
publickey = htmlDoc.Find(".ui.table td a[data-clipboard-text]").AttrOr("data-clipboard-text", "")
assert.Equal(t, publickey, pushMirror.GetPublicKey())
})
t.Run("Add deploy key", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
req := NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/settings/keys", pushToRepo.FullName()), map[string]string{
"_csrf": GetCSRF(t, sess, fmt.Sprintf("/%s/settings/keys", pushToRepo.FullName())),
"title": "push mirror key",
"content": publickey,
"is_writable": "true",
})
sess.MakeRequest(t, req, http.StatusSeeOther)
unittest.AssertExistsAndLoadBean(t, &asymkey_model.DeployKey{Name: "push mirror key", RepoID: pushToRepo.ID})
})
t.Run("Synchronize", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
req := NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/settings", srcRepo.FullName()), map[string]string{
"_csrf": GetCSRF(t, sess, fmt.Sprintf("/%s/settings", srcRepo.FullName())),
"action": "push-mirror-sync",
"push_mirror_id": strconv.FormatInt(pushMirror.ID, 10),
})
sess.MakeRequest(t, req, http.StatusSeeOther)
})
t.Run("Check mirrored content", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
shortSHA := "1032bbf17f"
req := NewRequest(t, "GET", fmt.Sprintf("/%s", srcRepo.FullName()))
resp := sess.MakeRequest(t, req, http.StatusOK)
htmlDoc := NewHTMLParser(t, resp.Body)
assert.Contains(t, htmlDoc.Find(".shortsha").Text(), shortSHA)
assert.Eventually(t, func() bool {
req = NewRequest(t, "GET", fmt.Sprintf("/%s", pushToRepo.FullName()))
Fix TestSSHPushMirror/Normal/Check_mirrored_content test (#7852) On slower CI hardware test `TestSSHPushMirror/Normal/Check_mirrored_content ` may throw an error like ``` === TestSSHPushMirror/Normal/Check_known_host_keys (tests/integration/mirror_push_test.go:312) --- FAIL: TestSSHPushMirror (5.38s) testlogger.go:405: 2025/05/12 15:48:41 ...les/storage/local.go:33:NewLocalStorage() [I] Creating new Local Storage at /src/forgejo/tests/gitea-lfs-meta testlogger.go:405: 2025/05/12 15:48:42 ...eb/routing/logger.go:102:func1() [I] router: completed GET /user/login for test-mock:12345, 200 OK in 4.6ms @ auth/auth.go:145(auth.SignIn) testlogger.go:405: 2025/05/12 15:48:42 ...eb/routing/logger.go:102:func1() [I] router: completed POST /user/login for test-mock:12345, 303 See Other in 14.8ms @ auth/auth.go:179(auth.SignInPost) testlogger.go:405: 2025/05/12 15:48:42 ...odels/user/avatar.go:59:GenerateRandomAvatar() [I] New random avatar created: 2 testlogger.go:405: 2025/05/12 15:48:42 ...eb/routing/logger.go:102:func1() [I] router: completed GET /user2/repo2/settings for test-mock:12345, 200 OK in 53.9ms @ setting/setting.go:300(setting.Settings) --- FAIL: TestSSHPushMirror/Normal (2.81s) --- FAIL: TestSSHPushMirror/Normal/Check_mirrored_content (2.26s) testlogger.go:405: 2025/05/12 15:48:43 ...eb/routing/logger.go:102:func1() [I] router: completed GET /user2/repo2 for test-mock:12345, 200 OK in 89.1ms @ repo/view.go:798(repo.Home) testlogger.go:405: 2025/05/12 15:48:43 ...eb/routing/logger.go:102:func1() [I] router: completed GET /api/internal/serv/command/10000/user2/push-mirror-test?mode=2&verb=git-receive-pack for 127.0.0.1:0, 200 OK in 5.2ms @ private/serv.go:79(private.ServCommand) testlogger.go:405: 2025/05/12 15:48:43 ...eb/routing/logger.go:102:func1() [I] router: completed POST /api/internal/hook/pre-receive/user2/push-mirror-test for 127.0.0.1:0, 200 OK in 10.0ms @ private/hook_pre_receive.go:178(private.HookPreReceive) mirror_push_test.go:304: Error Trace: /src/forgejo/tests/integration/integration_test.go:564 /src/forgejo/tests/integration/integration_test.go:228 /src/forgejo/tests/integration/mirror_push_test.go:304 /usr/lib/go-1.24/src/runtime/asm_amd64.s:1700 Error: Not equal: expected: 200 actual : 303 Test: TestSSHPushMirror/Normal/Check_mirrored_content Messages: Request: GET /user2/push-mirror-test mirror_push_test.go:304: Response: <a href="/user2/push-mirror-test">See Other</a>. testlogger.go:405: 2025/05/12 15:48:44 ...eb/routing/logger.go:102:func1() [I] router: completed GET /user2/push-mirror-test for test-mock:12345, 303 See Other in 34.7ms @ repo/view.go:798(repo.Home) testlogger.go:405: 2025/05/12 15:48:44 ...eb/routing/logger.go:102:func1() [I] router: completed POST /api/internal/hook/post-receive/user2/push-mirror-test for 127.0.0.1:0, 200 OK in 304.3ms @ private/hook_post_receive.go:35(private.HookPostReceive) testlogger.go:405: 2025/05/12 15:48:44 ...eb/routing/logger.go:102:func1() [I] router: completed POST /api/internal/ssh/10000/update/10000 for 127.0.0.1:0, 200 OK in 6.6ms @ private/key.go:16(private.UpdatePublicKeyInRepo) testlogger.go:405: 2025/05/12 15:48:45 ...eb/routing/logger.go:102:func1() [I] router: completed GET /user2/push-mirror-test for test-mock:12345, 200 OK in 121.0ms @ repo/view.go:798(repo.Home) ``` because it does not allow temporary 303 responses while waiting in `assert.Eventually` for repo to be updated. Fixes: 03508b33a8e890b05d845bbd8ead8672b8f03578 Author-Change-Id: IB#1160889 Signed-off-by: Pawel Boguslawski <pawel.boguslawski@ib.pl> ## Checklist The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org). ### Tests - I added test coverage for Go changes... - [x] in their respective `*_test.go` for unit tests. - [ ] in the `tests/integration` directory if it involves interactions with a live Forgejo server. - I added test coverage for JavaScript changes... - [ ] in `web_src/js/*.test.js` if it can be unit tested. - [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)). ### Documentation - [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change. - [x] I did not document these changes and I do not expect someone else to do it. ### Release notes - [ ] I do not want this change to show in the release notes. - [ ] I want the title to show in the release notes with a link to this pull request. - [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title. Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7852 Reviewed-by: Gusted <gusted@noreply.codeberg.org> Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org> Co-authored-by: pboguslawski <pboguslawski@noreply.codeberg.org> Co-committed-by: pboguslawski <pboguslawski@noreply.codeberg.org>
2025-05-24 11:06:48 +02:00
resp = sess.MakeRequest(t, req, NoExpectedStatus)
htmlDoc = NewHTMLParser(t, resp.Body)
Fix TestSSHPushMirror/Normal/Check_mirrored_content test (#7852) On slower CI hardware test `TestSSHPushMirror/Normal/Check_mirrored_content ` may throw an error like ``` === TestSSHPushMirror/Normal/Check_known_host_keys (tests/integration/mirror_push_test.go:312) --- FAIL: TestSSHPushMirror (5.38s) testlogger.go:405: 2025/05/12 15:48:41 ...les/storage/local.go:33:NewLocalStorage() [I] Creating new Local Storage at /src/forgejo/tests/gitea-lfs-meta testlogger.go:405: 2025/05/12 15:48:42 ...eb/routing/logger.go:102:func1() [I] router: completed GET /user/login for test-mock:12345, 200 OK in 4.6ms @ auth/auth.go:145(auth.SignIn) testlogger.go:405: 2025/05/12 15:48:42 ...eb/routing/logger.go:102:func1() [I] router: completed POST /user/login for test-mock:12345, 303 See Other in 14.8ms @ auth/auth.go:179(auth.SignInPost) testlogger.go:405: 2025/05/12 15:48:42 ...odels/user/avatar.go:59:GenerateRandomAvatar() [I] New random avatar created: 2 testlogger.go:405: 2025/05/12 15:48:42 ...eb/routing/logger.go:102:func1() [I] router: completed GET /user2/repo2/settings for test-mock:12345, 200 OK in 53.9ms @ setting/setting.go:300(setting.Settings) --- FAIL: TestSSHPushMirror/Normal (2.81s) --- FAIL: TestSSHPushMirror/Normal/Check_mirrored_content (2.26s) testlogger.go:405: 2025/05/12 15:48:43 ...eb/routing/logger.go:102:func1() [I] router: completed GET /user2/repo2 for test-mock:12345, 200 OK in 89.1ms @ repo/view.go:798(repo.Home) testlogger.go:405: 2025/05/12 15:48:43 ...eb/routing/logger.go:102:func1() [I] router: completed GET /api/internal/serv/command/10000/user2/push-mirror-test?mode=2&verb=git-receive-pack for 127.0.0.1:0, 200 OK in 5.2ms @ private/serv.go:79(private.ServCommand) testlogger.go:405: 2025/05/12 15:48:43 ...eb/routing/logger.go:102:func1() [I] router: completed POST /api/internal/hook/pre-receive/user2/push-mirror-test for 127.0.0.1:0, 200 OK in 10.0ms @ private/hook_pre_receive.go:178(private.HookPreReceive) mirror_push_test.go:304: Error Trace: /src/forgejo/tests/integration/integration_test.go:564 /src/forgejo/tests/integration/integration_test.go:228 /src/forgejo/tests/integration/mirror_push_test.go:304 /usr/lib/go-1.24/src/runtime/asm_amd64.s:1700 Error: Not equal: expected: 200 actual : 303 Test: TestSSHPushMirror/Normal/Check_mirrored_content Messages: Request: GET /user2/push-mirror-test mirror_push_test.go:304: Response: <a href="/user2/push-mirror-test">See Other</a>. testlogger.go:405: 2025/05/12 15:48:44 ...eb/routing/logger.go:102:func1() [I] router: completed GET /user2/push-mirror-test for test-mock:12345, 303 See Other in 34.7ms @ repo/view.go:798(repo.Home) testlogger.go:405: 2025/05/12 15:48:44 ...eb/routing/logger.go:102:func1() [I] router: completed POST /api/internal/hook/post-receive/user2/push-mirror-test for 127.0.0.1:0, 200 OK in 304.3ms @ private/hook_post_receive.go:35(private.HookPostReceive) testlogger.go:405: 2025/05/12 15:48:44 ...eb/routing/logger.go:102:func1() [I] router: completed POST /api/internal/ssh/10000/update/10000 for 127.0.0.1:0, 200 OK in 6.6ms @ private/key.go:16(private.UpdatePublicKeyInRepo) testlogger.go:405: 2025/05/12 15:48:45 ...eb/routing/logger.go:102:func1() [I] router: completed GET /user2/push-mirror-test for test-mock:12345, 200 OK in 121.0ms @ repo/view.go:798(repo.Home) ``` because it does not allow temporary 303 responses while waiting in `assert.Eventually` for repo to be updated. Fixes: 03508b33a8e890b05d845bbd8ead8672b8f03578 Author-Change-Id: IB#1160889 Signed-off-by: Pawel Boguslawski <pawel.boguslawski@ib.pl> ## Checklist The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org). ### Tests - I added test coverage for Go changes... - [x] in their respective `*_test.go` for unit tests. - [ ] in the `tests/integration` directory if it involves interactions with a live Forgejo server. - I added test coverage for JavaScript changes... - [ ] in `web_src/js/*.test.js` if it can be unit tested. - [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)). ### Documentation - [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change. - [x] I did not document these changes and I do not expect someone else to do it. ### Release notes - [ ] I do not want this change to show in the release notes. - [ ] I want the title to show in the release notes with a link to this pull request. - [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title. Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7852 Reviewed-by: Gusted <gusted@noreply.codeberg.org> Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org> Co-authored-by: pboguslawski <pboguslawski@noreply.codeberg.org> Co-committed-by: pboguslawski <pboguslawski@noreply.codeberg.org>
2025-05-24 11:06:48 +02:00
return resp.Code == http.StatusOK && htmlDoc.Find(".shortsha").Text() == shortSHA
}, time.Second*30, time.Second)
})
t.Run("Check known host keys", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
knownHosts, err := os.ReadFile(filepath.Join(setting.SSH.RootPath, "known_hosts"))
require.NoError(t, err)
publicKey, err := os.ReadFile(setting.SSH.ServerHostKeys[0] + ".pub")
require.NoError(t, err)
assert.Contains(t, string(knownHosts), string(publicKey))
})
})
})
}
func TestPushMirrorSettings(t *testing.T) {
onGiteaRun(t, func(t *testing.T, u *url.URL) {
defer test.MockVariableValue(&setting.Migrations.AllowLocalNetworks, true)()
defer test.MockVariableValue(&setting.Mirror.Enabled, true)()
require.NoError(t, migrations.Init())
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
srcRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
srcRepo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3})
assert.False(t, srcRepo.HasWiki())
sess := loginUser(t, user.Name)
pushToRepo, _, f := tests.CreateDeclarativeRepoWithOptions(t, user, tests.DeclarativeRepoOptions{
Name: optional.Some("push-mirror-test"),
AutoInit: optional.Some(false),
EnabledUnits: optional.Some([]unit.Type{unit.TypeCode}),
})
defer f()
t.Run("Adding", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
req := NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/settings", srcRepo2.FullName()), map[string]string{
"_csrf": GetCSRF(t, sess, fmt.Sprintf("/%s/settings", srcRepo2.FullName())),
"action": "push-mirror-add",
"push_mirror_address": u.String() + pushToRepo.FullName(),
"push_mirror_interval": "0",
})
sess.MakeRequest(t, req, http.StatusSeeOther)
req = NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/settings", srcRepo.FullName()), map[string]string{
"_csrf": GetCSRF(t, sess, fmt.Sprintf("/%s/settings", srcRepo.FullName())),
"action": "push-mirror-add",
"push_mirror_address": u.String() + pushToRepo.FullName(),
"push_mirror_interval": "0",
})
sess.MakeRequest(t, req, http.StatusSeeOther)
flashCookie := sess.GetCookie(gitea_context.CookieNameFlash)
assert.NotNil(t, flashCookie)
assert.Contains(t, flashCookie.Value, "success")
})
mirrors, _, err := repo_model.GetPushMirrorsByRepoID(db.DefaultContext, srcRepo.ID, db.ListOptions{})
require.NoError(t, err)
assert.Len(t, mirrors, 1)
mirrorID := mirrors[0].ID
mirrors, _, err = repo_model.GetPushMirrorsByRepoID(db.DefaultContext, srcRepo2.ID, db.ListOptions{})
require.NoError(t, err)
assert.Len(t, mirrors, 1)
t.Run("Interval", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
unittest.AssertExistsAndLoadBean(t, &repo_model.PushMirror{ID: mirrorID - 1})
req := NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/settings", srcRepo.FullName()), map[string]string{
"_csrf": GetCSRF(t, sess, fmt.Sprintf("/%s/settings", srcRepo.FullName())),
"action": "push-mirror-update",
"push_mirror_id": strconv.FormatInt(mirrorID-1, 10),
"push_mirror_interval": "10m0s",
})
sess.MakeRequest(t, req, http.StatusNotFound)
req = NewRequestWithValues(t, "POST", fmt.Sprintf("/%s/settings", srcRepo.FullName()), map[string]string{
"_csrf": GetCSRF(t, sess, fmt.Sprintf("/%s/settings", srcRepo.FullName())),
"action": "push-mirror-update",
"push_mirror_id": strconv.FormatInt(mirrorID, 10),
"push_mirror_interval": "10m0s",
})
sess.MakeRequest(t, req, http.StatusSeeOther)
flashCookie := sess.GetCookie(gitea_context.CookieNameFlash)
assert.NotNil(t, flashCookie)
assert.Contains(t, flashCookie.Value, "success")
})
})
}