From d0f24ff4cad05c1145afeca791e7d02fe146d46a Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Gomond Date: Mon, 25 Dec 2023 08:28:59 +0100 Subject: [PATCH] Added instance-level variables (#28115) This PR adds instance-level variables, and so closes #27726 ![gitea_instance_variables_1](https://github.com/go-gitea/gitea/assets/8344487/ad409cd4-ce36-4c84-a764-34451b0fb63a) ![gitea_instance_variables_2](https://github.com/go-gitea/gitea/assets/8344487/426f0965-dec6-4560-948c-067cdeddd720) ![gitea_instance_variables_3](https://github.com/go-gitea/gitea/assets/8344487/cf1d7776-4938-4825-922e-cbbbf28a5f33) --- models/actions/variable.go | 12 ++++-------- routers/api/actions/runner/utils.go | 10 ++++++++-- routers/web/repo/setting/variables.go | 21 ++++++++++++++++++--- routers/web/web.go | 9 +++++---- templates/admin/actions.tmpl | 3 +++ templates/admin/navbar.tmpl | 5 ++++- 6 files changed, 42 insertions(+), 18 deletions(-) diff --git a/models/actions/variable.go b/models/actions/variable.go index 030b7bae9..12717e0ae 100644 --- a/models/actions/variable.go +++ b/models/actions/variable.go @@ -31,8 +31,8 @@ func init() { } func (v *ActionVariable) Validate() error { - if v.OwnerID == 0 && v.RepoID == 0 { - return errors.New("the variable is not bound to any scope") + if v.OwnerID != 0 && v.RepoID != 0 { + return errors.New("a variable should not be bound to an owner and a repository at the same time") } return nil } @@ -58,12 +58,8 @@ type FindVariablesOpts struct { func (opts FindVariablesOpts) ToConds() builder.Cond { cond := builder.NewCond() - if opts.OwnerID > 0 { - cond = cond.And(builder.Eq{"owner_id": opts.OwnerID}) - } - if opts.RepoID > 0 { - cond = cond.And(builder.Eq{"repo_id": opts.RepoID}) - } + cond = cond.And(builder.Eq{"owner_id": opts.OwnerID}) + cond = cond.And(builder.Eq{"repo_id": opts.RepoID}) return cond } diff --git a/routers/api/actions/runner/utils.go b/routers/api/actions/runner/utils.go index bf913f2c0..2555f86c8 100644 --- a/routers/api/actions/runner/utils.go +++ b/routers/api/actions/runner/utils.go @@ -94,6 +94,12 @@ func getSecretsOfTask(ctx context.Context, task *actions_model.ActionTask) map[s func getVariablesOfTask(ctx context.Context, task *actions_model.ActionTask) map[string]string { variables := map[string]string{} + // Global + globalVariables, err := db.Find[actions_model.ActionVariable](ctx, actions_model.FindVariablesOpts{}) + if err != nil { + log.Error("find global variables: %v", err) + } + // Org / User level ownerVariables, err := db.Find[actions_model.ActionVariable](ctx, actions_model.FindVariablesOpts{OwnerID: task.Job.Run.Repo.OwnerID}) if err != nil { @@ -106,8 +112,8 @@ func getVariablesOfTask(ctx context.Context, task *actions_model.ActionTask) map log.Error("find variables of repo: %d, error: %v", task.Job.Run.RepoID, err) } - // Level precedence: Repo > Org / User - for _, v := range append(ownerVariables, repoVariables...) { + // Level precedence: Repo > Org / User > Global + for _, v := range append(globalVariables, append(ownerVariables, repoVariables...)...) { variables[v.Name] = v.Data } diff --git a/routers/web/repo/setting/variables.go b/routers/web/repo/setting/variables.go index a697a5d8d..428aa0bd5 100644 --- a/routers/web/repo/setting/variables.go +++ b/routers/web/repo/setting/variables.go @@ -15,9 +15,10 @@ import ( ) const ( - tplRepoVariables base.TplName = "repo/settings/actions" - tplOrgVariables base.TplName = "org/settings/actions" - tplUserVariables base.TplName = "user/settings/actions" + tplRepoVariables base.TplName = "repo/settings/actions" + tplOrgVariables base.TplName = "org/settings/actions" + tplUserVariables base.TplName = "user/settings/actions" + tplAdminVariables base.TplName = "admin/actions" ) type variablesCtx struct { @@ -26,6 +27,7 @@ type variablesCtx struct { IsRepo bool IsOrg bool IsUser bool + IsGlobal bool VariablesTemplate base.TplName RedirectLink string } @@ -33,6 +35,7 @@ type variablesCtx struct { func getVariablesCtx(ctx *context.Context) (*variablesCtx, error) { if ctx.Data["PageIsRepoSettings"] == true { return &variablesCtx{ + OwnerID: 0, RepoID: ctx.Repo.Repository.ID, IsRepo: true, VariablesTemplate: tplRepoVariables, @@ -48,6 +51,7 @@ func getVariablesCtx(ctx *context.Context) (*variablesCtx, error) { } return &variablesCtx{ OwnerID: ctx.ContextUser.ID, + RepoID: 0, IsOrg: true, VariablesTemplate: tplOrgVariables, RedirectLink: ctx.Org.OrgLink + "/settings/actions/variables", @@ -57,12 +61,23 @@ func getVariablesCtx(ctx *context.Context) (*variablesCtx, error) { if ctx.Data["PageIsUserSettings"] == true { return &variablesCtx{ OwnerID: ctx.Doer.ID, + RepoID: 0, IsUser: true, VariablesTemplate: tplUserVariables, RedirectLink: setting.AppSubURL + "/user/settings/actions/variables", }, nil } + if ctx.Data["PageIsAdmin"] == true { + return &variablesCtx{ + OwnerID: 0, + RepoID: 0, + IsGlobal: true, + VariablesTemplate: tplAdminVariables, + RedirectLink: setting.AppSubURL + "/admin/actions/variables", + }, nil + } + return nil, errors.New("unable to set Variables context") } diff --git a/routers/web/web.go b/routers/web/web.go index 359b608c7..02fb11b1f 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -417,7 +417,7 @@ func registerRoutes(m *web.Route) { m.Post("/packagist/{id}", web.Bind(forms.NewPackagistHookForm{}), repo_setting.PackagistHooksEditPost) } - addSettingVariablesRoutes := func() { + addSettingsVariablesRoutes := func() { m.Group("/variables", func() { m.Get("", repo_setting.Variables) m.Post("/new", web.Bind(forms.EditVariableForm{}), repo_setting.VariableCreate) @@ -618,7 +618,7 @@ func registerRoutes(m *web.Route) { m.Get("", user_setting.RedirectToDefaultSetting) addSettingsRunnersRoutes() addSettingsSecretsRoutes() - addSettingVariablesRoutes() + addSettingsVariablesRoutes() }, actions.MustEnableActions) m.Get("/organization", user_setting.Organization) @@ -763,6 +763,7 @@ func registerRoutes(m *web.Route) { m.Group("/actions", func() { m.Get("", admin.RedirectToDefaultSetting) addSettingsRunnersRoutes() + addSettingsVariablesRoutes() }) }, adminReq, ctxDataSet("EnableOAuth2", setting.OAuth2.Enable, "EnablePackages", setting.Packages.Enabled)) // ***** END: Admin ***** @@ -905,7 +906,7 @@ func registerRoutes(m *web.Route) { m.Get("", org_setting.RedirectToDefaultSetting) addSettingsRunnersRoutes() addSettingsSecretsRoutes() - addSettingVariablesRoutes() + addSettingsVariablesRoutes() }, actions.MustEnableActions) m.Methods("GET,POST", "/delete", org.SettingsDelete) @@ -1084,7 +1085,7 @@ func registerRoutes(m *web.Route) { m.Get("", repo_setting.RedirectToDefaultSetting) addSettingsRunnersRoutes() addSettingsSecretsRoutes() - addSettingVariablesRoutes() + addSettingsVariablesRoutes() }, actions.MustEnableActions) // the follow handler must be under "settings", otherwise this incomplete repo can't be accessed m.Group("/migrate", func() { diff --git a/templates/admin/actions.tmpl b/templates/admin/actions.tmpl index 9640e0fd1..597863d73 100644 --- a/templates/admin/actions.tmpl +++ b/templates/admin/actions.tmpl @@ -3,5 +3,8 @@ {{if eq .PageType "runners"}} {{template "shared/actions/runner_list" .}} {{end}} + {{if eq .PageType "variables"}} + {{template "shared/variables/variable_list" .}} + {{end}} {{template "admin/layout_footer" .}} diff --git a/templates/admin/navbar.tmpl b/templates/admin/navbar.tmpl index 8ece95239..b22db1d1f 100644 --- a/templates/admin/navbar.tmpl +++ b/templates/admin/navbar.tmpl @@ -60,12 +60,15 @@ {{end}} {{end}} {{if .EnableActions}} -
+
{{ctx.Locale.Tr "actions.actions"}}
{{end}}