forked from gitea/gitea
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)
This commit is contained in:
parent
0407a402bb
commit
d0f24ff4ca
|
@ -31,8 +31,8 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *ActionVariable) Validate() error {
|
func (v *ActionVariable) Validate() error {
|
||||||
if v.OwnerID == 0 && v.RepoID == 0 {
|
if v.OwnerID != 0 && v.RepoID != 0 {
|
||||||
return errors.New("the variable is not bound to any scope")
|
return errors.New("a variable should not be bound to an owner and a repository at the same time")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -58,12 +58,8 @@ type FindVariablesOpts struct {
|
||||||
|
|
||||||
func (opts FindVariablesOpts) ToConds() builder.Cond {
|
func (opts FindVariablesOpts) ToConds() builder.Cond {
|
||||||
cond := builder.NewCond()
|
cond := builder.NewCond()
|
||||||
if opts.OwnerID > 0 {
|
cond = cond.And(builder.Eq{"owner_id": opts.OwnerID})
|
||||||
cond = cond.And(builder.Eq{"owner_id": opts.OwnerID})
|
cond = cond.And(builder.Eq{"repo_id": opts.RepoID})
|
||||||
}
|
|
||||||
if opts.RepoID > 0 {
|
|
||||||
cond = cond.And(builder.Eq{"repo_id": opts.RepoID})
|
|
||||||
}
|
|
||||||
return cond
|
return cond
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
func getVariablesOfTask(ctx context.Context, task *actions_model.ActionTask) map[string]string {
|
||||||
variables := 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
|
// Org / User level
|
||||||
ownerVariables, err := db.Find[actions_model.ActionVariable](ctx, actions_model.FindVariablesOpts{OwnerID: task.Job.Run.Repo.OwnerID})
|
ownerVariables, err := db.Find[actions_model.ActionVariable](ctx, actions_model.FindVariablesOpts{OwnerID: task.Job.Run.Repo.OwnerID})
|
||||||
if err != nil {
|
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)
|
log.Error("find variables of repo: %d, error: %v", task.Job.Run.RepoID, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Level precedence: Repo > Org / User
|
// Level precedence: Repo > Org / User > Global
|
||||||
for _, v := range append(ownerVariables, repoVariables...) {
|
for _, v := range append(globalVariables, append(ownerVariables, repoVariables...)...) {
|
||||||
variables[v.Name] = v.Data
|
variables[v.Name] = v.Data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,9 +15,10 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
tplRepoVariables base.TplName = "repo/settings/actions"
|
tplRepoVariables base.TplName = "repo/settings/actions"
|
||||||
tplOrgVariables base.TplName = "org/settings/actions"
|
tplOrgVariables base.TplName = "org/settings/actions"
|
||||||
tplUserVariables base.TplName = "user/settings/actions"
|
tplUserVariables base.TplName = "user/settings/actions"
|
||||||
|
tplAdminVariables base.TplName = "admin/actions"
|
||||||
)
|
)
|
||||||
|
|
||||||
type variablesCtx struct {
|
type variablesCtx struct {
|
||||||
|
@ -26,6 +27,7 @@ type variablesCtx struct {
|
||||||
IsRepo bool
|
IsRepo bool
|
||||||
IsOrg bool
|
IsOrg bool
|
||||||
IsUser bool
|
IsUser bool
|
||||||
|
IsGlobal bool
|
||||||
VariablesTemplate base.TplName
|
VariablesTemplate base.TplName
|
||||||
RedirectLink string
|
RedirectLink string
|
||||||
}
|
}
|
||||||
|
@ -33,6 +35,7 @@ type variablesCtx struct {
|
||||||
func getVariablesCtx(ctx *context.Context) (*variablesCtx, error) {
|
func getVariablesCtx(ctx *context.Context) (*variablesCtx, error) {
|
||||||
if ctx.Data["PageIsRepoSettings"] == true {
|
if ctx.Data["PageIsRepoSettings"] == true {
|
||||||
return &variablesCtx{
|
return &variablesCtx{
|
||||||
|
OwnerID: 0,
|
||||||
RepoID: ctx.Repo.Repository.ID,
|
RepoID: ctx.Repo.Repository.ID,
|
||||||
IsRepo: true,
|
IsRepo: true,
|
||||||
VariablesTemplate: tplRepoVariables,
|
VariablesTemplate: tplRepoVariables,
|
||||||
|
@ -48,6 +51,7 @@ func getVariablesCtx(ctx *context.Context) (*variablesCtx, error) {
|
||||||
}
|
}
|
||||||
return &variablesCtx{
|
return &variablesCtx{
|
||||||
OwnerID: ctx.ContextUser.ID,
|
OwnerID: ctx.ContextUser.ID,
|
||||||
|
RepoID: 0,
|
||||||
IsOrg: true,
|
IsOrg: true,
|
||||||
VariablesTemplate: tplOrgVariables,
|
VariablesTemplate: tplOrgVariables,
|
||||||
RedirectLink: ctx.Org.OrgLink + "/settings/actions/variables",
|
RedirectLink: ctx.Org.OrgLink + "/settings/actions/variables",
|
||||||
|
@ -57,12 +61,23 @@ func getVariablesCtx(ctx *context.Context) (*variablesCtx, error) {
|
||||||
if ctx.Data["PageIsUserSettings"] == true {
|
if ctx.Data["PageIsUserSettings"] == true {
|
||||||
return &variablesCtx{
|
return &variablesCtx{
|
||||||
OwnerID: ctx.Doer.ID,
|
OwnerID: ctx.Doer.ID,
|
||||||
|
RepoID: 0,
|
||||||
IsUser: true,
|
IsUser: true,
|
||||||
VariablesTemplate: tplUserVariables,
|
VariablesTemplate: tplUserVariables,
|
||||||
RedirectLink: setting.AppSubURL + "/user/settings/actions/variables",
|
RedirectLink: setting.AppSubURL + "/user/settings/actions/variables",
|
||||||
}, nil
|
}, 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")
|
return nil, errors.New("unable to set Variables context")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -417,7 +417,7 @@ func registerRoutes(m *web.Route) {
|
||||||
m.Post("/packagist/{id}", web.Bind(forms.NewPackagistHookForm{}), repo_setting.PackagistHooksEditPost)
|
m.Post("/packagist/{id}", web.Bind(forms.NewPackagistHookForm{}), repo_setting.PackagistHooksEditPost)
|
||||||
}
|
}
|
||||||
|
|
||||||
addSettingVariablesRoutes := func() {
|
addSettingsVariablesRoutes := func() {
|
||||||
m.Group("/variables", func() {
|
m.Group("/variables", func() {
|
||||||
m.Get("", repo_setting.Variables)
|
m.Get("", repo_setting.Variables)
|
||||||
m.Post("/new", web.Bind(forms.EditVariableForm{}), repo_setting.VariableCreate)
|
m.Post("/new", web.Bind(forms.EditVariableForm{}), repo_setting.VariableCreate)
|
||||||
|
@ -618,7 +618,7 @@ func registerRoutes(m *web.Route) {
|
||||||
m.Get("", user_setting.RedirectToDefaultSetting)
|
m.Get("", user_setting.RedirectToDefaultSetting)
|
||||||
addSettingsRunnersRoutes()
|
addSettingsRunnersRoutes()
|
||||||
addSettingsSecretsRoutes()
|
addSettingsSecretsRoutes()
|
||||||
addSettingVariablesRoutes()
|
addSettingsVariablesRoutes()
|
||||||
}, actions.MustEnableActions)
|
}, actions.MustEnableActions)
|
||||||
|
|
||||||
m.Get("/organization", user_setting.Organization)
|
m.Get("/organization", user_setting.Organization)
|
||||||
|
@ -763,6 +763,7 @@ func registerRoutes(m *web.Route) {
|
||||||
m.Group("/actions", func() {
|
m.Group("/actions", func() {
|
||||||
m.Get("", admin.RedirectToDefaultSetting)
|
m.Get("", admin.RedirectToDefaultSetting)
|
||||||
addSettingsRunnersRoutes()
|
addSettingsRunnersRoutes()
|
||||||
|
addSettingsVariablesRoutes()
|
||||||
})
|
})
|
||||||
}, adminReq, ctxDataSet("EnableOAuth2", setting.OAuth2.Enable, "EnablePackages", setting.Packages.Enabled))
|
}, adminReq, ctxDataSet("EnableOAuth2", setting.OAuth2.Enable, "EnablePackages", setting.Packages.Enabled))
|
||||||
// ***** END: Admin *****
|
// ***** END: Admin *****
|
||||||
|
@ -905,7 +906,7 @@ func registerRoutes(m *web.Route) {
|
||||||
m.Get("", org_setting.RedirectToDefaultSetting)
|
m.Get("", org_setting.RedirectToDefaultSetting)
|
||||||
addSettingsRunnersRoutes()
|
addSettingsRunnersRoutes()
|
||||||
addSettingsSecretsRoutes()
|
addSettingsSecretsRoutes()
|
||||||
addSettingVariablesRoutes()
|
addSettingsVariablesRoutes()
|
||||||
}, actions.MustEnableActions)
|
}, actions.MustEnableActions)
|
||||||
|
|
||||||
m.Methods("GET,POST", "/delete", org.SettingsDelete)
|
m.Methods("GET,POST", "/delete", org.SettingsDelete)
|
||||||
|
@ -1084,7 +1085,7 @@ func registerRoutes(m *web.Route) {
|
||||||
m.Get("", repo_setting.RedirectToDefaultSetting)
|
m.Get("", repo_setting.RedirectToDefaultSetting)
|
||||||
addSettingsRunnersRoutes()
|
addSettingsRunnersRoutes()
|
||||||
addSettingsSecretsRoutes()
|
addSettingsSecretsRoutes()
|
||||||
addSettingVariablesRoutes()
|
addSettingsVariablesRoutes()
|
||||||
}, actions.MustEnableActions)
|
}, actions.MustEnableActions)
|
||||||
// the follow handler must be under "settings", otherwise this incomplete repo can't be accessed
|
// the follow handler must be under "settings", otherwise this incomplete repo can't be accessed
|
||||||
m.Group("/migrate", func() {
|
m.Group("/migrate", func() {
|
||||||
|
|
|
@ -3,5 +3,8 @@
|
||||||
{{if eq .PageType "runners"}}
|
{{if eq .PageType "runners"}}
|
||||||
{{template "shared/actions/runner_list" .}}
|
{{template "shared/actions/runner_list" .}}
|
||||||
{{end}}
|
{{end}}
|
||||||
|
{{if eq .PageType "variables"}}
|
||||||
|
{{template "shared/variables/variable_list" .}}
|
||||||
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
{{template "admin/layout_footer" .}}
|
{{template "admin/layout_footer" .}}
|
||||||
|
|
|
@ -60,12 +60,15 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if .EnableActions}}
|
{{if .EnableActions}}
|
||||||
<details class="item toggleable-item" {{if .PageIsSharedSettingsRunners}}open{{end}}>
|
<details class="item toggleable-item" {{if or .PageIsSharedSettingsRunners .PageIsSharedSettingsVariables}}open{{end}}>
|
||||||
<summary>{{ctx.Locale.Tr "actions.actions"}}</summary>
|
<summary>{{ctx.Locale.Tr "actions.actions"}}</summary>
|
||||||
<div class="menu">
|
<div class="menu">
|
||||||
<a class="{{if .PageIsSharedSettingsRunners}}active {{end}}item" href="{{AppSubUrl}}/admin/actions/runners">
|
<a class="{{if .PageIsSharedSettingsRunners}}active {{end}}item" href="{{AppSubUrl}}/admin/actions/runners">
|
||||||
{{ctx.Locale.Tr "actions.runners"}}
|
{{ctx.Locale.Tr "actions.runners"}}
|
||||||
</a>
|
</a>
|
||||||
|
<a class="{{if .PageIsSharedSettingsVariables}}active {{end}}item" href="{{AppSubUrl}}/admin/actions/variables">
|
||||||
|
{{ctx.Locale.Tr "actions.variables"}}
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</details>
|
</details>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
Loading…
Reference in New Issue