Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add Gitea support #4229

Merged
merged 61 commits into from
Mar 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
f5acff3
Add initial Gitea client structure
mvdkleijn Feb 11, 2024
af4d081
Add various missing config flags
mvdkleijn Feb 11, 2024
cfa19c5
initial gitea support added
florianbeisel Feb 12, 2024
599c518
Merge branch 'main' of https://github.com/florianbeisel/atlantis
florianbeisel Feb 12, 2024
b213f96
Merge remote-tracking branch 'remotes/florian/main' into test-merge
mvdkleijn Feb 13, 2024
b8e68de
Fix some post-merge issues
mvdkleijn Feb 13, 2024
97f8859
Replace HidePrevCommandComments by version from @florianbeisel
mvdkleijn Feb 13, 2024
3a1cb4a
Update mocks
mvdkleijn Feb 13, 2024
04e87ef
feat: add Webhook Signature Verification
florianbeisel Feb 13, 2024
3a2ce8e
fix: use release version in go.mod
florianbeisel Feb 13, 2024
011c06f
Set default Gitea url to cloud.gitea.com
mvdkleijn Feb 14, 2024
6c78b50
Fix and Add tests for Gitea
mvdkleijn Feb 14, 2024
8b2c16e
Merge branch 'test-merge' of github.com:mvdkleijn/atlantis into test-…
mvdkleijn Feb 14, 2024
f973c88
Fix missing copyright header
mvdkleijn Feb 14, 2024
182f62a
Changed comment to reflect no max comment length
mvdkleijn Feb 14, 2024
a4f268a
Implement GetCloneURL()
florianbeisel Feb 14, 2024
37dec75
Decode Base64 before passing on downloaded file content
florianbeisel Feb 14, 2024
c2904d4
Enable Gitea client as API Client
florianbeisel Feb 14, 2024
7a0bb60
Remove unneded comments
florianbeisel Feb 16, 2024
a9ef335
Remove old redundant file
mvdkleijn Feb 16, 2024
159b053
Merge pull request #2 from mvdkleijn/test-merge
mvdkleijn Feb 16, 2024
6db3497
Merge branch 'main' into feat-gitea-support
mvdkleijn Feb 16, 2024
085dda0
fix: invalid version number in go.mod
florianbeisel Feb 17, 2024
1987b41
fix: remove unnecessary type conversions
florianbeisel Feb 17, 2024
a0b424f
fix: removed unused function
florianbeisel Feb 17, 2024
015c560
fix: remove unnecessary type conversion of decodedData
florianbeisel Feb 17, 2024
6cdbb94
fix: fixes some tests
florianbeisel Feb 17, 2024
c375dac
Merge branch 'main' into feat-gitea-support
florianbeisel Feb 17, 2024
241165e
Correct gitea.com URL
mvdkleijn Feb 17, 2024
23f9d3d
Add Gitea to website docs
mvdkleijn Feb 17, 2024
28d75f8
fix: TestPost_UnsupportedGiteaEvent
florianbeisel Feb 18, 2024
2ef95a6
revert version downgrades
florianbeisel Feb 18, 2024
2b2f6e5
docs: add Gitea documentation to Guide section
florianbeisel Feb 18, 2024
4b7e557
docs: fix copy paste mistake
florianbeisel Feb 18, 2024
12bbba2
Merge branch 'main' into feat-gitea-support
jamengual Feb 19, 2024
f5a1e36
Update cmd/server_test.go
mvdkleijn Feb 20, 2024
9261196
Clarify usage msg for --gitea-base-url
mvdkleijn Feb 20, 2024
b9ed3cf
Apply suggestions from code review
mvdkleijn Feb 20, 2024
ac45625
Merge branch 'main' into feat-gitea-support
jamengual Feb 20, 2024
1fdcfd2
Turn ebreak number into const with comments
mvdkleijn Feb 21, 2024
72ff096
Add --gitea-page-size server argument
mvdkleijn Feb 21, 2024
917c0a2
Merge branch 'main' into feat-gitea-support
chenrui333 Feb 21, 2024
20be094
Fix broken test
mvdkleijn Feb 21, 2024
f4a6819
Merge branch 'main' into feat-gitea-support
jamengual Feb 24, 2024
7babe93
Fix event parser and comment parser
mvdkleijn Feb 26, 2024
e1f5418
Merge branch 'main' into feat-gitea-support
jamengual Feb 26, 2024
b4c3383
Add missing app permission to docs
mvdkleijn Feb 27, 2024
143f301
Merge branch 'main' into feat-gitea-support
mvdkleijn Feb 28, 2024
06ada67
Make Gitea client conform to updated interface
mvdkleijn Feb 28, 2024
8bb4f77
Update server/events/vcs/gitea/client.go
mvdkleijn Feb 28, 2024
fa2e839
Remove no longer needed logger
mvdkleijn Feb 28, 2024
ee870c7
Add extra logging statements for Gitea client
mvdkleijn Feb 28, 2024
7b3ea7a
Merge branch 'main' into feat-gitea-support
X-Guardian Feb 28, 2024
5470619
Add debug statements
mvdkleijn Mar 5, 2024
f1ae2c3
Merge branch 'main' into feat-gitea-support
mvdkleijn Mar 5, 2024
ed242e5
Merge branch 'main' into feat-gitea-support
florianbeisel Mar 7, 2024
1ebe7e4
Merge branch 'main' into feat-gitea-support
florianbeisel Mar 8, 2024
4b60895
Merge branch 'main' into feat-gitea-support
mvdkleijn Mar 9, 2024
bdd5f75
Merge branch 'main' into feat-gitea-support
mvdkleijn Mar 11, 2024
b462668
Merge branch 'main' into feat-gitea-support
mvdkleijn Mar 14, 2024
78c1ade
Merge branch 'main' into feat-gitea-support
mvdkleijn Mar 17, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 59 additions & 7 deletions cmd/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,11 @@ const (
GHOrganizationFlag = "gh-org"
GHWebhookSecretFlag = "gh-webhook-secret" // nolint: gosec
GHAllowMergeableBypassApply = "gh-allow-mergeable-bypass-apply" // nolint: gosec
GiteaBaseURLFlag = "gitea-base-url"
GiteaTokenFlag = "gitea-token"
GiteaUserFlag = "gitea-user"
GiteaWebhookSecretFlag = "gitea-webhook-secret" // nolint: gosec
GiteaPageSizeFlag = "gitea-page-size"
GitlabHostnameFlag = "gitlab-hostname"
GitlabTokenFlag = "gitlab-token"
GitlabUserFlag = "gitlab-user"
Expand Down Expand Up @@ -156,6 +161,8 @@ const (
DefaultExecutableName = "atlantis"
DefaultMarkdownTemplateOverridesDir = "~/.markdown_templates"
DefaultGHHostname = "github.com"
DefaultGiteaBaseURL = "https://gitea.com"
DefaultGiteaPageSize = 30
DefaultGitlabHostname = "gitlab.com"
DefaultLockingDBType = "boltdb"
DefaultLogLevel = "info"
Expand Down Expand Up @@ -318,6 +325,22 @@ var stringFlags = map[string]stringFlag{
"This means that an attacker could spoof calls to Atlantis and cause it to perform malicious actions. " +
"Should be specified via the ATLANTIS_GH_WEBHOOK_SECRET environment variable.",
},
GiteaBaseURLFlag: {
description: "Base URL of Gitea server installation. Must include 'http://' or 'https://'.",
},
GiteaUserFlag: {
description: "Gitea username of API user.",
defaultValue: "",
},
GiteaTokenFlag: {
description: "Gitea token of API user. Can also be specified via the ATLANTIS_GITEA_TOKEN environment variable.",
},
GiteaWebhookSecretFlag: {
description: "Optional secret used to validate Gitea webhooks." +
" SECURITY WARNING: If not specified, Atlantis won't be able to validate that the incoming webhook call came from Gitea. " +
"This means that an attacker could spoof calls to Atlantis and cause it to perform malicious actions. " +
"Should be specified via the ATLANTIS_GITEA_WEBHOOK_SECRET environment variable.",
},
GitlabHostnameFlag: {
description: "Hostname of your GitLab Enterprise installation. If using gitlab.com, no need to set.",
defaultValue: DefaultGitlabHostname,
Expand Down Expand Up @@ -568,6 +591,10 @@ var intFlags = map[string]intFlag{
" If merge base is further behind than this number of commits from any of branches heads, full fetch will be performed.",
defaultValue: DefaultCheckoutDepth,
},
GiteaPageSizeFlag: {
description: "Optional value that specifies the number of results per page to expect from Gitea.",
defaultValue: DefaultGiteaPageSize,
},
ParallelPoolSize: {
description: "Max size of the wait group that runs parallel plans and applies (if enabled).",
defaultValue: DefaultParallelPoolSize,
Expand Down Expand Up @@ -813,6 +840,12 @@ func (s *ServerCmd) setDefaults(c *server.UserConfig) {
if c.GitlabHostname == "" {
c.GitlabHostname = DefaultGitlabHostname
}
if c.GiteaBaseURL == "" {
c.GiteaBaseURL = DefaultGiteaBaseURL
}
if c.GiteaPageSize == 0 {
c.GiteaPageSize = DefaultGiteaPageSize
}
if c.BitbucketBaseURL == "" {
c.BitbucketBaseURL = DefaultBitbucketBaseURL
}
Expand Down Expand Up @@ -885,12 +918,17 @@ func (s *ServerCmd) validate(userConfig server.UserConfig) error {
// The following combinations are valid.
// 1. github user and token set
// 2. github app ID and (key file set or key set)
// 3. gitlab user and token set
// 4. bitbucket user and token set
// 5. azuredevops user and token set
// 6. any combination of the above
vcsErr := fmt.Errorf("--%s/--%s or --%s/--%s or --%s/--%s or --%s/--%s or --%s/--%s or --%s/--%s must be set", GHUserFlag, GHTokenFlag, GHAppIDFlag, GHAppKeyFileFlag, GHAppIDFlag, GHAppKeyFlag, GitlabUserFlag, GitlabTokenFlag, BitbucketUserFlag, BitbucketTokenFlag, ADUserFlag, ADTokenFlag)
if ((userConfig.GithubUser == "") != (userConfig.GithubToken == "")) || ((userConfig.GitlabUser == "") != (userConfig.GitlabToken == "")) || ((userConfig.BitbucketUser == "") != (userConfig.BitbucketToken == "")) || ((userConfig.AzureDevopsUser == "") != (userConfig.AzureDevopsToken == "")) {
// 3. gitea user and token set
// 4. gitlab user and token set
// 5. bitbucket user and token set
// 6. azuredevops user and token set
// 7. any combination of the above
vcsErr := fmt.Errorf("--%s/--%s or --%s/--%s or --%s/--%s or --%s/--%s or --%s/--%s or --%s/--%s or --%s/--%s must be set", GHUserFlag, GHTokenFlag, GHAppIDFlag, GHAppKeyFileFlag, GHAppIDFlag, GHAppKeyFlag, GiteaUserFlag, GiteaTokenFlag, GitlabUserFlag, GitlabTokenFlag, BitbucketUserFlag, BitbucketTokenFlag, ADUserFlag, ADTokenFlag)
if ((userConfig.GithubUser == "") != (userConfig.GithubToken == "")) ||
((userConfig.GiteaUser == "") != (userConfig.GiteaToken == "")) ||
((userConfig.GitlabUser == "") != (userConfig.GitlabToken == "")) ||
((userConfig.BitbucketUser == "") != (userConfig.BitbucketToken == "")) ||
((userConfig.AzureDevopsUser == "") != (userConfig.AzureDevopsToken == "")) {
return vcsErr
}
if (userConfig.GithubAppID != 0) && ((userConfig.GithubAppKey == "") && (userConfig.GithubAppKeyFile == "")) {
Expand All @@ -901,7 +939,7 @@ func (s *ServerCmd) validate(userConfig server.UserConfig) error {
}
// At this point, we know that there can't be a single user/token without
// its partner, but we haven't checked if any user/token is set at all.
if userConfig.GithubAppID == 0 && userConfig.GithubUser == "" && userConfig.GitlabUser == "" && userConfig.BitbucketUser == "" && userConfig.AzureDevopsUser == "" {
if userConfig.GithubAppID == 0 && userConfig.GithubUser == "" && userConfig.GiteaUser == "" && userConfig.GitlabUser == "" && userConfig.BitbucketUser == "" && userConfig.AzureDevopsUser == "" {
return vcsErr
}

Expand All @@ -924,6 +962,14 @@ func (s *ServerCmd) validate(userConfig server.UserConfig) error {
return fmt.Errorf("--%s must have http:// or https://, got %q", BitbucketBaseURLFlag, userConfig.BitbucketBaseURL)
}

parsed, err = url.Parse(userConfig.GiteaBaseURL)
if err != nil {
return fmt.Errorf("error parsing --%s flag value %q: %s", GiteaWebhookSecretFlag, userConfig.GiteaBaseURL, err)
}
if parsed.Scheme != "http" && parsed.Scheme != "https" {
return fmt.Errorf("--%s must have http:// or https://, got %q", GiteaBaseURLFlag, userConfig.GiteaBaseURL)
}

if userConfig.RepoConfig != "" && userConfig.RepoConfigJSON != "" {
return fmt.Errorf("cannot use --%s and --%s at the same time", RepoConfigFlag, RepoConfigJSONFlag)
}
Expand All @@ -936,6 +982,8 @@ func (s *ServerCmd) validate(userConfig server.UserConfig) error {
GitlabWebhookSecretFlag: userConfig.GitlabWebhookSecret,
BitbucketTokenFlag: userConfig.BitbucketToken,
BitbucketWebhookSecretFlag: userConfig.BitbucketWebhookSecret,
GiteaTokenFlag: userConfig.GiteaToken,
GiteaWebhookSecretFlag: userConfig.GiteaWebhookSecret,
} {
if strings.Contains(token, "\n") {
s.Logger.Warn("--%s contains a newline which is usually unintentional", name)
Expand Down Expand Up @@ -1029,6 +1077,7 @@ func (s *ServerCmd) setVarFileAllowlist(userConfig *server.UserConfig) {
// trimAtSymbolFromUsers trims @ from the front of the github and gitlab usernames
func (s *ServerCmd) trimAtSymbolFromUsers(userConfig *server.UserConfig) {
userConfig.GithubUser = strings.TrimPrefix(userConfig.GithubUser, "@")
userConfig.GiteaUser = strings.TrimPrefix(userConfig.GiteaUser, "@")
userConfig.GitlabUser = strings.TrimPrefix(userConfig.GitlabUser, "@")
userConfig.BitbucketUser = strings.TrimPrefix(userConfig.BitbucketUser, "@")
userConfig.AzureDevopsUser = strings.TrimPrefix(userConfig.AzureDevopsUser, "@")
Expand All @@ -1038,6 +1087,9 @@ func (s *ServerCmd) securityWarnings(userConfig *server.UserConfig) {
if userConfig.GithubUser != "" && userConfig.GithubWebhookSecret == "" && !s.SilenceOutput {
s.Logger.Warn("no GitHub webhook secret set. This could allow attackers to spoof requests from GitHub")
}
if userConfig.GiteaUser != "" && userConfig.GiteaWebhookSecret == "" && !s.SilenceOutput {
s.Logger.Warn("no Gitea webhook secret set. This could allow attackers to spoof requests from Gitea")
}
if userConfig.GitlabUser != "" && userConfig.GitlabWebhookSecret == "" && !s.SilenceOutput {
s.Logger.Warn("no GitLab webhook secret set. This could allow attackers to spoof requests from GitLab")
}
Expand Down
104 changes: 103 additions & 1 deletion cmd/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,11 @@ var testFlags = map[string]interface{}{
GHAppSlugFlag: "atlantis",
GHOrganizationFlag: "",
GHWebhookSecretFlag: "secret",
GiteaBaseURLFlag: "http://localhost",
GiteaTokenFlag: "gitea-token",
GiteaUserFlag: "gitea-user",
GiteaWebhookSecretFlag: "gitea-secret",
GiteaPageSizeFlag: 30,
GitlabHostnameFlag: "gitlab-hostname",
GitlabTokenFlag: "gitlab-token",
GitlabUserFlag: "gitlab-user",
Expand Down Expand Up @@ -156,6 +161,7 @@ func TestExecute_Defaults(t *testing.T) {
c := setup(map[string]interface{}{
GHUserFlag: "user",
GHTokenFlag: "token",
GiteaBaseURLFlag: "http://localhost",
RepoAllowlistFlag: "*",
}, t)
err := c.Execute()
Expand All @@ -174,6 +180,7 @@ func TestExecute_Defaults(t *testing.T) {
strExceptions := map[string]string{
GHUserFlag: "user",
GHTokenFlag: "token",
GiteaBaseURLFlag: "http://localhost",
DataDirFlag: dataDir,
MarkdownTemplateOverridesDirFlag: markdownTemplateOverridesDir,
AtlantisURLFlag: "http://" + hostname + ":4141",
Expand Down Expand Up @@ -422,7 +429,7 @@ func TestExecute_ValidateSSLConfig(t *testing.T) {
}

func TestExecute_ValidateVCSConfig(t *testing.T) {
expErr := "--gh-user/--gh-token or --gh-app-id/--gh-app-key-file or --gh-app-id/--gh-app-key or --gitlab-user/--gitlab-token or --bitbucket-user/--bitbucket-token or --azuredevops-user/--azuredevops-token must be set"
expErr := "--gh-user/--gh-token or --gh-app-id/--gh-app-key-file or --gh-app-id/--gh-app-key or --gitea-user/--gitea-token or --gitlab-user/--gitlab-token or --bitbucket-user/--bitbucket-token or --azuredevops-user/--azuredevops-token must be set"
cases := []struct {
description string
flags map[string]interface{}
Expand All @@ -440,6 +447,13 @@ func TestExecute_ValidateVCSConfig(t *testing.T) {
},
true,
},
{
"just gitea token set",
map[string]interface{}{
GiteaTokenFlag: "token",
},
true,
},
{
"just gitlab token set",
map[string]interface{}{
Expand Down Expand Up @@ -468,6 +482,13 @@ func TestExecute_ValidateVCSConfig(t *testing.T) {
},
true,
},
{
"just gitea user set",
map[string]interface{}{
GiteaUserFlag: "user",
},
true,
},
{
"just github app set",
map[string]interface{}{
Expand Down Expand Up @@ -534,6 +555,22 @@ func TestExecute_ValidateVCSConfig(t *testing.T) {
},
true,
},
{
"github user and gitea token set",
map[string]interface{}{
GHUserFlag: "user",
GiteaTokenFlag: "token",
},
true,
},
{
"gitea user and github token set",
map[string]interface{}{
GiteaUserFlag: "user",
GHTokenFlag: "token",
},
true,
},
{
"github user and github token set and should be successful",
map[string]interface{}{
Expand All @@ -542,6 +579,14 @@ func TestExecute_ValidateVCSConfig(t *testing.T) {
},
false,
},
{
"gitea user and gitea token set and should be successful",
map[string]interface{}{
GiteaUserFlag: "user",
GiteaTokenFlag: "token",
},
false,
},
{
"github app and key file set and should be successful",
map[string]interface{}{
Expand Down Expand Up @@ -587,6 +632,8 @@ func TestExecute_ValidateVCSConfig(t *testing.T) {
map[string]interface{}{
GHUserFlag: "user",
GHTokenFlag: "token",
GiteaUserFlag: "user",
GiteaTokenFlag: "token",
GitlabUserFlag: "user",
GitlabTokenFlag: "token",
BitbucketUserFlag: "user",
Expand Down Expand Up @@ -699,6 +746,19 @@ func TestExecute_GithubApp(t *testing.T) {
Equals(t, int64(1), passedConfig.GithubAppID)
}

func TestExecute_GiteaUser(t *testing.T) {
t.Log("Should remove the @ from the gitea username if it's passed.")
c := setup(map[string]interface{}{
GiteaUserFlag: "@user",
GiteaTokenFlag: "token",
RepoAllowlistFlag: "*",
}, t)
err := c.Execute()
Ok(t, err)

Equals(t, "user", passedConfig.GiteaUser)
}

func TestExecute_GitlabUser(t *testing.T) {
t.Log("Should remove the @ from the gitlab username if it's passed.")
c := setup(map[string]interface{}{
Expand Down Expand Up @@ -934,3 +994,45 @@ func configVal(t *testing.T, u server.UserConfig, tag string) interface{} {
t.Fatalf("no field with tag %q found", tag)
return nil
}

// Gitea base URL must have a scheme.
func TestExecute_GiteaBaseURLScheme(t *testing.T) {
c := setup(map[string]interface{}{
GiteaUserFlag: "user",
GiteaTokenFlag: "token",
RepoAllowlistFlag: "*",
GiteaBaseURLFlag: "mydomain.com",
}, t)
ErrEquals(t, "--gitea-base-url must have http:// or https://, got \"mydomain.com\"", c.Execute())

c = setup(map[string]interface{}{
GiteaUserFlag: "user",
GiteaTokenFlag: "token",
RepoAllowlistFlag: "*",
GiteaBaseURLFlag: "://mydomain.com",
}, t)
ErrEquals(t, "error parsing --gitea-webhook-secret flag value \"://mydomain.com\": parse \"://mydomain.com\": missing protocol scheme", c.Execute())
}

func TestExecute_GiteaWithWebhookSecret(t *testing.T) {
c := setup(map[string]interface{}{
GiteaUserFlag: "user",
GiteaTokenFlag: "token",
RepoAllowlistFlag: "*",
GiteaWebhookSecretFlag: "my secret",
}, t)
err := c.Execute()
Ok(t, err)
}

// Port should be retained on base url.
func TestExecute_GiteaBaseURLPort(t *testing.T) {
c := setup(map[string]interface{}{
GiteaUserFlag: "user",
GiteaTokenFlag: "token",
RepoAllowlistFlag: "*",
GiteaBaseURLFlag: "http://mydomain.com:7990",
}, t)
Ok(t, c.Execute())
Equals(t, "http://mydomain.com:7990", passedConfig.GiteaBaseURL)
}
5 changes: 4 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/runatlantis/atlantis
go 1.22.1

require (
code.gitea.io/sdk/gitea v0.17.1
github.com/Masterminds/sprig/v3 v3.2.3
github.com/alicebob/miniredis/v2 v2.32.1
github.com/bradleyfalzon/ghinstallation/v2 v2.9.0
Expand Down Expand Up @@ -77,10 +78,12 @@ require (
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/davidmz/go-pageant v1.0.2 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/fatih/color v1.15.0 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/go-fed/httpsig v1.1.0 // indirect
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/go-cmp v0.6.0 // indirect
Expand All @@ -97,7 +100,7 @@ require (
github.com/kr/text v0.2.0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
Expand Down
Loading
Loading