[BRANDING] parse FORGEJO__* in the container environment

Add the FORGEJO__ prefix as equivalent to GITEA__ when interpreted by
environment-to-ini. It is used when running the Forgejo container like
so:

  docker run --name forgejo -e FORGEJO__security__INSTALL_LOCK=true \
             -d codeberg.org/forgejo/forgejo:1.19

(cherry picked from commit 6cd61e2ab7)
(cherry picked from commit 62cae8cc6a)
(cherry picked from commit aee1afc509)
(cherry picked from commit 6ba563cd9b)
(cherry picked from commit 6429b20f4a)
(cherry picked from commit dd545aa077)
(cherry picked from commit 63a00e573e)
(cherry picked from commit 8e35a50b91)
(cherry picked from commit 26e8fb6cd9)
(cherry picked from commit 56bbf644be)
(cherry picked from commit 4d0a8c8640)
(cherry picked from commit b58f775fa2)
(cherry picked from commit f4b6fa7a93)
(cherry picked from commit 4eca363082)
(cherry picked from commit e2e7a72f80)
This commit is contained in:
Earl Warren 2023-01-12 22:56:56 +01:00
parent 2e0f6b5de8
commit 00ce992957
No known key found for this signature in database
GPG key ID: 0579CB2928A78A00
5 changed files with 74 additions and 24 deletions

View file

@ -75,6 +75,14 @@ pipeline:
commands:
- ./build/test-env-prepare.sh
environment-to-ini:
image: *golang_image
environment:
GOPROXY_OVERRIDE: *goproxy_override
commands:
- *goproxy_setup
- go test contrib/environment-to-ini/environment-to-ini.go contrib/environment-to-ini/environment-to-ini_test.go
build:
image: *test_image
environment:

View file

@ -5,6 +5,7 @@ package main
import (
"os"
"regexp"
"strings"
"code.gitea.io/gitea/modules/log"
@ -14,21 +15,21 @@ import (
)
// EnvironmentPrefix environment variables prefixed with this represent ini values to write
const EnvironmentPrefix = "GITEA"
const EnvironmentPrefix = "^(FORGEJO|GITEA)"
func main() {
app := cli.NewApp()
app.Name = "environment-to-ini"
app.Usage = "Use provided environment to update configuration ini"
app.Description = `As a helper to allow docker users to update the gitea configuration
app.Description = `As a helper to allow docker users to update the Forgejo configuration
through the environment, this command allows environment variables to
be mapped to values in the ini.
Environment variables of the form "GITEA__SECTION_NAME__KEY_NAME"
Environment variables of the form "FORGEJO__SECTION_NAME__KEY_NAME"
will be mapped to the ini section "[section_name]" and the key
"KEY_NAME" with the value as provided.
Environment variables of the form "GITEA__SECTION_NAME__KEY_NAME__FILE"
Environment variables of the form "FORGEJO__SECTION_NAME__KEY_NAME__FILE"
will be mapped to the ini section "[section_name]" and the key
"KEY_NAME" with the value loaded from the specified file.
@ -46,8 +47,8 @@ func main() {
...
"""
You would set the environment variables: "GITEA__LOG_0x2E_CONSOLE__COLORIZE=false"
and "GITEA__LOG_0x2E_CONSOLE__STDERR=false". Other examples can be found
You would set the environment variables: "FORGEJO__LOG_0x2E_CONSOLE__COLORIZE=false"
and "FORGEJO__LOG_0x2E_CONSOLE__STDERR=false". Other examples can be found
on the configuration cheat sheet.`
app.Flags = []cli.Flag{
cli.StringFlag{
@ -63,7 +64,7 @@ func main() {
cli.StringFlag{
Name: "work-path, w",
Value: setting.AppWorkPath,
Usage: "Set the gitea working path",
Usage: "Set the forgejo working path",
},
cli.StringFlag{
Name: "out, o",
@ -89,6 +90,19 @@ func main() {
}
}
func splitEnvironmentVariable(prefixRegexp *regexp.Regexp, kv string) (string, string) {
idx := strings.IndexByte(kv, '=')
if idx < 0 {
return "", ""
}
k := kv[:idx]
loc := prefixRegexp.FindStringIndex(k)
if loc == nil {
return "", ""
}
return k[loc[1]:], kv[idx+1:]
}
func runEnvironmentToIni(c *cli.Context) error {
providedCustom := c.String("custom-path")
providedConf := c.String("config")
@ -119,17 +133,15 @@ func runEnvironmentToIni(c *cli.Context) error {
// clear Gitea's specific environment variables if requested
if c.Bool("clear") {
prefixRegexp := regexp.MustCompile(prefixGitea)
for _, kv := range os.Environ() {
idx := strings.IndexByte(kv, '=')
if idx < 0 {
eKey, _ := splitEnvironmentVariable(prefixRegexp, kv)
if eKey == "" {
continue
}
eKey := kv[:idx]
if strings.HasPrefix(eKey, prefixGitea) {
_ = os.Unsetenv(eKey)
}
}
}
return nil
}

View file

@ -0,0 +1,21 @@
// Copyright 2023 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package main
import (
"regexp"
"testing"
"github.com/stretchr/testify/assert"
)
func Test_splitEnvironmentVariable(t *testing.T) {
prefixRegexp := regexp.MustCompile(EnvironmentPrefix + "__")
k, v := splitEnvironmentVariable(prefixRegexp, "FORGEJO__KEY=VALUE")
assert.Equal(t, k, "KEY")
assert.Equal(t, v, "VALUE")
k, v = splitEnvironmentVariable(prefixRegexp, "nothing=interesting")
assert.Equal(t, k, "")
assert.Equal(t, v, "")
}

View file

@ -75,19 +75,21 @@ func decodeEnvSectionKey(encoded string) (ok bool, section, key string) {
// decodeEnvironmentKey decode the environment key to section and key
// The environment key is in the form of GITEA__SECTION__KEY or GITEA__SECTION__KEY__FILE
func decodeEnvironmentKey(prefixGitea, suffixFile, envKey string) (ok bool, section, key string, useFileValue bool) {
if !strings.HasPrefix(envKey, prefixGitea) {
return false, "", "", false
}
func decodeEnvironmentKey(prefixRegexp *regexp.Regexp, suffixFile, envKey string) (ok bool, section, key string, useFileValue bool) {
if strings.HasSuffix(envKey, suffixFile) {
useFileValue = true
envKey = envKey[:len(envKey)-len(suffixFile)]
}
ok, section, key = decodeEnvSectionKey(envKey[len(prefixGitea):])
loc := prefixRegexp.FindStringIndex(envKey)
if loc == nil {
return false, "", "", false
}
ok, section, key = decodeEnvSectionKey(envKey[loc[1]:])
return ok, section, key, useFileValue
}
func EnvironmentToConfig(cfg ConfigProvider, prefixGitea, suffixFile string, envs []string) (changed bool) {
prefixRegexp := regexp.MustCompile(prefixGitea)
for _, kv := range envs {
idx := strings.IndexByte(kv, '=')
if idx < 0 {
@ -97,7 +99,7 @@ func EnvironmentToConfig(cfg ConfigProvider, prefixGitea, suffixFile string, env
// parse the environment variable to config section name and key name
envKey := kv[:idx]
envValue := kv[idx+1:]
ok, sectionName, keyName, useFileValue := decodeEnvironmentKey(prefixGitea, suffixFile, envKey)
ok, sectionName, keyName, useFileValue := decodeEnvironmentKey(prefixRegexp, suffixFile, envKey)
if !ok {
continue
}

View file

@ -5,6 +5,7 @@ package setting
import (
"os"
"regexp"
"testing"
"github.com/stretchr/testify/assert"
@ -33,7 +34,7 @@ func TestDecodeEnvSectionKey(t *testing.T) {
}
func TestDecodeEnvironmentKey(t *testing.T) {
prefix := "GITEA__"
prefix := regexp.MustCompile("^(FORGEJO|GITEA)__")
suffix := "__FILE"
ok, section, key, file := decodeEnvironmentKey(prefix, suffix, "SEC__KEY")
@ -54,6 +55,12 @@ func TestDecodeEnvironmentKey(t *testing.T) {
assert.Equal(t, "KEY", key)
assert.False(t, file)
ok, section, key, file = decodeEnvironmentKey(prefix, suffix, "FORGEJO__SEC__KEY")
assert.True(t, ok)
assert.Equal(t, "sec", section)
assert.Equal(t, "KEY", key)
assert.False(t, file)
// with "__FILE" suffix, it doesn't support to write "[sec].FILE" to config (no such key FILE is used in Gitea)
// but it could be fixed in the future by adding a new suffix like "__VALUE" (no such key VALUE is used in Gitea either)
ok, section, key, file = decodeEnvironmentKey(prefix, suffix, "GITEA__SEC__FILE")
@ -72,7 +79,7 @@ func TestDecodeEnvironmentKey(t *testing.T) {
func TestEnvironmentToConfig(t *testing.T) {
cfg, _ := NewConfigProviderFromData("")
changed := EnvironmentToConfig(cfg, "GITEA__", "__FILE", nil)
changed := EnvironmentToConfig(cfg, "^(FORGEJO|GITEA)__", "__FILE", nil)
assert.False(t, changed)
cfg, err := NewConfigProviderFromData(`
@ -81,16 +88,16 @@ key = old
`)
assert.NoError(t, err)
changed = EnvironmentToConfig(cfg, "GITEA__", "__FILE", []string{"GITEA__sec__key=new"})
changed = EnvironmentToConfig(cfg, "^(FORGEJO|GITEA)__", "__FILE", []string{"GITEA__sec__key=new"})
assert.True(t, changed)
assert.Equal(t, "new", cfg.Section("sec").Key("key").String())
changed = EnvironmentToConfig(cfg, "GITEA__", "__FILE", []string{"GITEA__sec__key=new"})
changed = EnvironmentToConfig(cfg, "^(FORGEJO|GITEA)__", "__FILE", []string{"GITEA__sec__key=new"})
assert.False(t, changed)
tmpFile := t.TempDir() + "/the-file"
_ = os.WriteFile(tmpFile, []byte("value-from-file"), 0o644)
changed = EnvironmentToConfig(cfg, "GITEA__", "__FILE", []string{"GITEA__sec__key__FILE=" + tmpFile})
changed = EnvironmentToConfig(cfg, "^(FORGEJO|GITEA)__", "__FILE", []string{"GITEA__sec__key__FILE=" + tmpFile})
assert.True(t, changed)
assert.Equal(t, "value-from-file", cfg.Section("sec").Key("key").String())
}