Skip to content

Commit ce2491f

Browse files
authored
Merge branch 'main' into fix-refissue
2 parents c2af838 + 87d670c commit ce2491f

File tree

98 files changed

+1103
-484
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

98 files changed

+1103
-484
lines changed

Dockerfile

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,20 +26,16 @@ WORKDIR ${GOPATH}/src/code.gitea.io/gitea
2626
RUN if [ -n "${GITEA_VERSION}" ]; then git checkout "${GITEA_VERSION}"; fi \
2727
&& make clean-all build
2828

29-
# Begin env-to-ini build
30-
RUN go build contrib/environment-to-ini/environment-to-ini.go
31-
3229
# Copy local files
3330
COPY docker/root /tmp/local
3431

3532
# Set permissions
3633
RUN chmod 755 /tmp/local/usr/bin/entrypoint \
37-
/tmp/local/usr/local/bin/gitea \
34+
/tmp/local/usr/local/bin/* \
3835
/tmp/local/etc/s6/gitea/* \
3936
/tmp/local/etc/s6/openssh/* \
4037
/tmp/local/etc/s6/.s6-svscan/* \
41-
/go/src/code.gitea.io/gitea/gitea \
42-
/go/src/code.gitea.io/gitea/environment-to-ini
38+
/go/src/code.gitea.io/gitea/gitea
4339

4440
FROM docker.io/library/alpine:3.22
4541
LABEL maintainer="[email protected]"
@@ -82,4 +78,3 @@ CMD ["/usr/bin/s6-svscan", "/etc/s6"]
8278

8379
COPY --from=build-env /tmp/local /
8480
COPY --from=build-env /go/src/code.gitea.io/gitea/gitea /app/gitea/gitea
85-
COPY --from=build-env /go/src/code.gitea.io/gitea/environment-to-ini /usr/local/bin/environment-to-ini

Dockerfile.rootless

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,12 @@ WORKDIR ${GOPATH}/src/code.gitea.io/gitea
2626
RUN if [ -n "${GITEA_VERSION}" ]; then git checkout "${GITEA_VERSION}"; fi \
2727
&& make clean-all build
2828

29-
# Begin env-to-ini build
30-
RUN go build contrib/environment-to-ini/environment-to-ini.go
31-
3229
# Copy local files
3330
COPY docker/rootless /tmp/local
3431

3532
# Set permissions
36-
RUN chmod 755 /tmp/local/usr/local/bin/docker-entrypoint.sh \
37-
/tmp/local/usr/local/bin/docker-setup.sh \
38-
/tmp/local/usr/local/bin/gitea \
39-
/go/src/code.gitea.io/gitea/gitea \
40-
/go/src/code.gitea.io/gitea/environment-to-ini
33+
RUN chmod 755 /tmp/local/usr/local/bin/* \
34+
/go/src/code.gitea.io/gitea/gitea
4135

4236
FROM docker.io/library/alpine:3.22
4337
LABEL maintainer="[email protected]"
@@ -71,7 +65,6 @@ RUN chown git:git /var/lib/gitea /etc/gitea
7165

7266
COPY --from=build-env /tmp/local /
7367
COPY --from=build-env --chown=root:root /go/src/code.gitea.io/gitea/gitea /app/gitea/gitea
74-
COPY --from=build-env --chown=root:root /go/src/code.gitea.io/gitea/environment-to-ini /usr/local/bin/environment-to-ini
7568

7669
# git:git
7770
USER 1000:1000

cmd/config.go

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
// Copyright 2025 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package cmd
5+
6+
import (
7+
"context"
8+
"errors"
9+
"fmt"
10+
"os"
11+
12+
"code.gitea.io/gitea/modules/setting"
13+
14+
"github.com/urfave/cli/v3"
15+
)
16+
17+
func cmdConfig() *cli.Command {
18+
subcmdConfigEditIni := &cli.Command{
19+
Name: "edit-ini",
20+
Usage: "Load an existing INI file, apply environment variables, keep specified keys, and output to a new INI file.",
21+
Description: `
22+
Help users to edit the Gitea configuration INI file.
23+
24+
# Keep Specified Keys
25+
26+
If you need to re-create the configuration file with only a subset of keys,
27+
you can provide an INI template file for the kept keys and use the "--config-keep-keys" flag.
28+
For example, if a helm chart needs to reset the settings and only keep SECRET_KEY,
29+
it can use a template file (only keys take effect, values are ignored):
30+
31+
[security]
32+
SECRET_KEY=
33+
34+
$ ./gitea config edit-ini --config app-old.ini --config-keep-keys app-keys.ini --out app-new.ini
35+
36+
# Map Environment Variables to INI Configuration
37+
38+
Environment variables of the form "GITEA__section_name__KEY_NAME"
39+
will be mapped to the ini section "[section_name]" and the key
40+
"KEY_NAME" with the value as provided.
41+
42+
Environment variables of the form "GITEA__section_name__KEY_NAME__FILE"
43+
will be mapped to the ini section "[section_name]" and the key
44+
"KEY_NAME" with the value loaded from the specified file.
45+
46+
Environment variable keys can only contain characters "0-9A-Z_",
47+
if a section or key name contains dot ".", it needs to be escaped as _0x2E_.
48+
For example, to apply this config:
49+
50+
[git.config]
51+
foo.bar=val
52+
53+
$ export GITEA__git_0x2E_config__foo_0x2E_bar=val
54+
55+
# Put All Together
56+
57+
$ ./gitea config edit-ini --config app.ini --config-keep-keys app-keys.ini --apply-env {--in-place|--out app-new.ini}
58+
`,
59+
Flags: []cli.Flag{
60+
// "--config" flag is provided by global flags, and this flag is also used by "environment-to-ini" script wrapper
61+
// "--in-place" is also used by "environment-to-ini" script wrapper for its old behavior: always overwrite the existing config file
62+
&cli.BoolFlag{
63+
Name: "in-place",
64+
Usage: "Output to the same config file as input. This flag will be ignored if --out is set.",
65+
},
66+
&cli.StringFlag{
67+
Name: "config-keep-keys",
68+
Usage: "An INI template file containing keys for keeping. Only the keys defined in the INI template will be kept from old config. If not set, all keys will be kept.",
69+
},
70+
&cli.BoolFlag{
71+
Name: "apply-env",
72+
Usage: "Apply all GITEA__* variables from the environment to the config.",
73+
},
74+
&cli.StringFlag{
75+
Name: "out",
76+
Usage: "Destination config file to write to.",
77+
},
78+
},
79+
Action: runConfigEditIni,
80+
}
81+
82+
return &cli.Command{
83+
Name: "config",
84+
Usage: "Manage Gitea configuration",
85+
Commands: []*cli.Command{
86+
subcmdConfigEditIni,
87+
},
88+
}
89+
}
90+
91+
func runConfigEditIni(_ context.Context, c *cli.Command) error {
92+
// the config system may change the environment variables, so get a copy first, to be used later
93+
env := append([]string{}, os.Environ()...)
94+
95+
// don't use the guessed setting.CustomConf, instead, require the user to provide --config explicitly
96+
if !c.IsSet("config") {
97+
return errors.New("flag is required but not set: --config")
98+
}
99+
configFileIn := c.String("config")
100+
101+
cfgIn, err := setting.NewConfigProviderFromFile(configFileIn)
102+
if err != nil {
103+
return fmt.Errorf("failed to load config file %q: %v", configFileIn, err)
104+
}
105+
106+
// determine output config file: use "--out" flag or use "--in-place" flag to overwrite input file
107+
inPlace := c.Bool("in-place")
108+
configFileOut := c.String("out")
109+
if configFileOut == "" {
110+
if !inPlace {
111+
return errors.New("either --in-place or --out must be specified")
112+
}
113+
configFileOut = configFileIn // in-place edit
114+
}
115+
116+
needWriteOut := configFileOut != configFileIn
117+
118+
cfgOut := cfgIn
119+
configKeepKeys := c.String("config-keep-keys")
120+
if configKeepKeys != "" {
121+
needWriteOut = true
122+
cfgOut, err = setting.NewConfigProviderFromFile(configKeepKeys)
123+
if err != nil {
124+
return fmt.Errorf("failed to load config-keep-keys template file %q: %v", configKeepKeys, err)
125+
}
126+
127+
for _, secOut := range cfgOut.Sections() {
128+
for _, keyOut := range secOut.Keys() {
129+
secIn := cfgIn.Section(secOut.Name())
130+
keyIn := setting.ConfigSectionKey(secIn, keyOut.Name())
131+
if keyIn != nil {
132+
keyOut.SetValue(keyIn.String())
133+
} else {
134+
secOut.DeleteKey(keyOut.Name())
135+
}
136+
}
137+
if len(secOut.Keys()) == 0 {
138+
cfgOut.DeleteSection(secOut.Name())
139+
}
140+
}
141+
}
142+
143+
if c.Bool("apply-env") {
144+
if setting.EnvironmentToConfig(cfgOut, env) {
145+
needWriteOut = true
146+
}
147+
}
148+
149+
if needWriteOut {
150+
err = cfgOut.SaveTo(configFileOut)
151+
if err != nil {
152+
return err
153+
}
154+
}
155+
return nil
156+
}

cmd/config_test.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// Copyright 2025 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package cmd
5+
6+
import (
7+
"os"
8+
"testing"
9+
10+
"github.com/stretchr/testify/require"
11+
)
12+
13+
func TestConfigEdit(t *testing.T) {
14+
tmpDir := t.TempDir()
15+
configOld := tmpDir + "/app-old.ini"
16+
configTemplate := tmpDir + "/app-template.ini"
17+
_ = os.WriteFile(configOld, []byte(`
18+
[sec]
19+
k1=v1
20+
k2=v2
21+
`), os.ModePerm)
22+
23+
_ = os.WriteFile(configTemplate, []byte(`
24+
[sec]
25+
k1=in-template
26+
27+
[sec2]
28+
k3=v3
29+
`), os.ModePerm)
30+
31+
t.Setenv("GITEA__EnV__KeY", "val")
32+
33+
t.Run("OutputToNewWithEnv", func(t *testing.T) {
34+
configNew := tmpDir + "/app-new.ini"
35+
err := NewMainApp(AppVersion{}).Run(t.Context(), []string{
36+
"./gitea", "--config", configOld,
37+
"config", "edit-ini",
38+
"--apply-env",
39+
"--config-keep-keys", configTemplate,
40+
"--out", configNew,
41+
})
42+
require.NoError(t, err)
43+
44+
// "k1" old value is kept because its key is in the template
45+
// "k2" is removed because it isn't in the template
46+
// "k3" isn't in new config because it isn't in the old config
47+
// [env] is applied from environment variable
48+
data, _ := os.ReadFile(configNew)
49+
require.Equal(t, `[sec]
50+
k1 = v1
51+
52+
[env]
53+
KeY = val
54+
`, string(data))
55+
})
56+
57+
t.Run("OutputToExisting(environment-to-ini)", func(t *testing.T) {
58+
// the legacy "environment-to-ini" (now a wrapper script) behavior:
59+
// if no "--out", then "--in-place" must be used to overwrite the existing "--config" file
60+
err := NewMainApp(AppVersion{}).Run(t.Context(), []string{
61+
"./gitea", "config", "edit-ini",
62+
"--apply-env",
63+
"--config", configOld,
64+
})
65+
require.ErrorContains(t, err, "either --in-place or --out must be specified")
66+
67+
// simulate the "environment-to-ini" behavior with "--in-place"
68+
err = NewMainApp(AppVersion{}).Run(t.Context(), []string{
69+
"./gitea", "config", "edit-ini",
70+
"--in-place",
71+
"--apply-env",
72+
"--config", configOld,
73+
})
74+
require.NoError(t, err)
75+
76+
data, _ := os.ReadFile(configOld)
77+
require.Equal(t, `[sec]
78+
k1 = v1
79+
k2 = v2
80+
81+
[env]
82+
KeY = val
83+
`, string(data))
84+
})
85+
}

cmd/main.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ func NewMainApp(appVer AppVersion) *cli.Command {
128128

129129
// these sub-commands do not need the config file, and they do not depend on any path or environment variable.
130130
subCmdStandalone := []*cli.Command{
131+
cmdConfig(),
131132
cmdCert(),
132133
CmdGenerate,
133134
CmdDocs,

cmd/web.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,6 @@ func serveInstall(cmd *cli.Command) error {
156156
case <-graceful.GetManager().IsShutdown():
157157
<-graceful.GetManager().Done()
158158
log.Info("PID: %d Gitea Web Finished", os.Getpid())
159-
log.GetManager().Close()
160159
return err
161160
default:
162161
}
@@ -231,7 +230,6 @@ func serveInstalled(c *cli.Command) error {
231230
err := listen(webRoutes, true)
232231
<-graceful.GetManager().Done()
233232
log.Info("PID: %d Gitea Web Finished", os.Getpid())
234-
log.GetManager().Close()
235233
return err
236234
}
237235

contrib/environment-to-ini/README

Lines changed: 0 additions & 47 deletions
This file was deleted.

0 commit comments

Comments
 (0)