mirror of
https://github.com/go-gitea/gitea
synced 2026-02-04 18:06:31 +00:00
Compare commits
340 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1dc22029d7 | ||
|
|
4ff7ac6421 | ||
|
|
3d7f636ee4 | ||
|
|
ac70ffca56 | ||
|
|
8852a59367 | ||
|
|
8c771c8b91 | ||
|
|
53586e9d60 | ||
|
|
81f5d5b722 | ||
|
|
2184a06c1a | ||
|
|
c4798b08b1 | ||
|
|
ee87b4e18c | ||
|
|
bd1946e372 | ||
|
|
5bfe469821 | ||
|
|
53276d3e49 | ||
|
|
e6801df99c | ||
|
|
67d16c653f | ||
|
|
d4243578dd | ||
|
|
6ac353b693 | ||
|
|
3be10ddc88 | ||
|
|
37bf5e761a | ||
|
|
45d8d63621 | ||
|
|
b4bfaf7d4d | ||
|
|
1650a26eb5 | ||
|
|
a9ebf911fa | ||
|
|
de6ac4bf2a | ||
|
|
a9030052a7 | ||
|
|
ed78711e46 | ||
|
|
c23ab427e1 | ||
|
|
e3cdb050fa | ||
|
|
8df6713a6e | ||
|
|
3ef97932d5 | ||
|
|
15adec19e7 | ||
|
|
8e94b715cc | ||
|
|
b2ec116c60 | ||
|
|
edfa2c5b78 | ||
|
|
73ae6b21d1 | ||
|
|
b83e4f295d | ||
|
|
95bf09fca0 | ||
|
|
3b5cc02345 | ||
|
|
37b73b3337 | ||
|
|
d2c9fb02dd | ||
|
|
cdeb55f6e5 | ||
|
|
0ef7b66018 | ||
|
|
826b7b979c | ||
|
|
7dc46ffbaa | ||
|
|
3a7e0953c1 | ||
|
|
9da84a36eb | ||
|
|
8a6a1143a4 | ||
|
|
b4cd1028d9 | ||
|
|
d1af0a3e4c | ||
|
|
a83d597989 | ||
|
|
c5dee8823c | ||
|
|
275abd6593 | ||
|
|
d19d5bc5b8 | ||
|
|
e7757aa4be | ||
|
|
e81d38b0f6 | ||
|
|
f29c52a169 | ||
|
|
04f9ab1aa9 | ||
|
|
b369ed579d | ||
|
|
64cc691b7f | ||
|
|
1bad05da3d | ||
|
|
57f520e7e5 | ||
|
|
e4f200e616 | ||
|
|
6ecd2e782f | ||
|
|
2fea93b2d3 | ||
|
|
0ee51a5221 | ||
|
|
da1c38dd47 | ||
|
|
aa984f21fa | ||
|
|
8f722012f6 | ||
|
|
cb7ba8969d | ||
|
|
7eaf7aacde | ||
|
|
b390b439e1 | ||
|
|
306b7b5d1d | ||
|
|
4498a26222 | ||
|
|
6f57be0025 | ||
|
|
257287954c | ||
|
|
7a74957c19 | ||
|
|
f979569a3d | ||
|
|
8ceb78caad | ||
|
|
4dccac3dbf | ||
|
|
73e70f3c44 | ||
|
|
499257d81e | ||
|
|
84fa30e3d5 | ||
|
|
f1a0b64109 | ||
|
|
bfdbc626cb | ||
|
|
3abbf5fc21 | ||
|
|
d9d3f5234e | ||
|
|
7d7ba76c08 | ||
|
|
e76b3f72b2 | ||
|
|
4bc6bfb476 | ||
|
|
5999349ce7 | ||
|
|
e301e26d7a | ||
|
|
d2efd2bf73 | ||
|
|
89297c9355 | ||
|
|
d2328c4051 | ||
|
|
af5d66b341 | ||
|
|
912a418920 | ||
|
|
cc7a4f17e0 | ||
|
|
5f82011b7c | ||
|
|
1bbbeb24ef | ||
|
|
1254a8271e | ||
|
|
ef3e3afc05 | ||
|
|
b1094ff28c | ||
|
|
8044d87c18 | ||
|
|
1b8e36587e | ||
|
|
a2f52f3561 | ||
|
|
65de747b13 | ||
|
|
7e86dffc35 | ||
|
|
7297cceda7 | ||
|
|
077160b838 | ||
|
|
da4448421e | ||
|
|
5ccb626cda | ||
|
|
b00f7c3c54 | ||
|
|
51fd730147 | ||
|
|
7117355169 | ||
|
|
d5f2c9d74d | ||
|
|
95c2cb4b79 | ||
|
|
7d717e22a8 | ||
|
|
dc66ceadac | ||
|
|
8cd5483e8a | ||
|
|
2e6e5bc9c9 | ||
|
|
f134229bf2 | ||
|
|
3d3c740636 | ||
|
|
c4f569b9a5 | ||
|
|
03b6e7900b | ||
|
|
463e144d97 | ||
|
|
2b32f8b95f | ||
|
|
94fbd44bac | ||
|
|
494e373292 | ||
|
|
10f93995e9 | ||
|
|
67a73dd05f | ||
|
|
893c97dd71 | ||
|
|
447fa6715c | ||
|
|
2398a23562 | ||
|
|
93c7611c32 | ||
|
|
607801ec41 | ||
|
|
16d2cf05ab | ||
|
|
d562b419b6 | ||
|
|
5482602ba8 | ||
|
|
37d3e0ec33 | ||
|
|
29724f31c5 | ||
|
|
580da8f353 | ||
|
|
8644993699 | ||
|
|
f55fe989a4 | ||
|
|
27dbe97542 | ||
|
|
abf0386e2e | ||
|
|
2b10eebed8 | ||
|
|
695738fb31 | ||
|
|
cfde557e23 | ||
|
|
3dbc63777f | ||
|
|
4aabd8e823 | ||
|
|
6a5b8eb7b6 | ||
|
|
a00e473341 | ||
|
|
4019a6d4b2 | ||
|
|
0487e39f82 | ||
|
|
3a7cb1a83b | ||
|
|
f317186aa6 | ||
|
|
5b7df68555 | ||
|
|
833a4b1775 | ||
|
|
1b8ecd179b | ||
|
|
085b56302c | ||
|
|
5066b208de | ||
|
|
ac658bb92c | ||
|
|
001d3fb820 | ||
|
|
8092251133 | ||
|
|
55239cbab7 | ||
|
|
df74ee0376 | ||
|
|
8d88f148d7 | ||
|
|
7bfab90a8f | ||
|
|
1a8da2e08f | ||
|
|
7c180ff8eb | ||
|
|
c34f7cdb1a | ||
|
|
fd0baf637d | ||
|
|
dff3ce089d | ||
|
|
9836b7db7b | ||
|
|
d752f0d7d0 | ||
|
|
669c76c0fd | ||
|
|
ac57ec5c47 | ||
|
|
f6dab64412 | ||
|
|
847f0bb9f3 | ||
|
|
1886bd6a01 | ||
|
|
7e07f5c4dc | ||
|
|
799536db46 | ||
|
|
c68650a7fb | ||
|
|
fe7caa05cc | ||
|
|
026167f854 | ||
|
|
8abfbe2165 | ||
|
|
16bfe983c2 | ||
|
|
503af4b807 | ||
|
|
8b3dd7de5d | ||
|
|
a04535e212 | ||
|
|
a1460333dc | ||
|
|
d15f20b2d2 | ||
|
|
863da7d5a1 | ||
|
|
1cad923b36 | ||
|
|
edb6ba28f1 | ||
|
|
494721cc90 | ||
|
|
d27e693ecf | ||
|
|
81a995cd84 | ||
|
|
d977e7ec10 | ||
|
|
b73d1ac1eb | ||
|
|
428d26d4a8 | ||
|
|
a254c26df9 | ||
|
|
1fed0e1adc | ||
|
|
88a652fa92 | ||
|
|
35039b8563 | ||
|
|
62afc0a727 | ||
|
|
b6a2323981 | ||
|
|
f23b587fe7 | ||
|
|
305cac291d | ||
|
|
6705b215db | ||
|
|
a9b4aa4cc4 | ||
|
|
1faa39b44c | ||
|
|
780f71c4ca | ||
|
|
484cb22f14 | ||
|
|
2a70473af7 | ||
|
|
a28863bff7 | ||
|
|
162f2841d0 | ||
|
|
e7a5429d7a | ||
|
|
622d21691c | ||
|
|
774b37b9f8 | ||
|
|
9dfdfe2389 | ||
|
|
4439a68911 | ||
|
|
782c376c8b | ||
|
|
a3b917151c | ||
|
|
0732ba32ee | ||
|
|
726d6a5077 | ||
|
|
b33cae7a3a | ||
|
|
854fcb1434 | ||
|
|
4730ed18f1 | ||
|
|
937996c74c | ||
|
|
3f253b3f5a | ||
|
|
f5a98b0f5b | ||
|
|
1a97a84023 | ||
|
|
420d015b76 | ||
|
|
22911a1ece | ||
|
|
4b763d8d37 | ||
|
|
1254fc668a | ||
|
|
09824025f7 | ||
|
|
bd1a915bdb | ||
|
|
cab7044772 | ||
|
|
68c9f1abd8 | ||
|
|
301de3ab6b | ||
|
|
8f8bd3c0cb | ||
|
|
23a6fa9421 | ||
|
|
b7c2f48ebf | ||
|
|
70e31b4aa0 | ||
|
|
d73846f0b4 | ||
|
|
527bbf67e8 | ||
|
|
5feb31f219 | ||
|
|
31efbafbe3 | ||
|
|
28af02eea0 | ||
|
|
c698a6fc5d | ||
|
|
e5a51eca45 | ||
|
|
8536dc4b73 | ||
|
|
0a0f46f299 | ||
|
|
1543ac9c8d | ||
|
|
c3c0710412 | ||
|
|
fa33919e24 | ||
|
|
b1162495af | ||
|
|
41655ee878 | ||
|
|
0d9b44c0e3 | ||
|
|
e87f36e885 | ||
|
|
b301cb17a3 | ||
|
|
e259daeff8 | ||
|
|
edb618c136 | ||
|
|
43cf04c031 | ||
|
|
e9991b1f06 | ||
|
|
975785dd42 | ||
|
|
e269e8901f | ||
|
|
87c31c2ffe | ||
|
|
54c674c936 | ||
|
|
2ba58fab22 | ||
|
|
cd7bd8568c | ||
|
|
cf80f829b4 | ||
|
|
ed25e094ab | ||
|
|
10df304b2f | ||
|
|
ecae62837c | ||
|
|
e8e871b44e | ||
|
|
6be6c19daf | ||
|
|
61f91bdc7e | ||
|
|
8ab50be000 | ||
|
|
dfab6e2d1c | ||
|
|
2f7bbdf8c9 | ||
|
|
af4767df5c | ||
|
|
233a399706 | ||
|
|
dcf1717793 | ||
|
|
b1e68f39e7 | ||
|
|
ee3d9330a8 | ||
|
|
d1d15306d1 | ||
|
|
e3b1ebbbfe | ||
|
|
17ae7e335e | ||
|
|
1edb57eda9 | ||
|
|
a2a9b0f977 | ||
|
|
ff96f804b6 | ||
|
|
a926994bfe | ||
|
|
83903535e3 | ||
|
|
8142408d3a | ||
|
|
a4158d1904 | ||
|
|
781019216c | ||
|
|
1322cd7a58 | ||
|
|
464bbd747e | ||
|
|
574182e1eb | ||
|
|
ef8209a953 | ||
|
|
9309098eab | ||
|
|
790a79b04c | ||
|
|
f8a40dafb9 | ||
|
|
9843a0b741 | ||
|
|
085a4debd5 | ||
|
|
4c1e24864f | ||
|
|
5d5f907e7f | ||
|
|
39178b5756 | ||
|
|
3d8412dd51 | ||
|
|
ff7057a46d | ||
|
|
bb8ef28913 | ||
|
|
13918ad344 | ||
|
|
7528ce60e7 | ||
|
|
6c6a7e7d97 | ||
|
|
111c509287 | ||
|
|
9d7ef0ad63 | ||
|
|
9aae54c81f | ||
|
|
1bc4ffc337 | ||
|
|
27879bc45e | ||
|
|
a3694b6989 | ||
|
|
28625fba5b | ||
|
|
7c3196ceac | ||
|
|
80c1264f4b | ||
|
|
f0340c28f1 | ||
|
|
5beb29ad35 | ||
|
|
27e307142b | ||
|
|
e02e752f68 | ||
|
|
5ddf67a9c2 | ||
|
|
4d3e2b23b8 | ||
|
|
ddf61373f6 | ||
|
|
b4ed3f07e4 | ||
|
|
ced94f2e0d | ||
|
|
aff432b197 | ||
|
|
0ac3be1482 | ||
|
|
75eaf99076 | ||
|
|
e67d60d336 |
@@ -2,12 +2,9 @@ root = "."
|
||||
tmp_dir = ".air"
|
||||
|
||||
[build]
|
||||
cmd = "make --no-print-directory backend"
|
||||
cmd = "make backend"
|
||||
bin = "gitea"
|
||||
delay = 1000
|
||||
include_ext = ["go", "tmpl"]
|
||||
include_file = ["main.go"]
|
||||
include_dir = ["cmd", "models", "modules", "options", "routers", "services"]
|
||||
exclude_dir = ["modules/git/tests", "services/gitdiff/testdata", "modules/avatar/testdata", "models/fixtures", "models/migrations/fixtures", "modules/migration/file_format_testdata", "modules/avatar/identicon/testdata"]
|
||||
include_dir = ["cmd", "models", "modules", "options", "routers", "services"]
|
||||
exclude_regex = ["_test.go$", "_gen.go$"]
|
||||
stop_on_error = true
|
||||
|
||||
@@ -76,6 +76,7 @@ cpu.out
|
||||
/yarn-error.log
|
||||
/npm-debug.log*
|
||||
/public/js
|
||||
/public/serviceworker.js
|
||||
/public/css
|
||||
/public/fonts
|
||||
/public/img/webpack
|
||||
|
||||
+1246
-13
File diff suppressed because it is too large
Load Diff
+19
-233
@@ -9,17 +9,10 @@ parserOptions:
|
||||
ecmaVersion: latest
|
||||
|
||||
plugins:
|
||||
- "@eslint-community/eslint-plugin-eslint-comments"
|
||||
- eslint-plugin-array-func
|
||||
- eslint-plugin-custom-elements
|
||||
- eslint-plugin-unicorn
|
||||
- eslint-plugin-import
|
||||
- eslint-plugin-jquery
|
||||
- eslint-plugin-no-jquery
|
||||
- eslint-plugin-no-use-extend-native
|
||||
- eslint-plugin-regexp
|
||||
- eslint-plugin-sonarjs
|
||||
- eslint-plugin-unicorn
|
||||
- eslint-plugin-wc
|
||||
|
||||
env:
|
||||
es2022: true
|
||||
@@ -29,11 +22,11 @@ globals:
|
||||
__webpack_public_path__: true
|
||||
|
||||
overrides:
|
||||
- files: ["web_src/**/*", "docs/**/*"]
|
||||
- files: ["web_src/**/*.js", "docs/**/*.js"]
|
||||
env:
|
||||
browser: true
|
||||
node: false
|
||||
- files: ["web_src/**/*worker.*"]
|
||||
- files: ["web_src/**/*worker.js"]
|
||||
env:
|
||||
worker: true
|
||||
rules:
|
||||
@@ -42,31 +35,16 @@ overrides:
|
||||
rules:
|
||||
import/no-unresolved: [0]
|
||||
import/no-extraneous-dependencies: [0]
|
||||
- files: ["*.config.*"]
|
||||
- files: ["*.config.js"]
|
||||
rules:
|
||||
import/no-unused-modules: [0]
|
||||
|
||||
rules:
|
||||
"@eslint-community/eslint-comments/disable-enable-pair": [2]
|
||||
"@eslint-community/eslint-comments/no-aggregating-enable": [2]
|
||||
"@eslint-community/eslint-comments/no-duplicate-disable": [2]
|
||||
"@eslint-community/eslint-comments/no-restricted-disable": [0]
|
||||
"@eslint-community/eslint-comments/no-unlimited-disable": [2]
|
||||
"@eslint-community/eslint-comments/no-unused-disable": [2]
|
||||
"@eslint-community/eslint-comments/no-unused-enable": [2]
|
||||
"@eslint-community/eslint-comments/no-use": [0]
|
||||
"@eslint-community/eslint-comments/require-description": [0]
|
||||
accessor-pairs: [2]
|
||||
array-bracket-newline: [0]
|
||||
array-bracket-spacing: [2, never]
|
||||
array-callback-return: [2, {checkForEach: true}]
|
||||
array-element-newline: [0]
|
||||
array-func/avoid-reverse: [2]
|
||||
array-func/from-map: [2]
|
||||
array-func/no-unnecessary-this-arg: [2]
|
||||
array-func/prefer-array-from: [2]
|
||||
array-func/prefer-flat-map: [0] # handled by unicorn/prefer-array-flat-map
|
||||
array-func/prefer-flat: [0] # handled by unicorn/prefer-array-flat
|
||||
arrow-body-style: [0]
|
||||
arrow-parens: [2, always]
|
||||
arrow-spacing: [2, {before: true, after: true}]
|
||||
@@ -84,19 +62,6 @@ rules:
|
||||
consistent-this: [0]
|
||||
constructor-super: [2]
|
||||
curly: [0]
|
||||
custom-elements/expose-class-on-global: [0]
|
||||
custom-elements/extends-correct-class: [2]
|
||||
custom-elements/file-name-matches-element: [2]
|
||||
custom-elements/no-constructor: [2]
|
||||
custom-elements/no-customized-built-in-elements: [2]
|
||||
custom-elements/no-dom-traversal-in-attributechangedcallback: [2]
|
||||
custom-elements/no-dom-traversal-in-connectedcallback: [2]
|
||||
custom-elements/no-exports-with-element: [2]
|
||||
custom-elements/no-method-prefixed-with-on: [2]
|
||||
custom-elements/no-unchecked-define: [0]
|
||||
custom-elements/one-element-per-file: [0]
|
||||
custom-elements/tag-name-matches-class: [2]
|
||||
custom-elements/valid-tag-name: [2]
|
||||
default-case-last: [2]
|
||||
default-case: [0]
|
||||
default-param-last: [0]
|
||||
@@ -132,9 +97,9 @@ rules:
|
||||
import/namespace: [0]
|
||||
import/newline-after-import: [0]
|
||||
import/no-absolute-path: [0]
|
||||
import/no-amd: [2]
|
||||
import/no-amd: [0]
|
||||
import/no-anonymous-default-export: [0]
|
||||
import/no-commonjs: [2]
|
||||
import/no-commonjs: [0]
|
||||
import/no-cycle: [2, {ignoreExternal: true, maxDepth: 1}]
|
||||
import/no-default-export: [0]
|
||||
import/no-deprecated: [0]
|
||||
@@ -199,7 +164,7 @@ rules:
|
||||
jquery/no-parse-html: [2]
|
||||
jquery/no-prop: [0]
|
||||
jquery/no-proxy: [2]
|
||||
jquery/no-ready: [2]
|
||||
jquery/no-ready: [0]
|
||||
jquery/no-serialize: [2]
|
||||
jquery/no-show: [2]
|
||||
jquery/no-size: [2]
|
||||
@@ -291,99 +256,6 @@ rules:
|
||||
no-invalid-this: [0]
|
||||
no-irregular-whitespace: [2]
|
||||
no-iterator: [2]
|
||||
no-jquery/no-ajax-events: [2]
|
||||
no-jquery/no-ajax: [0]
|
||||
no-jquery/no-and-self: [2]
|
||||
no-jquery/no-animate-toggle: [2]
|
||||
no-jquery/no-animate: [2]
|
||||
no-jquery/no-append-html: [0]
|
||||
no-jquery/no-attr: [0]
|
||||
no-jquery/no-bind: [2]
|
||||
no-jquery/no-box-model: [2]
|
||||
no-jquery/no-browser: [2]
|
||||
no-jquery/no-camel-case: [2]
|
||||
no-jquery/no-class-state: [0]
|
||||
no-jquery/no-class: [0]
|
||||
no-jquery/no-clone: [2]
|
||||
no-jquery/no-closest: [0]
|
||||
no-jquery/no-constructor-attributes: [2]
|
||||
no-jquery/no-contains: [2]
|
||||
no-jquery/no-context-prop: [2]
|
||||
no-jquery/no-css: [0]
|
||||
no-jquery/no-data: [0]
|
||||
no-jquery/no-deferred: [2]
|
||||
no-jquery/no-delegate: [2]
|
||||
no-jquery/no-each-collection: [0]
|
||||
no-jquery/no-each-util: [0]
|
||||
no-jquery/no-each: [0]
|
||||
no-jquery/no-error-shorthand: [2]
|
||||
no-jquery/no-error: [2]
|
||||
no-jquery/no-escape-selector: [2]
|
||||
no-jquery/no-event-shorthand: [2]
|
||||
no-jquery/no-extend: [2]
|
||||
no-jquery/no-fade: [2]
|
||||
no-jquery/no-filter: [0]
|
||||
no-jquery/no-find-collection: [0]
|
||||
no-jquery/no-find-util: [2]
|
||||
no-jquery/no-find: [0]
|
||||
no-jquery/no-fx-interval: [2]
|
||||
no-jquery/no-global-eval: [2]
|
||||
no-jquery/no-global-selector: [0]
|
||||
no-jquery/no-grep: [2]
|
||||
no-jquery/no-has: [2]
|
||||
no-jquery/no-hold-ready: [2]
|
||||
no-jquery/no-html: [0]
|
||||
no-jquery/no-in-array: [2]
|
||||
no-jquery/no-is-array: [2]
|
||||
no-jquery/no-is-empty-object: [2]
|
||||
no-jquery/no-is-function: [2]
|
||||
no-jquery/no-is-numeric: [2]
|
||||
no-jquery/no-is-plain-object: [2]
|
||||
no-jquery/no-is-window: [2]
|
||||
no-jquery/no-is: [0]
|
||||
no-jquery/no-jquery-constructor: [0]
|
||||
no-jquery/no-live: [2]
|
||||
no-jquery/no-load-shorthand: [2]
|
||||
no-jquery/no-load: [2]
|
||||
no-jquery/no-map-collection: [0]
|
||||
no-jquery/no-map-util: [2]
|
||||
no-jquery/no-map: [0]
|
||||
no-jquery/no-merge: [2]
|
||||
no-jquery/no-node-name: [2]
|
||||
no-jquery/no-noop: [2]
|
||||
no-jquery/no-now: [2]
|
||||
no-jquery/no-on-ready: [2]
|
||||
no-jquery/no-other-methods: [0]
|
||||
no-jquery/no-other-utils: [2]
|
||||
no-jquery/no-param: [2]
|
||||
no-jquery/no-parent: [0]
|
||||
no-jquery/no-parents: [0]
|
||||
no-jquery/no-parse-html-literal: [0]
|
||||
no-jquery/no-parse-html: [2]
|
||||
no-jquery/no-parse-json: [2]
|
||||
no-jquery/no-parse-xml: [2]
|
||||
no-jquery/no-prop: [0]
|
||||
no-jquery/no-proxy: [2]
|
||||
no-jquery/no-ready-shorthand: [2]
|
||||
no-jquery/no-ready: [2]
|
||||
no-jquery/no-selector-prop: [2]
|
||||
no-jquery/no-serialize: [2]
|
||||
no-jquery/no-size: [2]
|
||||
no-jquery/no-sizzle: [0]
|
||||
no-jquery/no-slide: [2]
|
||||
no-jquery/no-sub: [2]
|
||||
no-jquery/no-support: [2]
|
||||
no-jquery/no-text: [0]
|
||||
no-jquery/no-trigger: [0]
|
||||
no-jquery/no-trim: [2]
|
||||
no-jquery/no-type: [2]
|
||||
no-jquery/no-unique: [2]
|
||||
no-jquery/no-unload-shorthand: [2]
|
||||
no-jquery/no-val: [0]
|
||||
no-jquery/no-visibility: [2]
|
||||
no-jquery/no-when: [2]
|
||||
no-jquery/no-wrap: [2]
|
||||
no-jquery/variable-pattern: [0]
|
||||
no-label-var: [2]
|
||||
no-labels: [0] # handled by no-restricted-syntax
|
||||
no-lone-blocks: [2]
|
||||
@@ -452,7 +324,6 @@ rules:
|
||||
no-unused-private-class-members: [2]
|
||||
no-unused-vars: [2, {args: all, argsIgnorePattern: ^_, varsIgnorePattern: ^_, caughtErrorsIgnorePattern: ^_, destructuredArrayIgnorePattern: ^_, ignoreRestSiblings: false}]
|
||||
no-use-before-define: [2, {functions: false, classes: true, variables: true, allowNamedExports: true}]
|
||||
no-use-extend-native/no-use-extend-native: [2]
|
||||
no-useless-backreference: [2]
|
||||
no-useless-call: [2]
|
||||
no-useless-catch: [2]
|
||||
@@ -493,80 +364,6 @@ rules:
|
||||
quote-props: [0]
|
||||
quotes: [2, single, {avoidEscape: true, allowTemplateLiterals: true}]
|
||||
radix: [2, as-needed]
|
||||
regexp/confusing-quantifier: [2]
|
||||
regexp/control-character-escape: [2]
|
||||
regexp/hexadecimal-escape: [0]
|
||||
regexp/letter-case: [0]
|
||||
regexp/match-any: [2]
|
||||
regexp/negation: [2]
|
||||
regexp/no-contradiction-with-assertion: [0]
|
||||
regexp/no-control-character: [0]
|
||||
regexp/no-dupe-characters-character-class: [2]
|
||||
regexp/no-dupe-disjunctions: [2]
|
||||
regexp/no-empty-alternative: [2]
|
||||
regexp/no-empty-capturing-group: [2]
|
||||
regexp/no-empty-character-class: [0]
|
||||
regexp/no-empty-group: [2]
|
||||
regexp/no-empty-lookarounds-assertion: [2]
|
||||
regexp/no-escape-backspace: [2]
|
||||
regexp/no-extra-lookaround-assertions: [0]
|
||||
regexp/no-invalid-regexp: [2]
|
||||
regexp/no-invisible-character: [2]
|
||||
regexp/no-lazy-ends: [2]
|
||||
regexp/no-legacy-features: [2]
|
||||
regexp/no-misleading-capturing-group: [0]
|
||||
regexp/no-misleading-unicode-character: [0]
|
||||
regexp/no-missing-g-flag: [2]
|
||||
regexp/no-non-standard-flag: [2]
|
||||
regexp/no-obscure-range: [2]
|
||||
regexp/no-octal: [2]
|
||||
regexp/no-optional-assertion: [2]
|
||||
regexp/no-potentially-useless-backreference: [2]
|
||||
regexp/no-standalone-backslash: [2]
|
||||
regexp/no-super-linear-backtracking: [0]
|
||||
regexp/no-super-linear-move: [0]
|
||||
regexp/no-trivially-nested-assertion: [2]
|
||||
regexp/no-trivially-nested-quantifier: [2]
|
||||
regexp/no-unused-capturing-group: [0]
|
||||
regexp/no-useless-assertions: [2]
|
||||
regexp/no-useless-backreference: [2]
|
||||
regexp/no-useless-character-class: [2]
|
||||
regexp/no-useless-dollar-replacements: [2]
|
||||
regexp/no-useless-escape: [2]
|
||||
regexp/no-useless-flag: [2]
|
||||
regexp/no-useless-lazy: [2]
|
||||
regexp/no-useless-non-capturing-group: [2]
|
||||
regexp/no-useless-quantifier: [2]
|
||||
regexp/no-useless-range: [2]
|
||||
regexp/no-useless-two-nums-quantifier: [2]
|
||||
regexp/no-zero-quantifier: [2]
|
||||
regexp/optimal-lookaround-quantifier: [2]
|
||||
regexp/optimal-quantifier-concatenation: [0]
|
||||
regexp/prefer-character-class: [0]
|
||||
regexp/prefer-d: [0]
|
||||
regexp/prefer-escape-replacement-dollar-char: [0]
|
||||
regexp/prefer-lookaround: [0]
|
||||
regexp/prefer-named-backreference: [0]
|
||||
regexp/prefer-named-capture-group: [0]
|
||||
regexp/prefer-named-replacement: [0]
|
||||
regexp/prefer-plus-quantifier: [2]
|
||||
regexp/prefer-predefined-assertion: [2]
|
||||
regexp/prefer-quantifier: [0]
|
||||
regexp/prefer-question-quantifier: [2]
|
||||
regexp/prefer-range: [2]
|
||||
regexp/prefer-regexp-exec: [2]
|
||||
regexp/prefer-regexp-test: [2]
|
||||
regexp/prefer-result-array-groups: [0]
|
||||
regexp/prefer-star-quantifier: [2]
|
||||
regexp/prefer-unicode-codepoint-escapes: [2]
|
||||
regexp/prefer-w: [0]
|
||||
regexp/require-unicode-regexp: [0]
|
||||
regexp/sort-alternatives: [0]
|
||||
regexp/sort-character-class-elements: [0]
|
||||
regexp/sort-flags: [0]
|
||||
regexp/strict: [2]
|
||||
regexp/unicode-escape: [0]
|
||||
regexp/use-ignore-case: [0]
|
||||
require-atomic-updates: [0]
|
||||
require-await: [0]
|
||||
require-unicode-regexp: [0]
|
||||
@@ -596,7 +393,7 @@ rules:
|
||||
sonarjs/no-nested-template-literals: [0]
|
||||
sonarjs/no-one-iteration-loop: [2]
|
||||
sonarjs/no-redundant-boolean: [2]
|
||||
sonarjs/no-redundant-jump: [2]
|
||||
sonarjs/no-redundant-jump: [0]
|
||||
sonarjs/no-same-line-conditional: [2]
|
||||
sonarjs/no-small-switch: [0]
|
||||
sonarjs/no-unused-collection: [2]
|
||||
@@ -636,18 +433,17 @@ rules:
|
||||
unicorn/import-style: [0]
|
||||
unicorn/new-for-builtins: [2]
|
||||
unicorn/no-abusive-eslint-disable: [0]
|
||||
unicorn/no-array-callback-reference: [0]
|
||||
unicorn/no-array-for-each: [2]
|
||||
unicorn/no-array-instanceof: [0]
|
||||
unicorn/no-array-method-this-argument: [2]
|
||||
unicorn/no-array-push-push: [2]
|
||||
unicorn/no-array-reduce: [2]
|
||||
unicorn/no-await-expression-member: [0]
|
||||
unicorn/no-console-spaces: [0]
|
||||
unicorn/no-document-cookie: [2]
|
||||
unicorn/no-empty-file: [2]
|
||||
unicorn/no-fn-reference-in-iterator: [0]
|
||||
unicorn/no-for-loop: [0]
|
||||
unicorn/no-hex-escape: [0]
|
||||
unicorn/no-instanceof-array: [0]
|
||||
unicorn/no-invalid-remove-event-listener: [2]
|
||||
unicorn/no-keyword-prefix: [0]
|
||||
unicorn/no-lonely-if: [2]
|
||||
@@ -658,6 +454,7 @@ rules:
|
||||
unicorn/no-null: [0]
|
||||
unicorn/no-object-as-default-parameter: [0]
|
||||
unicorn/no-process-exit: [0]
|
||||
unicorn/no-reduce: [2]
|
||||
unicorn/no-static-only-class: [2]
|
||||
unicorn/no-thenable: [2]
|
||||
unicorn/no-this-assignment: [2]
|
||||
@@ -683,19 +480,15 @@ rules:
|
||||
unicorn/prefer-array-index-of: [2]
|
||||
unicorn/prefer-array-some: [2]
|
||||
unicorn/prefer-at: [0]
|
||||
unicorn/prefer-blob-reading-methods: [2]
|
||||
unicorn/prefer-code-point: [0]
|
||||
unicorn/prefer-dataset: [2]
|
||||
unicorn/prefer-date-now: [2]
|
||||
unicorn/prefer-default-parameters: [0]
|
||||
unicorn/prefer-dom-node-append: [2]
|
||||
unicorn/prefer-dom-node-dataset: [0]
|
||||
unicorn/prefer-dom-node-remove: [2]
|
||||
unicorn/prefer-dom-node-text-content: [2]
|
||||
unicorn/prefer-event-key: [2]
|
||||
unicorn/prefer-event-target: [2]
|
||||
unicorn/prefer-export-from: [2, {ignoreUsedVariables: true}]
|
||||
unicorn/prefer-export-from: [2]
|
||||
unicorn/prefer-includes: [2]
|
||||
unicorn/prefer-json-parse-buffer: [0]
|
||||
unicorn/prefer-keyboard-event-key: [2]
|
||||
unicorn/prefer-logical-operator-over-ternary: [2]
|
||||
unicorn/prefer-math-trunc: [2]
|
||||
unicorn/prefer-modern-dom-apis: [0]
|
||||
@@ -703,7 +496,9 @@ rules:
|
||||
unicorn/prefer-module: [2]
|
||||
unicorn/prefer-native-coercion-functions: [2]
|
||||
unicorn/prefer-negative-index: [2]
|
||||
unicorn/prefer-node-append: [0]
|
||||
unicorn/prefer-node-protocol: [2]
|
||||
unicorn/prefer-node-remove: [0]
|
||||
unicorn/prefer-number-properties: [0]
|
||||
unicorn/prefer-object-from-entries: [2]
|
||||
unicorn/prefer-object-has-own: [0]
|
||||
@@ -712,17 +507,17 @@ rules:
|
||||
unicorn/prefer-query-selector: [0]
|
||||
unicorn/prefer-reflect-apply: [0]
|
||||
unicorn/prefer-regexp-test: [2]
|
||||
unicorn/prefer-replace-all: [0]
|
||||
unicorn/prefer-set-has: [0]
|
||||
unicorn/prefer-set-size: [2]
|
||||
unicorn/prefer-spread: [0]
|
||||
unicorn/prefer-string-replace-all: [0]
|
||||
unicorn/prefer-starts-ends-with: [2]
|
||||
unicorn/prefer-string-slice: [0]
|
||||
unicorn/prefer-string-starts-ends-with: [2]
|
||||
unicorn/prefer-string-trim-start-end: [2]
|
||||
unicorn/prefer-switch: [0]
|
||||
unicorn/prefer-ternary: [0]
|
||||
unicorn/prefer-text-content: [2]
|
||||
unicorn/prefer-top-level-await: [0]
|
||||
unicorn/prefer-trim-start-end: [2]
|
||||
unicorn/prefer-type-error: [0]
|
||||
unicorn/prevent-abbreviations: [0]
|
||||
unicorn/relative-url-style: [2]
|
||||
@@ -737,15 +532,6 @@ rules:
|
||||
use-isnan: [2]
|
||||
valid-typeof: [2, {requireStringLiterals: true}]
|
||||
vars-on-top: [0]
|
||||
wc/attach-shadow-constructor: [2]
|
||||
wc/guard-super-call: [2]
|
||||
wc/no-closed-shadow-root: [2]
|
||||
wc/no-constructor-attributes: [2]
|
||||
wc/no-constructor-params: [2]
|
||||
wc/no-invalid-element-name: [0] # covered by custom-elements/valid-tag-name
|
||||
wc/no-self-class: [2]
|
||||
wc/no-typos: [2]
|
||||
wc/require-listener-teardown: [2]
|
||||
wrap-iife: [2, inside]
|
||||
wrap-regex: [0]
|
||||
yield-star-spacing: [2, after]
|
||||
|
||||
+1
-3
@@ -1,10 +1,8 @@
|
||||
* text=auto eol=lf
|
||||
*.tmpl linguist-language=Handlebars
|
||||
/assets/*.json linguist-generated
|
||||
/public/img/svg/*.svg linguist-generated
|
||||
/templates/swagger/v1_json.tmpl linguist-generated
|
||||
/public/vendor/** -text -eol linguist-vendored
|
||||
/vendor/** -text -eol linguist-vendored
|
||||
/web_src/fomantic/build/** linguist-generated
|
||||
/web_src/fomantic/_site/globals/site.variables linguist-language=Less
|
||||
/web_src/js/vendor/** -text -eol linguist-vendored
|
||||
Dockerfile.* linguist-language=Dockerfile
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
# Configuration for Lock Threads - https://github.com/dessant/lock-threads-app
|
||||
|
||||
# Number of days of inactivity before a closed issue or pull request is locked
|
||||
daysUntilLock: 60
|
||||
|
||||
# Skip issues and pull requests created before a given timestamp. Timestamp must
|
||||
# follow ISO 8601 (`YYYY-MM-DD`). `false` is disabled
|
||||
skipCreatedBefore: false
|
||||
|
||||
# Issues and pull requests with these labels will be ignored.
|
||||
exemptLabels: []
|
||||
|
||||
# Label to add before locking, such as `outdated`. `false` is disabled
|
||||
lockLabel: false
|
||||
|
||||
# Comment to post before locking.
|
||||
lockComment: >
|
||||
This thread has been automatically locked since there has not been
|
||||
any recent activity after it was closed. Please open a new issue for
|
||||
related bugs and link to relevant comments in this thread.
|
||||
|
||||
# Assign `resolved` as the reason for locking. Set to `false` to disable
|
||||
setLockReason: true
|
||||
@@ -1,28 +0,0 @@
|
||||
name: cron-licenses
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "7 0 * * 1" # every Monday at 00:07 UTC
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
cron-licenses:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'go-gitea/gitea'
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: ">=1.20.1"
|
||||
- run: make generate-license generate-gitignore
|
||||
timeout-minutes: 40
|
||||
- name: push translations to repo
|
||||
uses: appleboy/git-push-action@v0.0.2
|
||||
with:
|
||||
author_email: "teabot@gitea.io"
|
||||
author_name: GiteaBot
|
||||
branch: main
|
||||
commit: true
|
||||
commit_message: "[skip ci] Updated licenses and gitignores"
|
||||
remote: "git@github.com:go-gitea/gitea.git"
|
||||
ssh_key: ${{ secrets.DEPLOY_KEY }}
|
||||
@@ -1,22 +0,0 @@
|
||||
name: cron-lock
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0 * * *" # every day at 00:00 UTC
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
concurrency:
|
||||
group: lock
|
||||
|
||||
jobs:
|
||||
action:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'go-gitea/gitea'
|
||||
steps:
|
||||
- uses: dessant/lock-threads@v4
|
||||
with:
|
||||
issue-inactive-days: 45
|
||||
@@ -1,49 +0,0 @@
|
||||
name: cron-translations
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "7 0 * * *" # every day at 00:07 UTC
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
crowdin-pull:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'go-gitea/gitea'
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: download from crowdin
|
||||
uses: docker://jonasfranz/crowdin
|
||||
env:
|
||||
CROWDIN_KEY: ${{ secrets.CROWDIN_KEY }}
|
||||
PLUGIN_DOWNLOAD: true
|
||||
PLUGIN_EXPORT_DIR: options/locale/
|
||||
PLUGIN_IGNORE_BRANCH: true
|
||||
PLUGIN_PROJECT_IDENTIFIER: gitea
|
||||
- name: update locales
|
||||
run: ./build/update-locales.sh
|
||||
- name: push translations to repo
|
||||
uses: appleboy/git-push-action@v0.0.2
|
||||
with:
|
||||
author_email: "teabot@gitea.io"
|
||||
author_name: GiteaBot
|
||||
branch: main
|
||||
commit: true
|
||||
commit_message: "[skip ci] Updated translations via Crowdin"
|
||||
remote: "git@github.com:go-gitea/gitea.git"
|
||||
ssh_key: ${{ secrets.DEPLOY_KEY }}
|
||||
crowdin-push:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'go-gitea/gitea'
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: push translations to crowdin
|
||||
uses: docker://jonasfranz/crowdin
|
||||
env:
|
||||
CROWDIN_KEY: ${{ secrets.CROWDIN_KEY }}
|
||||
PLUGIN_UPLOAD: true
|
||||
PLUGIN_EXPORT_DIR: options/locale/
|
||||
PLUGIN_IGNORE_BRANCH: true
|
||||
PLUGIN_PROJECT_IDENTIFIER: gitea
|
||||
PLUGIN_FILES: |
|
||||
locale_en-US.ini: options/locale/locale_en-US.ini
|
||||
PLUGIN_BRANCH: main
|
||||
@@ -1,53 +0,0 @@
|
||||
name: files-changed
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
outputs:
|
||||
backend:
|
||||
description: "whether backend files changed"
|
||||
value: ${{ jobs.detect.outputs.backend }}
|
||||
frontend:
|
||||
description: "whether frontend files changed"
|
||||
value: ${{ jobs.detect.outputs.frontend }}
|
||||
docs:
|
||||
description: "whether docs files changed"
|
||||
value: ${{ jobs.detect.outputs.docs }}
|
||||
actions:
|
||||
description: "whether actions files changed"
|
||||
value: ${{ jobs.detect.outputs.actions }}
|
||||
|
||||
jobs:
|
||||
detect:
|
||||
name: detect which files changed
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 3
|
||||
# Map a step output to a job output
|
||||
outputs:
|
||||
backend: ${{ steps.changes.outputs.backend }}
|
||||
frontend: ${{ steps.changes.outputs.frontend }}
|
||||
docs: ${{ steps.changes.outputs.docs }}
|
||||
actions: ${{ steps.changes.outputs.actions }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: dorny/paths-filter@v2
|
||||
id: changes
|
||||
with:
|
||||
filters: |
|
||||
backend:
|
||||
- "**/*.go"
|
||||
- "**/*.tmpl"
|
||||
- "go.mod"
|
||||
- "go.sum"
|
||||
|
||||
frontend:
|
||||
- "**/*.js"
|
||||
- "web_src/**"
|
||||
- "package.json"
|
||||
- "package-lock.json"
|
||||
|
||||
docs:
|
||||
- "**/*.md"
|
||||
- "docs/**"
|
||||
|
||||
actions:
|
||||
- ".github/workflows/*"
|
||||
@@ -1,140 +0,0 @@
|
||||
name: compliance
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
files-changed:
|
||||
uses: ./.github/workflows/files-changed.yml
|
||||
|
||||
lint-backend:
|
||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: ">=1.20"
|
||||
check-latest: true
|
||||
- run: make deps-backend deps-tools
|
||||
- run: make lint-backend
|
||||
env:
|
||||
TAGS: bindata sqlite sqlite_unlock_notify
|
||||
|
||||
lint-go-windows:
|
||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: ">=1.20"
|
||||
check-latest: true
|
||||
- run: make deps-backend deps-tools
|
||||
- run: make lint-go-windows lint-go-vet
|
||||
env:
|
||||
TAGS: bindata sqlite sqlite_unlock_notify
|
||||
GOOS: windows
|
||||
GOARCH: amd64
|
||||
|
||||
lint-go-gogit:
|
||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: ">=1.20"
|
||||
check-latest: true
|
||||
- run: make deps-backend deps-tools
|
||||
- run: make lint-go
|
||||
env:
|
||||
TAGS: bindata gogit sqlite sqlite_unlock_notify
|
||||
|
||||
checks-backend:
|
||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: ">=1.20"
|
||||
check-latest: true
|
||||
- run: make deps-backend deps-tools
|
||||
- run: make --always-make checks-backend # ensure the "go-licenses" make target runs
|
||||
|
||||
frontend:
|
||||
if: needs.files-changed.outputs.frontend == 'true' || needs.files-changed.outputs.actions == 'true'
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 20
|
||||
- run: make deps-frontend
|
||||
- run: make lint-frontend
|
||||
- run: make checks-frontend
|
||||
- run: make frontend
|
||||
|
||||
backend:
|
||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: ">=1.20"
|
||||
check-latest: true
|
||||
# no frontend build here as backend should be able to build
|
||||
# even without any frontend files
|
||||
- run: make deps-backend deps-tools
|
||||
- run: go build -o gitea_no_gcc # test if build succeeds without the sqlite tag
|
||||
- name: build-backend-arm64
|
||||
run: make backend # test cross compile
|
||||
env:
|
||||
GOOS: linux
|
||||
GOARCH: arm64
|
||||
TAGS: bindata gogit
|
||||
- name: build-backend-windows
|
||||
run: go build -o gitea_windows
|
||||
env:
|
||||
GOOS: windows
|
||||
GOARCH: amd64
|
||||
TAGS: bindata gogit
|
||||
- name: build-backend-386
|
||||
run: go build -o gitea_linux_386 # test if compatible with 32 bit
|
||||
env:
|
||||
GOOS: linux
|
||||
GOARCH: 386
|
||||
|
||||
docs:
|
||||
if: needs.files-changed.outputs.docs == 'true' || needs.files-changed.outputs.actions == 'true'
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 20
|
||||
- run: make deps-frontend
|
||||
- run: make lint-md
|
||||
- run: make docs # test if build could succeed
|
||||
|
||||
actions:
|
||||
if: needs.files-changed.outputs.actions == 'true' || needs.files-changed.outputs.actions == 'true'
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v4
|
||||
- run: make lint-actions
|
||||
@@ -1,247 +0,0 @@
|
||||
name: db-tests
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
files-changed:
|
||||
uses: ./.github/workflows/files-changed.yml
|
||||
|
||||
test-pgsql:
|
||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
services:
|
||||
pgsql:
|
||||
image: postgres:15
|
||||
env:
|
||||
POSTGRES_DB: test
|
||||
POSTGRES_PASSWORD: postgres
|
||||
ports:
|
||||
- "5432:5432"
|
||||
ldap:
|
||||
image: gitea/test-openldap:latest
|
||||
ports:
|
||||
- "389:389"
|
||||
- "636:636"
|
||||
minio:
|
||||
# as github actions doesn't support "entrypoint", we need to use a non-official image
|
||||
# that has a custom entrypoint set to "minio server /data"
|
||||
image: bitnami/minio:2021.3.17
|
||||
env:
|
||||
MINIO_ACCESS_KEY: 123456
|
||||
MINIO_SECRET_KEY: 12345678
|
||||
ports:
|
||||
- "9000:9000"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: ">=1.20.0"
|
||||
- name: Add hosts to /etc/hosts
|
||||
run: '[ -e "/.dockerenv" ] || [ -e "/run/.containerenv" ] || echo "127.0.0.1 pgsql ldap minio" | sudo tee -a /etc/hosts'
|
||||
- run: make deps-backend
|
||||
- run: make backend
|
||||
env:
|
||||
TAGS: bindata
|
||||
- run: make test-pgsql-migration test-pgsql
|
||||
timeout-minutes: 50
|
||||
env:
|
||||
TAGS: bindata gogit
|
||||
RACE_ENABLED: true
|
||||
TEST_TAGS: gogit
|
||||
TEST_LDAP: 1
|
||||
USE_REPO_TEST_DIR: 1
|
||||
|
||||
test-sqlite:
|
||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: ">=1.20.0"
|
||||
- run: make deps-backend
|
||||
- run: make backend
|
||||
env:
|
||||
TAGS: bindata gogit sqlite sqlite_unlock_notify
|
||||
- run: make test-sqlite-migration test-sqlite
|
||||
timeout-minutes: 50
|
||||
env:
|
||||
TAGS: bindata gogit sqlite sqlite_unlock_notify
|
||||
RACE_ENABLED: true
|
||||
TEST_TAGS: gogit sqlite sqlite_unlock_notify
|
||||
USE_REPO_TEST_DIR: 1
|
||||
|
||||
test-unit:
|
||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
services:
|
||||
mysql:
|
||||
image: mysql:5.7
|
||||
env:
|
||||
MYSQL_ALLOW_EMPTY_PASSWORD: yes
|
||||
MYSQL_DATABASE: test
|
||||
ports:
|
||||
- "3306:3306"
|
||||
elasticsearch:
|
||||
image: elasticsearch:7.5.0
|
||||
env:
|
||||
discovery.type: single-node
|
||||
ports:
|
||||
- "9200:9200"
|
||||
smtpimap:
|
||||
image: tabascoterrier/docker-imap-devel:latest
|
||||
ports:
|
||||
- "25:25"
|
||||
- "143:143"
|
||||
- "587:587"
|
||||
- "993:993"
|
||||
redis:
|
||||
image: redis
|
||||
options: >- # wait until redis has started
|
||||
--health-cmd "redis-cli ping"
|
||||
--health-interval 5s
|
||||
--health-timeout 3s
|
||||
--health-retries 10
|
||||
ports:
|
||||
- 6379:6379
|
||||
minio:
|
||||
image: bitnami/minio:2021.3.17
|
||||
env:
|
||||
MINIO_ACCESS_KEY: 123456
|
||||
MINIO_SECRET_KEY: 12345678
|
||||
ports:
|
||||
- "9000:9000"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: ">=1.20.0"
|
||||
- name: Add hosts to /etc/hosts
|
||||
run: '[ -e "/.dockerenv" ] || [ -e "/run/.containerenv" ] || echo "127.0.0.1 mysql elasticsearch smtpimap" | sudo tee -a /etc/hosts'
|
||||
- run: make deps-backend
|
||||
- run: make backend
|
||||
env:
|
||||
TAGS: bindata
|
||||
- name: unit-tests
|
||||
run: make unit-test-coverage test-check
|
||||
env:
|
||||
TAGS: bindata
|
||||
RACE_ENABLED: true
|
||||
GITHUB_READ_TOKEN: ${{ secrets.GITHUB_READ_TOKEN }}
|
||||
- name: unit-tests-gogit
|
||||
run: make unit-test-coverage test-check
|
||||
env:
|
||||
TAGS: bindata gogit
|
||||
RACE_ENABLED: true
|
||||
GITHUB_READ_TOKEN: ${{ secrets.GITHUB_READ_TOKEN }}
|
||||
|
||||
test-mysql5:
|
||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
services:
|
||||
mysql:
|
||||
image: mysql:5.7
|
||||
env:
|
||||
MYSQL_ALLOW_EMPTY_PASSWORD: yes
|
||||
MYSQL_DATABASE: test
|
||||
ports:
|
||||
- "3306:3306"
|
||||
elasticsearch:
|
||||
image: elasticsearch:7.5.0
|
||||
env:
|
||||
discovery.type: single-node
|
||||
ports:
|
||||
- "9200:9200"
|
||||
smtpimap:
|
||||
image: tabascoterrier/docker-imap-devel:latest
|
||||
ports:
|
||||
- "25:25"
|
||||
- "143:143"
|
||||
- "587:587"
|
||||
- "993:993"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: ">=1.20.0"
|
||||
- name: Add hosts to /etc/hosts
|
||||
run: '[ -e "/.dockerenv" ] || [ -e "/run/.containerenv" ] || echo "127.0.0.1 mysql elasticsearch smtpimap" | sudo tee -a /etc/hosts'
|
||||
- run: make deps-backend
|
||||
- run: make backend
|
||||
env:
|
||||
TAGS: bindata
|
||||
- name: run tests
|
||||
run: make test-mysql-migration integration-test-coverage
|
||||
env:
|
||||
TAGS: bindata
|
||||
RACE_ENABLED: true
|
||||
USE_REPO_TEST_DIR: 1
|
||||
TEST_INDEXER_CODE_ES_URL: "http://elastic:changeme@elasticsearch:9200"
|
||||
|
||||
test-mysql8:
|
||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
services:
|
||||
mysql8:
|
||||
image: mysql:8
|
||||
env:
|
||||
MYSQL_ALLOW_EMPTY_PASSWORD: yes
|
||||
MYSQL_DATABASE: testgitea
|
||||
ports:
|
||||
- "3306:3306"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: ">=1.20.0"
|
||||
- name: Add hosts to /etc/hosts
|
||||
run: '[ -e "/.dockerenv" ] || [ -e "/run/.containerenv" ] || echo "127.0.0.1 mysql8" | sudo tee -a /etc/hosts'
|
||||
- run: make deps-backend
|
||||
- run: make backend
|
||||
env:
|
||||
TAGS: bindata
|
||||
- run: make test-mysql8-migration test-mysql8
|
||||
timeout-minutes: 50
|
||||
env:
|
||||
TAGS: bindata
|
||||
USE_REPO_TEST_DIR: 1
|
||||
|
||||
test-mssql:
|
||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
services:
|
||||
mssql:
|
||||
image: mcr.microsoft.com/mssql/server:latest
|
||||
env:
|
||||
ACCEPT_EULA: Y
|
||||
MSSQL_PID: Standard
|
||||
SA_PASSWORD: MwantsaSecurePassword1
|
||||
ports:
|
||||
- "1433:1433"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: ">=1.20.0"
|
||||
- name: Add hosts to /etc/hosts
|
||||
run: '[ -e "/.dockerenv" ] || [ -e "/run/.containerenv" ] || echo "127.0.0.1 mssql" | sudo tee -a /etc/hosts'
|
||||
- run: make deps-backend
|
||||
- run: make backend
|
||||
env:
|
||||
TAGS: bindata
|
||||
- run: make test-mssql-migration test-mssql
|
||||
timeout-minutes: 50
|
||||
env:
|
||||
TAGS: bindata
|
||||
USE_REPO_TEST_DIR: 1
|
||||
@@ -1,23 +0,0 @@
|
||||
name: docker-dryrun
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
files-changed:
|
||||
uses: ./.github/workflows/files-changed.yml
|
||||
|
||||
docker-dryrun:
|
||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.frontend == 'true' || needs.files-changed.outputs.actions == 'true'
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: docker/setup-buildx-action@v2
|
||||
- uses: docker/build-push-action@v4
|
||||
with:
|
||||
push: false
|
||||
tags: gitea/gitea:linux-amd64
|
||||
@@ -1,32 +0,0 @@
|
||||
name: e2e-tests
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
files-changed:
|
||||
uses: ./.github/workflows/files-changed.yml
|
||||
|
||||
test-e2e:
|
||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.frontend == 'true' || needs.files-changed.outputs.actions == 'true'
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: ">=1.20"
|
||||
check-latest: true
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 20
|
||||
- run: make deps-frontend frontend deps-backend
|
||||
- run: npx playwright install --with-deps
|
||||
- run: make test-e2e-sqlite
|
||||
timeout-minutes: 40
|
||||
env:
|
||||
USE_REPO_TEST_DIR: 1
|
||||
@@ -1,92 +0,0 @@
|
||||
name: release-nightly-assets
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, release/v* ]
|
||||
|
||||
jobs:
|
||||
nightly-binary:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
||||
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
|
||||
- run: git fetch --unshallow --quiet --tags --force
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: ">=1.20"
|
||||
check-latest: true
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 20
|
||||
- run: make deps-frontend deps-backend
|
||||
# xgo build
|
||||
- run: make release
|
||||
env:
|
||||
TAGS: bindata sqlite sqlite_unlock_notify
|
||||
- name: import gpg key
|
||||
id: import_gpg
|
||||
uses: crazy-max/ghaction-import-gpg@v5
|
||||
with:
|
||||
gpg_private_key: ${{ secrets.GPGSIGN_KEY }}
|
||||
passphrase: ${{ secrets.GPGSIGN_PASSPHRASE }}
|
||||
- name: sign binaries
|
||||
run: |
|
||||
for f in dist/release/*; do
|
||||
echo '${{ secrets.GPGSIGN_PASSPHRASE }}' | gpg --pinentry-mode loopback --passphrase-fd 0 --batch --yes --detach-sign -u ${{ steps.import_gpg.outputs.fingerprint }} --output "$f.asc" "$f"
|
||||
done
|
||||
# clean branch name to get the folder name in S3
|
||||
- name: Get cleaned branch name
|
||||
id: clean_name
|
||||
run: |
|
||||
REF_NAME=$(echo "${{ github.ref }}" | sed -e 's/refs\/heads\///' -e 's/refs\/tags\///' -e 's/release\/v//')
|
||||
echo "Cleaned name is ${REF_NAME}"
|
||||
echo "branch=${REF_NAME}" >> "$GITHUB_OUTPUT"
|
||||
- name: upload binaries to s3
|
||||
uses: jakejarvis/s3-sync-action@master
|
||||
env:
|
||||
AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }}
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
AWS_REGION: ${{ secrets.AWS_REGION }}
|
||||
SOURCE_DIR: dist/release
|
||||
DEST_DIR: gitea/${{ steps.clean_name.outputs.branch }}
|
||||
nightly-docker:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
||||
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
|
||||
- run: git fetch --unshallow --quiet --tags --force
|
||||
- uses: docker/setup-qemu-action@v2
|
||||
- uses: docker/setup-buildx-action@v2
|
||||
- name: Get cleaned branch name
|
||||
id: clean_name
|
||||
run: |
|
||||
# if main then say nightly otherwise cleanup name
|
||||
if [ "${{ github.ref }}" = "refs/heads/main" ]; then
|
||||
echo "branch=nightly" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
REF_NAME=$(echo "${{ github.ref }}" | sed -e 's/refs\/heads\///' -e 's/refs\/tags\///' -e 's/release\/v//')
|
||||
echo "branch=${REF_NAME}-nightly" >> "$GITHUB_OUTPUT"
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: build rootful docker image
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: gitea/gitea:${{ steps.clean_name.outputs.branch }}
|
||||
- name: build rootless docker image
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
file: Dockerfile.rootless
|
||||
tags: gitea/gitea:${{ steps.clean_name.outputs.branch }}-rootless
|
||||
+7
-2
@@ -16,6 +16,10 @@ _test
|
||||
.vscode
|
||||
__debug_bin
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
@@ -43,7 +47,6 @@ cpu.out
|
||||
|
||||
*.db
|
||||
*.log
|
||||
*.log.*.gz
|
||||
|
||||
/gitea
|
||||
/gitea-vet
|
||||
@@ -53,6 +56,8 @@ cpu.out
|
||||
/bin
|
||||
/dist
|
||||
/custom/*
|
||||
!/custom/conf
|
||||
/custom/conf/*
|
||||
!/custom/conf/app.example.ini
|
||||
/data
|
||||
/indexers
|
||||
@@ -66,12 +71,12 @@ cpu.out
|
||||
/tests/e2e/test-artifacts
|
||||
/tests/e2e/test-snapshots
|
||||
/tests/*.ini
|
||||
/tests/**/*.git/**/*.sample
|
||||
/node_modules
|
||||
/yarn.lock
|
||||
/yarn-error.log
|
||||
/npm-debug.log*
|
||||
/public/js
|
||||
/public/serviceworker.js
|
||||
/public/css
|
||||
/public/fonts
|
||||
/public/img/webpack
|
||||
|
||||
+10
-7
@@ -10,12 +10,9 @@ tasks:
|
||||
- name: Run backend
|
||||
command: |
|
||||
gp sync-await setup
|
||||
if [ ! -f custom/conf/app.ini ]
|
||||
then
|
||||
mkdir -p custom/conf/
|
||||
echo -e "[server]\nROOT_URL=$(gp url 3000)/" > custom/conf/app.ini
|
||||
echo -e "\n[database]\nDB_TYPE = sqlite3\nPATH = $GITPOD_REPO_ROOT/data/gitea.db" >> custom/conf/app.ini
|
||||
fi
|
||||
mkdir -p custom/conf/
|
||||
echo -e "[server]\nROOT_URL=$(gp url 3000)/" > custom/conf/app.ini
|
||||
echo -e "\n[database]\nDB_TYPE = sqlite3\nPATH = $GITPOD_REPO_ROOT/data/gitea.db" >> custom/conf/app.ini
|
||||
export TAGS="sqlite sqlite_unlock_notify"
|
||||
make watch-backend
|
||||
- name: Run frontend
|
||||
@@ -23,6 +20,10 @@ tasks:
|
||||
gp sync-await setup
|
||||
make watch-frontend
|
||||
openMode: split-right
|
||||
- name: Run docs
|
||||
before: sudo bash -c "$(grep 'https://github.com/gohugoio/hugo/releases/download' Makefile | tr -d '\')" # install hugo
|
||||
command: cd docs && make clean update && hugo server -D -F --baseUrl $(gp url 1313) --liveReloadPort=443 --appendPort=false --bind=0.0.0.0
|
||||
openMode: split-right
|
||||
|
||||
vscode:
|
||||
extensions:
|
||||
@@ -31,7 +32,7 @@ vscode:
|
||||
- golang.go
|
||||
- stylelint.vscode-stylelint
|
||||
- DavidAnson.vscode-markdownlint
|
||||
- Vue.volar
|
||||
- johnsoncodehk.volar
|
||||
- ms-azuretools.vscode-docker
|
||||
- zixuanchen.vitest-explorer
|
||||
- alexcvzz.vscode-sqlite
|
||||
@@ -39,3 +40,5 @@ vscode:
|
||||
ports:
|
||||
- name: Gitea
|
||||
port: 3000
|
||||
- name: Docs
|
||||
port: 1313
|
||||
|
||||
+52
-6
@@ -5,7 +5,6 @@ linters:
|
||||
- depguard
|
||||
- dupl
|
||||
- errcheck
|
||||
- forbidigo
|
||||
- gocritic
|
||||
# - gocyclo # The cyclomatic complexety of a lot of functions is too high, we should refactor those another time.
|
||||
- gofmt
|
||||
@@ -23,7 +22,7 @@ linters:
|
||||
- unconvert
|
||||
- unused
|
||||
# - varcheck # deprecated - https://github.com/golangci/golangci-lint/issues/1841
|
||||
- wastedassign
|
||||
# - wastedassign # disabled - https://github.com/golangci/golangci-lint/issues/2649
|
||||
enable-all: false
|
||||
disable-all: true
|
||||
fast: false
|
||||
@@ -86,7 +85,6 @@ linters-settings:
|
||||
- io/ioutil: "use os or io instead"
|
||||
- golang.org/x/exp: "it's experimental and unreliable."
|
||||
- code.gitea.io/gitea/modules/git/internal: "do not use the internal package, use AddXxx function instead"
|
||||
- gopkg.in/ini.v1: "do not use the ini package, use gitea's config system instead"
|
||||
|
||||
issues:
|
||||
max-issues-per-linter: 0
|
||||
@@ -107,25 +105,73 @@ issues:
|
||||
- errcheck
|
||||
- dupl
|
||||
- gosec
|
||||
- path: cmd
|
||||
linters:
|
||||
- forbidigo
|
||||
- linters:
|
||||
- dupl
|
||||
text: "webhook"
|
||||
- linters:
|
||||
- gocritic
|
||||
text: "`ID' should not be capitalized"
|
||||
- path: modules/templates/helper.go
|
||||
linters:
|
||||
- gocritic
|
||||
- linters:
|
||||
- unused
|
||||
- deadcode
|
||||
text: "swagger"
|
||||
- path: contrib/pr/checkout.go
|
||||
linters:
|
||||
- errcheck
|
||||
- path: models/issue.go
|
||||
linters:
|
||||
- errcheck
|
||||
- path: models/migrations/
|
||||
linters:
|
||||
- errcheck
|
||||
- path: modules/log/
|
||||
linters:
|
||||
- errcheck
|
||||
- path: routers/api/v1/repo/issue_subscription.go
|
||||
linters:
|
||||
- dupl
|
||||
- path: routers/repo/view.go
|
||||
linters:
|
||||
- dupl
|
||||
- path: models/migrations/
|
||||
linters:
|
||||
- unused
|
||||
- linters:
|
||||
- staticcheck
|
||||
text: "argument x is overwritten before first use"
|
||||
- path: modules/httplib/httplib.go
|
||||
linters:
|
||||
- staticcheck
|
||||
# Enabling this would require refactoring the methods and how they are called.
|
||||
- path: models/issue_comment_list.go
|
||||
linters:
|
||||
- dupl
|
||||
- path: models/update.go
|
||||
linters:
|
||||
- unused
|
||||
- path: cmd/dump.go
|
||||
linters:
|
||||
- dupl
|
||||
- path: services/webhook/webhook.go
|
||||
linters:
|
||||
- structcheck
|
||||
- text: "commentFormatting: put a space between `//` and comment text"
|
||||
linters:
|
||||
- gocritic
|
||||
- text: "exitAfterDefer:"
|
||||
linters:
|
||||
- gocritic
|
||||
- path: modules/graceful/manager_windows.go
|
||||
linters:
|
||||
- staticcheck
|
||||
text: "svc.IsAnInteractiveSession is deprecated: Use IsWindowsService instead."
|
||||
- path: models/user/openid.go
|
||||
linters:
|
||||
- golint
|
||||
- path: models/user/badge.go
|
||||
linters:
|
||||
- revive
|
||||
text: "exported: type name will be used as user.UserBadge by other packages, and that stutters; consider calling this Badge"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
*.min.css
|
||||
*.min.js
|
||||
/assets/*.json
|
||||
/modules/options/bindata.go
|
||||
/modules/public/bindata.go
|
||||
/modules/templates/bindata.go
|
||||
/public/vendor/plugins
|
||||
/vendor
|
||||
node_modules
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
pattern = "(?)LGTM"
|
||||
self_approval_off = true
|
||||
ignore_maintainers_file = true
|
||||
@@ -3,4 +3,3 @@ fund=false
|
||||
update-notifier=false
|
||||
package-lock=true
|
||||
save-exact=true
|
||||
lockfile-version=3
|
||||
|
||||
+2
-6
@@ -5,14 +5,12 @@ ignoreFiles:
|
||||
- "**/*.go"
|
||||
|
||||
overrides:
|
||||
- files: ["**/chroma/*", "**/codemirror/*", "**/standalone/*", "**/console.css", "font_i18n.css"]
|
||||
- files: ["**/chroma/*", "**/codemirror/*", "**/standalone/*", "**/console/*"]
|
||||
rules:
|
||||
scale-unlimited/declaration-strict-value: null
|
||||
- files: ["**/chroma/*", "**/codemirror/*"]
|
||||
rules:
|
||||
block-no-empty: null
|
||||
- files: ["**/*.vue"]
|
||||
customSyntax: postcss-html
|
||||
|
||||
rules:
|
||||
alpha-value-notation: null
|
||||
@@ -80,7 +78,6 @@ rules:
|
||||
media-feature-name-no-vendor-prefix: true
|
||||
media-feature-name-unit-allowed-list: null
|
||||
media-feature-name-value-allowed-list: null
|
||||
media-feature-name-value-no-unknown: true
|
||||
media-feature-range-notation: null
|
||||
named-grid-areas-no-invalid: true
|
||||
no-descending-specificity: null
|
||||
@@ -91,7 +88,6 @@ rules:
|
||||
no-invalid-position-at-import-rule: null
|
||||
no-irregular-whitespace: true
|
||||
no-unknown-animations: null
|
||||
no-unknown-custom-properties: null
|
||||
number-max-precision: null
|
||||
property-allowed-list: null
|
||||
property-disallowed-list: null
|
||||
@@ -99,7 +95,7 @@ rules:
|
||||
property-no-vendor-prefix: null
|
||||
rule-empty-line-before: null
|
||||
rule-selector-property-disallowed-list: null
|
||||
scale-unlimited/declaration-strict-value: [[color, background-color, border-color, font-weight], {ignoreValues: /^(inherit|transparent|unset|initial|currentcolor|none)$/, ignoreFunctions: false, disableFix: true}]
|
||||
scale-unlimited/declaration-strict-value: [color, {ignoreValues: /^(inherit|transparent|unset|initial|currentcolor)$/}]
|
||||
selector-attribute-name-disallowed-list: null
|
||||
selector-attribute-operator-allowed-list: null
|
||||
selector-attribute-operator-disallowed-list: null
|
||||
|
||||
+13
-20
@@ -1,7 +1,6 @@
|
||||
# GNU makefile proxy script for BSD make
|
||||
#
|
||||
# Written and maintained by Mahmoud Al-Qudsi <mqudsi@neosmart.net>
|
||||
# Copyright NeoSmart Technologies <https://neosmart.net/> 2014-2019
|
||||
# Copyright NeoSmart Technologies <https://neosmart.net/> 2014-2018
|
||||
# Obtain updates from <https://github.com/neosmart/gmake-proxy>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
@@ -27,32 +26,26 @@
|
||||
|
||||
JARG =
|
||||
GMAKE = "gmake"
|
||||
# When gmake is called from another make instance, -w is automatically added
|
||||
# which causes extraneous messages about directory changes to be emitted.
|
||||
# Running with --no-print-directory silences these messages.
|
||||
#When gmake is called from another make instance, -w is automatically added
|
||||
#which causes extraneous messages about directory changes to be emitted.
|
||||
#--no-print-directory silences these messages.
|
||||
GARGS = "--no-print-directory"
|
||||
|
||||
.if "$(.MAKE.JOBS)" != ""
|
||||
JARG = -j$(.MAKE.JOBS)
|
||||
JARG = -j$(.MAKE.JOBS)
|
||||
.endif
|
||||
|
||||
# bmake prefers out-of-source builds and tries to cd into ./obj (among others)
|
||||
# where possible. GNU Make doesn't, so override that value.
|
||||
#by default bmake will cd into ./obj first
|
||||
.OBJDIR: ./
|
||||
|
||||
# The GNU convention is to use the lowercased `prefix` variable/macro to
|
||||
# specify the installation directory. Humor them.
|
||||
GPREFIX = ""
|
||||
.if defined(PREFIX) && ! defined(prefix)
|
||||
GPREFIX = 'prefix = "$(PREFIX)"'
|
||||
.endif
|
||||
|
||||
.BEGIN: .SILENT
|
||||
which $(GMAKE) || printf "Error: GNU Make is required!\n\n" 1>&2 && false
|
||||
|
||||
.PHONY: FRC
|
||||
$(.TARGETS): FRC
|
||||
$(GMAKE) $(GPREFIX) $(GARGS) $(.TARGETS:S,.DONE,,) $(JARG)
|
||||
$(GMAKE) $(GARGS) $(.TARGETS:S,.DONE,,) $(JARG)
|
||||
|
||||
.DONE .DEFAULT: .SILENT
|
||||
$(GMAKE) $(GPREFIX) $(GARGS) $(.TARGETS:S,.DONE,,) $(JARG)
|
||||
$(GMAKE) $(GARGS) $(.TARGETS:S,.DONE,,) $(JARG)
|
||||
|
||||
.ERROR: .SILENT
|
||||
if ! which $(GMAKE) > /dev/null; then \
|
||||
echo "GNU Make is required!"; \
|
||||
fi
|
||||
|
||||
+40
-1212
File diff suppressed because it is too large
Load Diff
@@ -1,96 +0,0 @@
|
||||
# Gitea Community Code of Conduct
|
||||
|
||||
## About
|
||||
|
||||
Online communities include people from many different backgrounds. The Gitea contributors are committed to providing a friendly, safe and welcoming environment for all, regardless of gender identity and expression, sexual orientation, disabilities, neurodiversity, physical appearance, body size, ethnicity, nationality, race, age, religion, or similar personal characteristics.
|
||||
|
||||
The first goal of the Code of Conduct is to specify a baseline standard of behavior so that people with different social values and communication styles can talk about Gitea effectively, productively, and respectfully.
|
||||
|
||||
The second goal is to provide a mechanism for resolving conflicts in the community when they arise.
|
||||
|
||||
The third goal of the Code of Conduct is to make our community welcoming to people from different backgrounds. Diversity is critical to the project; for Gitea to be successful, it needs contributors and users from all backgrounds.
|
||||
|
||||
We believe that healthy debate and disagreement are essential to a healthy project and community. However, it is never ok to be disrespectful. We value diverse opinions, but we value respectful behavior more.
|
||||
|
||||
## Community values
|
||||
|
||||
These are the values to which people in the Gitea community should aspire.
|
||||
|
||||
- **Be friendly and welcoming.**
|
||||
- **Be patient.**
|
||||
- Remember that people have varying communication styles and that not everyone is using their native language. (Meaning and tone can be lost in translation.)
|
||||
- **Be thoughtful.**
|
||||
- Productive communication requires effort. Think about how your words will be interpreted.
|
||||
- Remember that sometimes it is best to refrain entirely from commenting.
|
||||
- **Be respectful.**
|
||||
- In particular, respect differences of opinion.
|
||||
- **Be charitable.**
|
||||
- Interpret the arguments of others in good faith, do not seek to disagree.
|
||||
- When we do disagree, try to understand why.
|
||||
- **Be constructive.**
|
||||
- Avoid derailing: stay on topic; if you want to talk about something else, start a new conversation.
|
||||
- Avoid unconstructive criticism: don't merely decry the current state of affairs; offer—or at least solicit—suggestions as to how things may be improved.
|
||||
- Avoid snarking (pithy, unproductive, sniping comments)
|
||||
- Avoid discussing potentially offensive or sensitive issues; this all too often leads to unnecessary conflict.
|
||||
- Avoid microaggressions (brief and commonplace verbal, behavioral and environmental indignities that communicate hostile, derogatory or negative slights and insults to a person or group).
|
||||
- **Be responsible.**
|
||||
- What you say and do matters. Take responsibility for your words and actions, including their consequences, whether intended or otherwise.
|
||||
|
||||
People are complicated. You should expect to be misunderstood and to misunderstand others; when this inevitably occurs, resist the urge to be defensive or assign blame. Try not to take offense where no offense was intended. Give people the benefit of the doubt. Even if the intent was to provoke, do not rise to it. It is the responsibility of all parties to de-escalate conflict when it arises.
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
### Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
### Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment include:
|
||||
|
||||
- Using welcoming and inclusive language
|
||||
- Being respectful of differing viewpoints and experiences
|
||||
- Gracefully accepting constructive criticism
|
||||
- Focusing on what is best for the community
|
||||
- Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
- The use of sexualized language or imagery and unwelcome sexual attention or advances
|
||||
- Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
- Public or private harassment
|
||||
- Publishing others’ private information, such as a physical or electronic address, without explicit permission
|
||||
- Other conduct which could reasonably be considered inappropriate in a professional setting
|
||||
|
||||
### Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject: comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, as well as to ban (temporarily or permanently) any contributor for behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
### Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
|
||||
|
||||
This Code of Conduct also applies outside the project spaces when the Project Stewards have a reasonable belief that an individual’s behavior may have a negative impact on the project or its community.
|
||||
|
||||
### Conflict Resolution
|
||||
|
||||
We do not believe that all conflict is bad; healthy debate and disagreement often yield positive results. However, it is never okay to be disrespectful or to engage in behavior that violates the project’s code of conduct.
|
||||
|
||||
If you see someone violating the code of conduct, you are encouraged to address the behavior directly with those involved. Many issues can be resolved quickly and easily, and this gives people more control over the outcome of their dispute. If you are unable to resolve the matter for any reason, or if the behavior is threatening or harassing, report it. We are dedicated to providing an environment where participants feel welcome and safe.
|
||||
|
||||
Reports should be directed to the Gitea Project Stewards at conduct@gitea.com. It is the Project Stewards’ duty to receive and address reported violations of the code of conduct. They will then work with a committee consisting of representatives from the technical-oversight-committee.
|
||||
|
||||
We will investigate every complaint, but you may not receive a direct response. We will use our discretion in determining when and how to follow up on reported incidents, which may range from not taking action to permanent expulsion from the project and project-sponsored spaces. Under normal circumstances, we will notify the accused of the report and provide them an opportunity to discuss it before any action is taken. If there is a consensus between maintainers that such an endeavor would be useless (i.e. in case of an obvious spammer), we reserve the right to take action without notifying the accused first. The identity of the reporter will be omitted from the details of the report supplied to the accused. In potentially harmful situations, such as ongoing harassment or threats to anyone’s safety, we may take action without notice.
|
||||
|
||||
### Attribution
|
||||
|
||||
This Code of Conduct is adapted from the Contributor Covenant, version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
|
||||
|
||||
## Summary
|
||||
|
||||
- Treat everyone with respect and kindness.
|
||||
- Be thoughtful in how you communicate.
|
||||
- Don’t be destructive or inflammatory.
|
||||
- If you encounter an issue, please mail conduct@gitea.com.
|
||||
+269
-389
@@ -1,157 +1,75 @@
|
||||
# Contribution Guidelines
|
||||
|
||||
<details><summary>Table of Contents</summary>
|
||||
## Table of Contents
|
||||
|
||||
- [Contribution Guidelines](#contribution-guidelines)
|
||||
- [Table of Contents](#table-of-contents)
|
||||
- [Introduction](#introduction)
|
||||
- [Issues](#issues)
|
||||
- [How to report issues](#how-to-report-issues)
|
||||
- [Types of issues](#types-of-issues)
|
||||
- [Discuss your design before the implementation](#discuss-your-design-before-the-implementation)
|
||||
- [Building Gitea](#building-gitea)
|
||||
- [Dependencies](#dependencies)
|
||||
- [Backend](#backend)
|
||||
- [Frontend](#frontend)
|
||||
- [Design guideline](#design-guideline)
|
||||
- [Styleguide](#styleguide)
|
||||
- [Copyright](#copyright)
|
||||
- [Testing](#testing)
|
||||
- [Bug reports](#bug-reports)
|
||||
- [Discuss your design](#discuss-your-design)
|
||||
- [Testing redux](#testing-redux)
|
||||
- [Vendoring](#vendoring)
|
||||
- [Translation](#translation)
|
||||
- [Building Gitea](#building-gitea)
|
||||
- [Code review](#code-review)
|
||||
- [Pull request format](#pull-request-format)
|
||||
- [PR title and summary](#pr-title-and-summary)
|
||||
- [Milestone](#milestone)
|
||||
- [Labels](#labels)
|
||||
- [Breaking PRs](#breaking-prs)
|
||||
- [What is a breaking PR?](#what-is-a-breaking-pr)
|
||||
- [How to handle breaking PRs?](#how-to-handle-breaking-prs)
|
||||
- [Maintaining open PRs](#maintaining-open-prs)
|
||||
- [Getting PRs merged](#getting-prs-merged)
|
||||
- [Final call](#final-call)
|
||||
- [Commit messages](#commit-messages)
|
||||
- [PR Co-authors](#pr-co-authors)
|
||||
- [PRs targeting `main`](#prs-targeting-main)
|
||||
- [Backport PRs](#backport-prs)
|
||||
- [Documentation](#documentation)
|
||||
- [Styleguide](#styleguide)
|
||||
- [Design guideline](#design-guideline)
|
||||
- [API v1](#api-v1)
|
||||
- [GitHub API compatibility](#github-api-compatibility)
|
||||
- [Adding/Maintaining API routes](#addingmaintaining-api-routes)
|
||||
- [When to use what HTTP method](#when-to-use-what-http-method)
|
||||
- [Requirements for API routes](#requirements-for-api-routes)
|
||||
- [Backports and Frontports](#backports-and-frontports)
|
||||
- [What is backported?](#what-is-backported)
|
||||
- [How to backport?](#how-to-backport)
|
||||
- [Format of backport PRs](#format-of-backport-prs)
|
||||
- [Frontports](#frontports)
|
||||
- [Developer Certificate of Origin (DCO)](#developer-certificate-of-origin-dco)
|
||||
- [Release Cycle](#release-cycle)
|
||||
- [Maintainers](#maintainers)
|
||||
- [Technical Oversight Committee (TOC)](#technical-oversight-committee-toc)
|
||||
- [Current TOC members](#current-toc-members)
|
||||
- [Previous TOC/owners members](#previous-tocowners-members)
|
||||
- [Governance Compensation](#governance-compensation)
|
||||
- [TOC \& Working groups](#toc--working-groups)
|
||||
- [Roadmap](#roadmap)
|
||||
- [Owners](#owners)
|
||||
- [Versions](#versions)
|
||||
- [Releasing Gitea](#releasing-gitea)
|
||||
|
||||
</details>
|
||||
- [Copyright](#copyright)
|
||||
|
||||
## Introduction
|
||||
|
||||
This document explains how to contribute changes to the Gitea project. \
|
||||
It assumes you have followed the [installation instructions](https://docs.gitea.io/en-us/). \
|
||||
Sensitive security-related issues should be reported to [security@gitea.io](mailto:security@gitea.io).
|
||||
This document explains how to contribute changes to the Gitea project.
|
||||
It assumes you have followed the
|
||||
[installation instructions](https://docs.gitea.io/en-us/).
|
||||
Sensitive security-related issues should be reported to
|
||||
[security@gitea.io](mailto:security@gitea.io).
|
||||
|
||||
For configuring IDEs for Gitea development, see the [contributed IDE configurations](contrib/ide/).
|
||||
For configuring IDE or code editor to develop Gitea see [IDE and code editor configuration](contrib/ide/)
|
||||
|
||||
## Issues
|
||||
## Bug reports
|
||||
|
||||
### How to report issues
|
||||
Please search the issues on the issue tracker with a variety of keywords
|
||||
to ensure your bug is not already reported.
|
||||
|
||||
Please search the issues on the issue tracker with a variety of related keywords to ensure that your issue has not already been reported.
|
||||
If unique, [open an issue](https://github.com/go-gitea/gitea/issues/new)
|
||||
and answer the questions so we can understand and reproduce the
|
||||
problematic behavior.
|
||||
|
||||
If your issue has not been reported yet, [open an issue](https://github.com/go-gitea/gitea/issues/new)
|
||||
and answer the questions so we can understand and reproduce the problematic behavior. \
|
||||
Please write clear and concise instructions so that we can reproduce the behavior — even if it seems obvious. \
|
||||
The more detailed and specific you are, the faster we can fix the issue. \
|
||||
It is really helpful if you can reproduce your problem on a site running on the latest commits, i.e. <https://try.gitea.io>, as perhaps your problem has already been fixed on a current version. \
|
||||
Please follow the guidelines described in [How to Report Bugs Effectively](http://www.chiark.greenend.org.uk/~sgtatham/bugs.html) for your report.
|
||||
To show us that the issue you are having is in Gitea itself, please
|
||||
write clear, concise instructions so we can reproduce the behavior—
|
||||
even if it seems obvious. The more detailed and specific you are,
|
||||
the faster we can fix the issue. Check out [How to Report Bugs
|
||||
Effectively](http://www.chiark.greenend.org.uk/~sgtatham/bugs.html).
|
||||
|
||||
Please be kind, remember that Gitea comes at no cost to you, and you're getting free help.
|
||||
Please be kind, remember that Gitea comes at no cost to you, and you're
|
||||
getting free help.
|
||||
|
||||
### Types of issues
|
||||
## Discuss your design
|
||||
|
||||
Typically, issues fall in one of the following categories:
|
||||
The project welcomes submissions. If you want to change or add something,
|
||||
please let everyone know what you're working on—[file an issue](https://github.com/go-gitea/gitea/issues/new)!
|
||||
Significant changes must go through the change proposal process
|
||||
before they can be accepted. To create a proposal, file an issue with
|
||||
your proposed changes documented, and make sure to note in the title
|
||||
of the issue that it is a proposal.
|
||||
|
||||
- `bug`: Something in the frontend or backend behaves unexpectedly
|
||||
- `security issue`: bug that has serious implications such as leaking another users data. Please do not file such issues on the public tracker and send a mail to security@gitea.io instead
|
||||
- `feature`: Completely new functionality. You should describe this feature in enough detail that anyone who reads the issue can understand how it is supposed to be implemented
|
||||
- `enhancement`: An existing feature should get an upgrade
|
||||
- `refactoring`: Parts of the code base don't conform with other parts and should be changed to improve Gitea's maintainability
|
||||
This process gives everyone a chance to validate the design, helps
|
||||
prevent duplication of effort, and ensures that the idea fits inside
|
||||
the goals for the project and tools. It also checks that the design is
|
||||
sound before code is written; the code review tool is not the place for
|
||||
high-level discussions.
|
||||
|
||||
### Discuss your design before the implementation
|
||||
## Testing redux
|
||||
|
||||
We welcome submissions. \
|
||||
If you want to change or add something, please let everyone know what you're working on — [file an issue](https://github.com/go-gitea/gitea/issues/new) or comment on an existing one before starting your work!
|
||||
|
||||
Significant changes such as new features must go through the change proposal process before they can be accepted. \
|
||||
This is mainly to save yourself the trouble of implementing it, only to find out that your proposed implementation has some potential problems. \
|
||||
Furthermore, this process gives everyone a chance to validate the design, helps prevent duplication of effort, and ensures that the idea fits inside
|
||||
the goals for the project and tools.
|
||||
|
||||
Pull requests should not be the place for architecture discussions.
|
||||
|
||||
## Building Gitea
|
||||
|
||||
See the [development setup instructions](https://docs.gitea.com/development/hacking-on-gitea).
|
||||
|
||||
## Dependencies
|
||||
|
||||
### Backend
|
||||
|
||||
Go dependencies are managed using [Go Modules](https://golang.org/cmd/go/#hdr-Module_maintenance). \
|
||||
You can find more details in the [go mod documentation](https://go.dev/ref/mod) and the [Go Modules Wiki](https://github.com/golang/go/wiki/Modules).
|
||||
|
||||
Pull requests should only modify `go.mod` and `go.sum` where it is related to your change, be it a bugfix or a new feature. \
|
||||
Apart from that, these files should only be modified by Pull Requests whose only purpose is to update dependencies.
|
||||
|
||||
The `go.mod`, `go.sum` update needs to be justified as part of the PR description,
|
||||
and must be verified by the reviewers and/or merger to always reference
|
||||
an existing upstream commit.
|
||||
|
||||
### Frontend
|
||||
|
||||
For the frontend, we use [npm](https://www.npmjs.com/).
|
||||
|
||||
The same restrictions apply for frontend dependencies as for backend dependencies, with the exceptions that the files for it are `package.json` and `package-lock.json`, and that new versions must always reference an existing version.
|
||||
|
||||
## Design guideline
|
||||
|
||||
Depending on your change, please read the
|
||||
|
||||
- [backend development guideline](https://docs.gitea.com/contributing/guidelines-backend)
|
||||
- [frontend development guideline](https://docs.gitea.com/contributing/guidelines-frontend)
|
||||
- [refactoring guideline](https://docs.gitea.com/contributing/guidelines-refactoring)
|
||||
|
||||
## Styleguide
|
||||
|
||||
You should always run `make fmt` before committing to conform to Gitea's styleguide.
|
||||
|
||||
## Copyright
|
||||
|
||||
New code files that you contribute should use the standard copyright header:
|
||||
|
||||
```
|
||||
// Copyright <current year> The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
```
|
||||
|
||||
Afterwards, copyright should only be modified when the copyright author changes.
|
||||
|
||||
## Testing
|
||||
|
||||
Before submitting a pull request, run all tests to make sure your changes don't cause a regression elsewhere.
|
||||
Before submitting a pull request, run all the tests for the whole tree
|
||||
to make sure your changes don't cause regression elsewhere.
|
||||
|
||||
Here's how to run the test suite:
|
||||
|
||||
@@ -159,304 +77,257 @@ Here's how to run the test suite:
|
||||
|
||||
| | |
|
||||
| :-------------------- | :---------------------------------------------------------------- |
|
||||
|``make lint`` | lint everything (not needed if you only change the front- **or** backend) |
|
||||
|``make lint`` | lint everything (not suggest if you only change one type code) |
|
||||
|``make lint-frontend`` | lint frontend files |
|
||||
|``make lint-backend`` | lint backend files |
|
||||
|
||||
- run tests (we suggest running them on Linux)
|
||||
- run test code (Suggest run in Linux)
|
||||
|
||||
| Command | Action | |
|
||||
| :------------------------------------- | :----------------------------------------------- | ------------ |
|
||||
|``make test[\#SpecificTestName]`` | run unit test(s) |
|
||||
|``make test-sqlite[\#SpecificTestName]``| run [integration](tests/integration) test(s) for SQLite |[More details](tests/integration/README.md) |
|
||||
|``make test-e2e-sqlite[\#SpecificTestName]``| run [end-to-end](tests/e2e) test(s) for SQLite |[More details](tests/e2e/README.md) |
|
||||
| | |
|
||||
| :------------------------------------- | :----------------------------------------------- |
|
||||
|``make test[\#TestSpecificName]`` | run unit test |
|
||||
|``make test-sqlite[\#TestSpecificName]``| run [integration](tests/integration) test for SQLite |
|
||||
|[More details about integration tests](tests/integration/README.md) |
|
||||
|``make test-e2e-sqlite[\#TestSpecificFileName]``| run [end-to-end](tests/e2e) test for SQLite |
|
||||
|[More details about e2e tests](tests/e2e/README.md) |
|
||||
|
||||
## Vendoring
|
||||
|
||||
We manage dependencies via [Go Modules](https://golang.org/cmd/go/#hdr-Module_maintenance), more details: [go mod](https://go.dev/ref/mod).
|
||||
|
||||
Pull requests should only include `go.mod`, `go.sum` updates if they are part of
|
||||
the same change, be it a bugfix or a feature addition.
|
||||
|
||||
The `go.mod`, `go.sum` update needs to be justified as part of the PR description,
|
||||
and must be verified by the reviewers and/or merger to always reference
|
||||
an existing upstream commit.
|
||||
|
||||
You can find more information on how to get started with it on the [Modules Wiki](https://github.com/golang/go/wiki/Modules).
|
||||
|
||||
## Translation
|
||||
|
||||
All translation work happens on [Crowdin](https://crowdin.com/project/gitea).
|
||||
The only translation that is maintained in this repository is [the English translation](https://github.com/go-gitea/gitea/blob/main/options/locale/locale_en-US.ini).
|
||||
It is synced regularly with Crowdin. \
|
||||
Other locales on main branch **should not** be updated manually as they will be overwritten with each sync. \
|
||||
Once a language has reached a **satisfactory percentage** of translated keys (~25%), it will be synced back into this repo and included in the next released version.
|
||||
We do all translation work inside [Crowdin](https://crowdin.com/project/gitea).
|
||||
The only translation that is maintained in this Git repository is
|
||||
[`en_US.ini`](https://github.com/go-gitea/gitea/blob/main/options/locale/locale_en-US.ini)
|
||||
and is synced regularly to Crowdin. Once a translation has reached
|
||||
A SATISFACTORY PERCENTAGE it will be synced back into this repo and
|
||||
included in the next released version.
|
||||
|
||||
The tool `go run build/backport-locale.go` can be used to backport locales from the main branch to release branches that were missed.
|
||||
## Building Gitea
|
||||
|
||||
See the [hacking instructions](https://docs.gitea.io/en-us/hacking-on-gitea/).
|
||||
|
||||
## Code review
|
||||
|
||||
### Pull request format
|
||||
Changes to Gitea must be reviewed before they are accepted—no matter who
|
||||
makes the change, even if they are an owner or a maintainer. We use GitHub's
|
||||
pull request workflow to do that. And, we also use [LGTM](http://lgtm.co)
|
||||
to ensure every PR is reviewed by at least 2 maintainers.
|
||||
|
||||
Please try to make your pull request easy to review for us. \
|
||||
For that, please read the [*Best Practices for Faster Reviews*](https://github.com/kubernetes/community/blob/261cb0fd089b64002c91e8eddceebf032462ccd6/contributors/guide/pull-requests.md#best-practices-for-faster-reviews) guide. \
|
||||
It has lots of useful tips for any project you may want to contribute to. \
|
||||
Please try to make your pull request easy to review for us. And, please read
|
||||
the *[How to get faster PR reviews](https://github.com/kubernetes/community/blob/261cb0fd089b64002c91e8eddceebf032462ccd6/contributors/guide/pull-requests.md#best-practices-for-faster-reviews)* guide;
|
||||
it has lots of useful tips for any project you may want to contribute.
|
||||
Some of the key points:
|
||||
|
||||
- Make small pull requests. \
|
||||
The smaller, the faster to review and the more likely it will be merged soon.
|
||||
- Don't make changes unrelated to your PR. \
|
||||
Maybe there are typos on some comments, maybe refactoring would be welcome on a function... \
|
||||
but if that is not related to your PR, please make *another* PR for that.
|
||||
- Split big pull requests into multiple small ones. \
|
||||
An incremental change will be faster to review than a huge PR.
|
||||
- Allow edits by maintainers. This way, the maintainers will take care of merging the PR later on instead of you.
|
||||
- Make small pull requests. The smaller, the faster to review and the
|
||||
more likely it will be merged soon.
|
||||
- Don't make changes unrelated to your PR. Maybe there are typos on
|
||||
some comments, maybe refactoring would be welcome on a function... but
|
||||
if that is not related to your PR, please make *another* PR for that.
|
||||
- Split big pull requests into multiple small ones. An incremental change
|
||||
will be faster to review than a huge PR.
|
||||
- Use the first comment as a summary explainer of your PR and you should keep this up-to-date as the PR evolves.
|
||||
|
||||
### PR title and summary
|
||||
|
||||
In the PR title, describe the problem you are fixing, not how you are fixing it. \
|
||||
Use the first comment as a summary of your PR. \
|
||||
In the PR summary, you can describe exactly how you are fixing this problem. \
|
||||
Keep this summary up-to-date as the PR evolves. \
|
||||
If your PR changes the UI, you must add **after** screenshots in the PR summary. \
|
||||
If you are not implementing a new feature, you should also post **before** screenshots for comparison. \
|
||||
If your PR closes some issues, you must note that in a way that both GitHub and Gitea understand, i.e. by appending a paragraph like
|
||||
|
||||
```text
|
||||
Fixes/Closes/Resolves #<ISSUE_NR_X>.
|
||||
Fixes/Closes/Resolves #<ISSUE_NR_Y>.
|
||||
```
|
||||
|
||||
to your summary. \
|
||||
Each issue that will be closed must stand on a separate line.
|
||||
|
||||
### Milestone
|
||||
|
||||
A PR should only be assigned to a milestone if it will likely be merged into the given version. \
|
||||
As a rule of thumb, assume that a PR will stay open for an additional month for every 100 added lines. \
|
||||
PRs without a milestone may not be merged.
|
||||
|
||||
### Labels
|
||||
|
||||
Every PR should be labeled correctly with every label that applies. \
|
||||
This includes especially the distinction between `bug` (fixing existing functionality), `feature` (new functionality), `enhancement` (upgrades for existing functionality), and `refactoring` (improving the internal code structure without changing the output (much)). \
|
||||
Furthermore,
|
||||
|
||||
- the amount of pending required approvals
|
||||
- whether this PR is `blocked`, a `backport` or `breaking`
|
||||
- if it targets the `ui` or `api`
|
||||
- if it increases the application `speed`
|
||||
- reduces `memory usage`
|
||||
|
||||
are oftentimes notable labels.
|
||||
|
||||
### Breaking PRs
|
||||
|
||||
#### What is a breaking PR?
|
||||
|
||||
A PR is breaking if it meets one of the following criteria:
|
||||
|
||||
- It changes API output in an incompatible way for existing users
|
||||
- It removes a setting that an admin could previously set (i.e. via `app.ini`)
|
||||
- An admin must do something manually to restore the old behavior
|
||||
|
||||
In particular, this means that adding new settings is not breaking.\
|
||||
Changing the default value of a setting or replacing the setting with another one is breaking, however.
|
||||
|
||||
#### How to handle breaking PRs?
|
||||
|
||||
If your PR has a breaking change, you must add a `BREAKING` section to your PR summary, e.g.
|
||||
If your PR could cause a breaking change you must add a BREAKING section to this comment e.g.:
|
||||
|
||||
```
|
||||
## :warning: BREAKING :warning:
|
||||
```
|
||||
|
||||
To explain how this will affect users and how to mitigate these changes.
|
||||
To explain how this could affect users and how to mitigate these changes.
|
||||
|
||||
### Maintaining open PRs
|
||||
Once code review starts on your PR, do not rebase nor squash your branch as it makes it
|
||||
difficult to review the new changes. Only if there is a need, sync your branch by merging
|
||||
the base branch into yours. Don't worry about merge commits messing up your tree as
|
||||
the final merge process squashes all commits into one, with the visible commit message (first
|
||||
line) being the PR title + PR index and description being the PR's first comment.
|
||||
|
||||
The moment you create a non-draft PR or the moment you convert a draft PR to a non-draft PR is the moment code review starts for it. \
|
||||
Once that happens, do not rebase or squash your branch anymore as it makes it difficult to review the new changes. \
|
||||
Merge the base branch into your branch only when you really need to, i.e. because of conflicting changes in the mean time. \
|
||||
This reduces unnecessary CI runs. \
|
||||
Don't worry about merge commits messing up your commit history as every PR will be squash merged. \
|
||||
This means that all changes are joined into a single new commit whose message is as described below.
|
||||
Once your PR gets the `lgtm/done` label, don't worry about keeping it up-to-date or breaking
|
||||
builds (unless there's a merge conflict or a request is made by a maintainer to make
|
||||
modifications). It is the maintainer team's responsibility from this point to get it merged.
|
||||
|
||||
### Getting PRs merged
|
||||
## Styleguide
|
||||
|
||||
Changes to Gitea must be reviewed before they are accepted — no matter who
|
||||
makes the change, even if they are an owner or a maintainer. \
|
||||
The only exception are critical bugs that prevent Gitea from being compiled or started. \
|
||||
Specifically, we require two approvals from maintainers for every PR. \
|
||||
Once this criteria has been met, your PR receives the `lgtm/done` label. \
|
||||
From this point on, your only responsibility is to fix merge conflicts or respond to/implement requests by maintainers. \
|
||||
It is the responsibility of the maintainers from this point to get your PR merged.
|
||||
For imports you should use the following format (*without* the comments)
|
||||
|
||||
If a PR has the `lgtm/done` label and there are no open discussions or merge conflicts anymore, any maintainer can add the `reviewed/wait-merge` label. \
|
||||
This label means that the PR is part of the merge queue and will be merged as soon as possible. \
|
||||
The merge queue will be cleared in the order of the list below:
|
||||
```go
|
||||
import (
|
||||
// stdlib
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
<https://github.com/go-gitea/gitea/pulls?q=is%3Apr+label%3Areviewed%2Fwait-merge+sort%3Acreated-asc+is%3Aopen>
|
||||
// local packages
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/sdk/gitea"
|
||||
|
||||
Gitea uses it's own tool, the <https://github.com/GiteaBot/gitea-backporter> to automate parts of the review process. \
|
||||
This tool does the things listed below automatically:
|
||||
|
||||
- create a backport PR if needed once the initial PR was merged
|
||||
- remove the PR from the merge queue after the PR merged
|
||||
- keep the oldest branch in the merge queue up to date with merges
|
||||
|
||||
### Final call
|
||||
|
||||
If a PR has been ignored for more than 7 days with no comments or reviews, and the author or any maintainer believes it will not survive a long wait (such as a refactoring PR), they can send "final call" to the TOC by mentioning them in a comment.
|
||||
|
||||
After another 7 days, if there is still zero approval, this is considered a polite refusal, and the PR will be closed to avoid wasting further time. Therefore, the "final call" has a cost, and should be used cautiously.
|
||||
|
||||
However, if there are no objections from maintainers, the PR can be merged with only one approval from the TOC (not the author).
|
||||
|
||||
### Commit messages
|
||||
|
||||
Mergers are able and required to rewrite the PR title and summary (the first comment of a PR) so that it can produce an easily understandable commit message if necessary. \
|
||||
The final commit message should no longer contain any uncertainty such as `hopefully, <x> won't happen anymore`. Replace uncertainty with certainty.
|
||||
|
||||
#### PR Co-authors
|
||||
|
||||
A person counts as a PR co-author the moment they (co-)authored a commit that is not simply a `Merge base branch into branch` commit. \
|
||||
Mergers are required to remove such "false-positive" co-authors when writing the commit message. \
|
||||
The true co-authors must remain in the commit message.
|
||||
|
||||
#### PRs targeting `main`
|
||||
|
||||
The commit message of PRs targeting `main` is always
|
||||
|
||||
```bash
|
||||
$PR_TITLE ($PR_INDEX)
|
||||
|
||||
$REWRITTEN_PR_SUMMARY
|
||||
// external packages
|
||||
"github.com/foo/bar"
|
||||
"gopkg.io/baz.v1"
|
||||
)
|
||||
```
|
||||
|
||||
#### Backport PRs
|
||||
## Design guideline
|
||||
|
||||
The commit message of backport PRs is always
|
||||
To maintain understandable code and avoid circular dependencies it is important to have a good structure of the code. The Gitea code is divided into the following parts:
|
||||
|
||||
```bash
|
||||
$PR_TITLE ($INITIAL_PR_INDEX) ($BACKPORT_PR_INDEX)
|
||||
|
||||
$REWRITTEN_PR_SUMMARY
|
||||
```
|
||||
- **models:** Contains the data structures used by xorm to construct database tables. It also contains supporting functions to query and update the database. Dependencies to other code in Gitea should be avoided although some modules might be needed (for example for logging).
|
||||
- **models/fixtures:** Sample model data used in integration tests.
|
||||
- **models/migrations:** Handling of database migrations between versions. PRs that changes a database structure shall also have a migration step.
|
||||
- **modules:** Different modules to handle specific functionality in Gitea. Shall only depend on other modules but not other packages (models, services).
|
||||
- **public:** Frontend files (javascript, images, css, etc.)
|
||||
- **routers:** Handling of server requests. As it uses other Gitea packages to serve the request, other packages (models, modules or services) shall not depend on routers.
|
||||
- **services:** Support functions for common routing operations. Uses models and modules to handle the request.
|
||||
- **templates:** Golang templates for generating the html output.
|
||||
- **tests/e2e:** End to end tests
|
||||
- **tests/integration:** Integration tests
|
||||
- **tests/gitea-repositories-meta:** Sample repos used in integration tests. Adding a new repo requires editing `models/fixtures/repositories.yml` and `models/fixtures/repo_unit.yml` to match.
|
||||
- **tests/gitea-lfs-meta:** Sample LFS objects used in integration tests. Adding a new object requires editing `models/fixtures/lfs_meta_object.yml` to match.
|
||||
- **vendor:** External code that Gitea depends on.
|
||||
|
||||
## Documentation
|
||||
|
||||
If you add a new feature or change an existing aspect of Gitea, the documentation for that feature must be created or updated in the same PR.
|
||||
If you add a new feature or change an existing aspect of Gitea, the documentation for that feature must be created or updated.
|
||||
|
||||
## API v1
|
||||
|
||||
The API is documented by [swagger](http://try.gitea.io/api/swagger) and is based on [the GitHub API](https://docs.github.com/en/rest).
|
||||
The API is documented by [swagger](http://try.gitea.io/api/swagger) and is based on [GitHub API v3](https://developer.github.com/v3/).
|
||||
|
||||
### GitHub API compatibility
|
||||
Thus, Gitea´s API should use the same endpoints and fields as GitHub´s API as far as possible, unless there are good reasons to deviate.
|
||||
|
||||
Gitea's API should use the same endpoints and fields as the GitHub API as far as possible, unless there are good reasons to deviate. \
|
||||
If Gitea provides functionality that GitHub does not, a new endpoint can be created. \
|
||||
If information is provided by Gitea that is not provided by the GitHub API, a new field can be used that doesn't collide with any GitHub fields. \
|
||||
Updating an existing API should not remove existing fields unless there is a really good reason to do so. \
|
||||
The same applies to status responses. If you notice a problem, feel free to leave a comment in the code for future refactoring to API v2 (which is currently not planned).
|
||||
If Gitea provides functionality that GitHub does not, a new endpoint can be created.
|
||||
|
||||
### Adding/Maintaining API routes
|
||||
If information is provided by Gitea that is not provided by the GitHub API, a new field can be used that doesn't collide with any GitHub fields.
|
||||
|
||||
All expected results (errors, success, fail messages) must be documented ([example](https://github.com/go-gitea/gitea/blob/c620eb5b2d0d874da68ebd734d3864c5224f71f7/routers/api/v1/repo/issue.go#L319-L327)). \
|
||||
All JSON input types must be defined as a struct in [modules/structs/](modules/structs/) ([example](https://github.com/go-gitea/gitea/blob/c620eb5b2d0d874da68ebd734d3864c5224f71f7/modules/structs/issue.go#L76-L91)) \
|
||||
and referenced in [routers/api/v1/swagger/options.go](https://github.com/go-gitea/gitea/blob/c620eb5b2d0d874da68ebd734d3864c5224f71f7/routers/api/v1/swagger/options.go). \
|
||||
They can then be used like [this example](https://github.com/go-gitea/gitea/blob/c620eb5b2d0d874da68ebd734d3864c5224f71f7/routers/api/v1/repo/issue.go#L318). \
|
||||
All JSON responses must be defined as a struct in [modules/structs/](modules/structs/) ([example](https://github.com/go-gitea/gitea/blob/c620eb5b2d0d874da68ebd734d3864c5224f71f7/modules/structs/issue.go#L36-L68)) \
|
||||
and referenced in its category in [routers/api/v1/swagger/](routers/api/v1/swagger/) ([example](https://github.com/go-gitea/gitea/blob/c620eb5b2d0d874da68ebd734d3864c5224f71f7/routers/api/v1/swagger/issue.go#L11-L16)) \
|
||||
They can be used like [this example](https://github.com/go-gitea/gitea/blob/c620eb5b2d0d874da68ebd734d3864c5224f71f7/routers/api/v1/repo/issue.go#L277-L279).
|
||||
Updating an existing API should not remove existing fields unless there is a really good reason to do so.
|
||||
|
||||
### When to use what HTTP method
|
||||
The same applies to status responses. If you notice a problem, feel free to leave a comment in the code for future refactoring to APIv2 (which is currently not planned).
|
||||
|
||||
All expected results (errors, success, fail messages) should be documented
|
||||
([example](https://github.com/go-gitea/gitea/blob/c620eb5b2d0d874da68ebd734d3864c5224f71f7/routers/api/v1/repo/issue.go#L319-L327)).
|
||||
|
||||
All JSON input types must be defined as a struct in [modules/structs/](modules/structs/)
|
||||
([example](https://github.com/go-gitea/gitea/blob/c620eb5b2d0d874da68ebd734d3864c5224f71f7/modules/structs/issue.go#L76-L91))
|
||||
and referenced in
|
||||
[routers/api/v1/swagger/options.go](https://github.com/go-gitea/gitea/blob/c620eb5b2d0d874da68ebd734d3864c5224f71f7/routers/api/v1/swagger/options.go).
|
||||
|
||||
They can then be used like the following:
|
||||
([example](https://github.com/go-gitea/gitea/blob/c620eb5b2d0d874da68ebd734d3864c5224f71f7/routers/api/v1/repo/issue.go#L318)).
|
||||
|
||||
All JSON responses must be defined as a struct in [modules/structs/](modules/structs/)
|
||||
([example](https://github.com/go-gitea/gitea/blob/c620eb5b2d0d874da68ebd734d3864c5224f71f7/modules/structs/issue.go#L36-L68))
|
||||
and referenced in its category in [routers/api/v1/swagger/](routers/api/v1/swagger/)
|
||||
([example](https://github.com/go-gitea/gitea/blob/c620eb5b2d0d874da68ebd734d3864c5224f71f7/routers/api/v1/swagger/issue.go#L11-L16))
|
||||
|
||||
They can be used like the following:
|
||||
([example](https://github.com/go-gitea/gitea/blob/c620eb5b2d0d874da68ebd734d3864c5224f71f7/routers/api/v1/repo/issue.go#L277-L279))
|
||||
|
||||
In general, HTTP methods are chosen as follows:
|
||||
|
||||
- **GET** endpoints return the requested object(s) and status **OK (200)**
|
||||
- **DELETE** endpoints return the status **No Content (204)** and no content either
|
||||
- **POST** endpoints are used to **create** new objects (e.g. a User) and return the status **Created (201)** and the created object
|
||||
- **PUT** endpoints are used to **add/assign** existing Objects (e.g. a user to a team) and return the status **No Content (204)** and no content either
|
||||
- **PATCH** endpoints are used to **edit/change** an existing object and return the changed object and the status **OK (200)**
|
||||
- **GET** endpoints return requested object and status **OK (200)**
|
||||
- **DELETE** endpoints return status **No Content (204)**
|
||||
- **POST** endpoints return status **Created (201)**, used to **create** new objects (e.g. a User)
|
||||
- **PUT** endpoints return status **No Content (204)**, used to **add/assign** existing Objects (e.g. User) to something (e.g. Org-Team)
|
||||
- **PATCH** endpoints return changed object and status **OK (200)**, used to **edit/change** an existing object
|
||||
|
||||
### Requirements for API routes
|
||||
An endpoint which changes/edits an object expects all fields to be optional (except ones to identify the object, which are required).
|
||||
|
||||
All parameters of endpoints changing/editing an object must be optional (except the ones to identify the object, which are required).
|
||||
|
||||
Endpoints returning lists must
|
||||
### Endpoints returning lists should
|
||||
|
||||
- support pagination (`page` & `limit` options in query)
|
||||
- set `X-Total-Count` header via **SetTotalCountHeader** ([example](https://github.com/go-gitea/gitea/blob/7aae98cc5d4113f1e9918b7ee7dd09f67c189e3e/routers/api/v1/repo/issue.go#L444))
|
||||
|
||||
## Backports and Frontports
|
||||
|
||||
### What is backported?
|
||||
Occasionally backports of PRs are required.
|
||||
|
||||
We backport PRs given the following circumstances:
|
||||
|
||||
1. Feature freeze is active, but `<version>-rc0` has not been released yet. Here, we backport as much as possible. <!-- TODO: Is that our definition with the new backport bot? -->
|
||||
2. `rc0` has been released. Here, we only backport bug- and security-fixes, and small enhancements. Large PRs such as refactors are not backported anymore. <!-- TODO: Is that our definition with the new backport bot? -->
|
||||
3. We never backport new features.
|
||||
4. We never backport breaking changes except when
|
||||
1. The breaking change has no effect on the vast majority of users
|
||||
2. The component triggering the breaking change is marked as experimental
|
||||
|
||||
### How to backport?
|
||||
|
||||
In the past, it was necessary to manually backport your PRs. \
|
||||
Now, that's not a requirement anymore as our [backport bot](https://github.com/GiteaBot) tries to create backports automatically once the PR is merged when the PR
|
||||
|
||||
- does not have the label `backport/manual`
|
||||
- has the label `backport/<version>`
|
||||
|
||||
The `backport/manual` label signifies either that you want to backport the change yourself, or that there were conflicts when backporting, thus you **must** do it yourself.
|
||||
|
||||
### Format of backport PRs
|
||||
|
||||
The title of backport PRs should be
|
||||
The backported PR title should be:
|
||||
|
||||
```
|
||||
<original PR title> (#<original pr number>)
|
||||
Title of backported PR (#ORIGINAL_PR_NUMBER)
|
||||
```
|
||||
|
||||
The first two lines of the summary of the backporting PR should be
|
||||
The first two lines of the summary of the backporting PR should be:
|
||||
|
||||
```
|
||||
Backport #<original pr number>
|
||||
Backport #ORIGINAL_PR_NUMBER
|
||||
|
||||
```
|
||||
|
||||
with the rest of the summary and labels matching the original PR.
|
||||
with the rest of the summary matching the original PR. Similarly for frontports
|
||||
|
||||
### Frontports
|
||||
---
|
||||
|
||||
Frontports behave exactly as described above for backports.
|
||||
A command to help create backports can be found in `contrib/backport` and can be installed (from inside the gitea repo root directory) using:
|
||||
|
||||
```bash
|
||||
go install contrib/backport/backport.go
|
||||
```
|
||||
|
||||
## Developer Certificate of Origin (DCO)
|
||||
|
||||
We consider the act of contributing to the code by submitting a Pull Request as the "Sign off" or agreement to the certifications and terms of the [DCO](DCO) and [MIT license](LICENSE). \
|
||||
No further action is required. \
|
||||
You can also decide to sign off your commits by adding the following line at the end of your commit messages:
|
||||
We consider the act of contributing to the code by submitting a Pull
|
||||
Request as the "Sign off" or agreement to the certifications and terms
|
||||
of the [DCO](DCO) and [MIT license](LICENSE). No further action is required.
|
||||
Additionally you could add a line at the end of your commit message.
|
||||
|
||||
```
|
||||
Signed-off-by: Joe Smith <joe.smith@email.com>
|
||||
```
|
||||
|
||||
If you set the `user.name` and `user.email` Git config options, you can add the line to the end of your commits automatically with `git commit -s`.
|
||||
If you set your `user.name` and `user.email` Git configs, you can add the
|
||||
line to the end of your commit automatically with `git commit -s`.
|
||||
|
||||
We assume in good faith that the information you provide is legally binding.
|
||||
|
||||
## Release Cycle
|
||||
|
||||
We adopted a release schedule to streamline the process of working on, finishing, and issuing releases. \
|
||||
The overall goal is to make a major release every three or four months, which breaks down into two or three months of general development followed by one month of testing and polishing known as the release freeze. \
|
||||
All the feature pull requests should be
|
||||
We adopted a release schedule to streamline the process of working
|
||||
on, finishing, and issuing releases. The overall goal is to make a
|
||||
minor release every three or four months, which breaks down into two or three months of
|
||||
general development followed by one month of testing and polishing
|
||||
known as the release freeze. All the feature pull requests should be
|
||||
merged before feature freeze. And, during the frozen period, a corresponding
|
||||
release branch is open for fixes backported from main branch. Release candidates
|
||||
are made during this period for user testing to
|
||||
obtain a final version that is maintained in this branch.
|
||||
|
||||
Major release cycles are seasonal. They always begin on the 25th and end on
|
||||
the 24th (i.e., the 25th of December to March 24th).
|
||||
|
||||
During a development cycle, we may also publish any necessary minor releases
|
||||
for the previous version. For example, if the latest, published release is
|
||||
v1.2, then minor changes for the previous release—e.g., v1.1.0 -> v1.1.1—are
|
||||
still possible.
|
||||
|
||||
The previous release gets fixes for:
|
||||
|
||||
- Security issues
|
||||
- Critical bugs
|
||||
- Regressions
|
||||
- Build issues
|
||||
- Necessary enhancements (including necessary UI/UX fixes)
|
||||
|
||||
The backported fixes should avoid breaking downgrade between minor releases as much as possible.
|
||||
|
||||
## Maintainers
|
||||
|
||||
To make sure every PR is checked, we have [maintainers](MAINTAINERS). \
|
||||
Every PR **must** be reviewed by at least two maintainers (or owners) before it can get merged. \
|
||||
For refactoring PRs after a week and documentation only PRs, the approval of only one maintainer is enough. \
|
||||
A maintainer should be a contributor of Gitea and contributed at least
|
||||
To make sure every PR is checked, we have [team
|
||||
maintainers](MAINTAINERS). Every PR **MUST** be reviewed by at least
|
||||
two maintainers (or owners) before it can get merged. A maintainer
|
||||
should be a contributor of Gitea (or Gogs) and contributed at least
|
||||
4 accepted PRs. A contributor should apply as a maintainer in the
|
||||
[Discord](https://discord.gg/Gitea) `#develop` channel. The team maintainers may invite the contributor. A maintainer
|
||||
[Discord](https://discord.gg/NsatcWJ) #develop channel. The owners
|
||||
or the team maintainers may invite the contributor. A maintainer
|
||||
should spend some time on code reviews. If a maintainer has no
|
||||
time to do that, they should apply to leave the maintainers team
|
||||
and we will give them the honor of being a member of the [advisors
|
||||
@@ -470,74 +341,69 @@ if possible provide GPG signed commits.
|
||||
https://help.github.com/articles/securing-your-account-with-two-factor-authentication-2fa/
|
||||
https://help.github.com/articles/signing-commits-with-gpg/
|
||||
|
||||
## Technical Oversight Committee (TOC)
|
||||
## Owners
|
||||
|
||||
At the start of 2023, the `Owners` team was dissolved. Instead, the governance charter proposed a technical oversight committee (TOC) which expands the ownership team of the Gitea project from three elected positions to six positions. Three positions would be elected as it has been over the past years, and the other three would consist of appointed members from the Gitea company.
|
||||
https://blog.gitea.io/2023/02/gitea-quarterly-report-23q1/
|
||||
|
||||
When the new community members have been elected, the old members will give up ownership to the newly elected members. For security reasons, TOC members or any account with write access (like a bot) must use 2FA.
|
||||
Since Gitea is a pure community organization without any company support,
|
||||
to keep the development healthy we will elect three owners every year. All
|
||||
contributors may vote to elect up to three candidates, one of which will
|
||||
be the main owner, and the other two the assistant owners. When the new
|
||||
owners have been elected, the old owners will give up ownership to the
|
||||
newly elected owners. If an owner is unable to do so, the other owners
|
||||
will assist in ceding ownership to the newly elected owners.
|
||||
For security reasons, Owners or any account with write access (like a bot)
|
||||
must use 2FA.
|
||||
https://help.github.com/articles/securing-your-account-with-two-factor-authentication-2fa/
|
||||
|
||||
### Current TOC members
|
||||
After the election, the new owners should proactively agree
|
||||
with our [CONTRIBUTING](CONTRIBUTING.md) requirements in the
|
||||
[Discord](https://discord.gg/NsatcWJ) #general channel. Below are the
|
||||
words to speak:
|
||||
|
||||
- 2023-01-01 ~ 2023-12-31 - https://blog.gitea.io/2023/02/gitea-quarterly-report-23q1/
|
||||
- Company
|
||||
- [Jason Song](https://gitea.com/wolfogre) <i@wolfogre.com>
|
||||
- [Lunny Xiao](https://gitea.com/lunny) <xiaolunwen@gmail.com>
|
||||
- [Matti Ranta](https://gitea.com/techknowlogick) <techknowlogick@gitea.io>
|
||||
- Community
|
||||
- [6543](https://gitea.com/6543) <6543@obermui.de>
|
||||
- [Andrew Thornton](https://gitea.com/zeripath) <art27@cantab.net>
|
||||
- [John Olheiser](https://gitea.com/jolheiser) <john.olheiser@gmail.com>
|
||||
```
|
||||
I'm honored to having been elected an owner of Gitea, I agree with
|
||||
[CONTRIBUTING](CONTRIBUTING.md). I will spend part of my time on Gitea
|
||||
and lead the development of Gitea.
|
||||
```
|
||||
|
||||
### Previous TOC/owners members
|
||||
To honor the past owners, here's the history of the owners and the time
|
||||
they served:
|
||||
|
||||
Here's the history of the owners and the time they served:
|
||||
- 2022-01-01 ~ 2022-12-31 - https://github.com/go-gitea/gitea/issues/17872
|
||||
- [Lunny Xiao](https://gitea.com/lunny) <xiaolunwen@gmail.com>
|
||||
- [Matti Ranta](https://gitea.com/techknowlogick) <techknowlogick@gitea.io>
|
||||
- [Andrew Thornton](https://gitea.com/zeripath) <art27@cantab.net>
|
||||
|
||||
- [Lunny Xiao](https://gitea.com/lunny) - 2016, 2017, [2018](https://github.com/go-gitea/gitea/issues/3255), [2019](https://github.com/go-gitea/gitea/issues/5572), [2020](https://github.com/go-gitea/gitea/issues/9230), [2021](https://github.com/go-gitea/gitea/issues/13801), [2022](https://github.com/go-gitea/gitea/issues/17872)
|
||||
- [Kim Carlbäcker](https://github.com/bkcsoft) - 2016, 2017
|
||||
- [Thomas Boerger](https://gitea.com/tboerger) - 2016, 2017
|
||||
- [Lauris Bukšis-Haberkorns](https://gitea.com/lafriks) - [2018](https://github.com/go-gitea/gitea/issues/3255), [2019](https://github.com/go-gitea/gitea/issues/5572), [2020](https://github.com/go-gitea/gitea/issues/9230), [2021](https://github.com/go-gitea/gitea/issues/13801)
|
||||
- [Matti Ranta](https://gitea.com/techknowlogick) - [2019](https://github.com/go-gitea/gitea/issues/5572), [2020](https://github.com/go-gitea/gitea/issues/9230), [2021](https://github.com/go-gitea/gitea/issues/13801), [2022](https://github.com/go-gitea/gitea/issues/17872)
|
||||
- [Andrew Thornton](https://gitea.com/zeripath) - [2020](https://github.com/go-gitea/gitea/issues/9230), [2021](https://github.com/go-gitea/gitea/issues/13801), [2022](https://github.com/go-gitea/gitea/issues/17872)
|
||||
- 2021-01-01 ~ 2021-12-31 - https://github.com/go-gitea/gitea/issues/13801
|
||||
- [Lunny Xiao](https://gitea.com/lunny) <xiaolunwen@gmail.com>
|
||||
- [Lauris Bukšis-Haberkorns](https://gitea.com/lafriks) <lauris@nix.lv>
|
||||
- [Matti Ranta](https://gitea.com/techknowlogick) <techknowlogick@gitea.io>
|
||||
|
||||
## Governance Compensation
|
||||
- 2020-01-01 ~ 2020-12-31 - https://github.com/go-gitea/gitea/issues/9230
|
||||
- [Lunny Xiao](https://gitea.com/lunny) <xiaolunwen@gmail.com>
|
||||
- [Lauris Bukšis-Haberkorns](https://gitea.com/lafriks) <lauris@nix.lv>
|
||||
- [Matti Ranta](https://gitea.com/techknowlogick) <techknowlogick@gitea.io>
|
||||
|
||||
Each member of the community elected TOC will be granted $500 each month as compensation for their work.
|
||||
- 2019-01-01 ~ 2019-12-31 - https://github.com/go-gitea/gitea/issues/5572
|
||||
- [Lunny Xiao](https://github.com/lunny) <xiaolunwen@gmail.com>
|
||||
- [Lauris Bukšis-Haberkorns](https://github.com/lafriks) <lauris@nix.lv>
|
||||
- [Matti Ranta](https://github.com/techknowlogick) <techknowlogick@gitea.io>
|
||||
|
||||
Furthermore, any community release manager for a specific release or LTS will be compensated $500 for the delivery of said release.
|
||||
- 2018-01-01 ~ 2018-12-31 - https://github.com/go-gitea/gitea/issues/3255
|
||||
- [Lunny Xiao](https://github.com/lunny) <xiaolunwen@gmail.com>
|
||||
- [Lauris Bukšis-Haberkorns](https://github.com/lafriks) <lauris@nix.lv>
|
||||
- [Kim Carlbäcker](https://github.com/bkcsoft) <kim.carlbacker@gmail.com>
|
||||
|
||||
These funds will come from community sources like the OpenCollective rather than directly from the company.
|
||||
Only non-company members are eligible for this compensation, and if a member of the community TOC takes the responsibility of release manager, they would only be compensated for their TOC duties.
|
||||
Gitea Ltd employees are not eligible to receive any funds from the OpenCollective unless it is reimbursement for a purchase made for the Gitea project itself.
|
||||
|
||||
## TOC & Working groups
|
||||
|
||||
With Gitea covering many projects outside of the main repository, several groups will be created to help focus on specific areas instead of requiring maintainers to be a jack-of-all-trades. Maintainers are of course more than welcome to be part of multiple groups should they wish to contribute in multiple places.
|
||||
|
||||
The currently proposed groups are:
|
||||
|
||||
- **Core Group**: maintain the primary Gitea repository
|
||||
- **Integration Group**: maintain the Gitea ecosystem's related tools, including go-sdk/tea/changelog/bots etc.
|
||||
- **Documentation Group**: maintain related documents and repositories
|
||||
- **Translation Group**: coordinate with translators and maintain translations
|
||||
- **Security Group**: managed by TOC directly, members are decided by TOC, maintains security patches/responsible for security items
|
||||
|
||||
## Roadmap
|
||||
|
||||
Each year a roadmap will be discussed with the entire Gitea maintainers team, and feedback will be solicited from various stakeholders.
|
||||
TOC members need to review the roadmap every year and work together on the direction of the project.
|
||||
|
||||
When a vote is required for a proposal or other change, the vote of community elected TOC members count slightly more than the vote of company elected TOC members. With this approach, we both avoid ties and ensure that changes align with the mission statement and community opinion.
|
||||
|
||||
You can visit our roadmap on the wiki.
|
||||
- 2016-11-04 ~ 2017-12-31
|
||||
- [Lunny Xiao](https://github.com/lunny) <xiaolunwen@gmail.com>
|
||||
- [Thomas Boerger](https://github.com/tboerger) <thomas@webhippie.de>
|
||||
- [Kim Carlbäcker](https://github.com/bkcsoft) <kim.carlbacker@gmail.com>
|
||||
|
||||
## Versions
|
||||
|
||||
Gitea has the `main` branch as a tip branch and has version branches
|
||||
such as `release/v1.19`. `release/v1.19` is a release branch and we will
|
||||
tag `v1.19.0` for binary download. If `v1.19.0` has bugs, we will accept
|
||||
pull requests on the `release/v1.19` branch and publish a `v1.19.1` tag,
|
||||
such as `release/v0.9`. `release/v0.9` is a release branch and we will
|
||||
tag `v0.9.0` for binary download. If `v0.9.0` has bugs, we will accept
|
||||
pull requests on the `release/v0.9` branch and publish a `v0.9.1` tag,
|
||||
after bringing the bug fix also to the main branch.
|
||||
|
||||
Since the `main` branch is a tip version, if you wish to use Gitea
|
||||
@@ -557,7 +423,21 @@ be reviewed by two maintainers and must pass the automatic tests.
|
||||
- And then push the tag as `git push origin v$vmaj.$vmin.$`. Drone CI will automatically create a release and upload all the compiled binary. (But currently it doesn't add the release notes automatically. Maybe we should fix that.)
|
||||
- If needed send a frontport PR for the changelog to branch `main` and update the version in `docs/config.yaml` to refer to the new version.
|
||||
- Send PR to [blog repository](https://gitea.com/gitea/blog) announcing the release.
|
||||
- Verify all release assets were correctly published through CI on dl.gitea.com and GitHub releases. Once ACKed:
|
||||
- bump the version of https://dl.gitea.com/gitea/version.json
|
||||
- Verify all release assets were correctly published through CI on dl.gitea.io and GitHub releases. Once ACKed:
|
||||
- bump the version of https://dl.gitea.io/gitea/version.json
|
||||
- merge the blog post PR
|
||||
- announce the release in discord `#announcements`
|
||||
|
||||
## Copyright
|
||||
|
||||
Code that you contribute should use the standard copyright header:
|
||||
|
||||
```
|
||||
// Copyright <year> The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
```
|
||||
|
||||
Files in the repository contain copyright from the year they are added
|
||||
to the year they are last changed. If the copyright author is changed,
|
||||
just paste the header below the old one.
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
#Build stage
|
||||
FROM docker.io/library/golang:1.20-alpine3.18 AS build-env
|
||||
FROM docker.io/library/golang:1.20-alpine3.17 AS build-env
|
||||
|
||||
ARG GOPROXY
|
||||
ENV GOPROXY ${GOPROXY:-direct}
|
||||
@@ -23,7 +23,7 @@ RUN if [ -n "${GITEA_VERSION}" ]; then git checkout "${GITEA_VERSION}"; fi \
|
||||
# Begin env-to-ini build
|
||||
RUN go build contrib/environment-to-ini/environment-to-ini.go
|
||||
|
||||
FROM docker.io/library/alpine:3.18
|
||||
FROM docker.io/library/alpine:3.17
|
||||
LABEL maintainer="maintainers@gitea.io"
|
||||
|
||||
EXPOSE 22 3000
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
#Build stage
|
||||
FROM docker.io/library/golang:1.20-alpine3.18 AS build-env
|
||||
FROM docker.io/library/golang:1.20-alpine3.17 AS build-env
|
||||
|
||||
ARG GOPROXY
|
||||
ENV GOPROXY ${GOPROXY:-direct}
|
||||
@@ -23,7 +23,7 @@ RUN if [ -n "${GITEA_VERSION}" ]; then git checkout "${GITEA_VERSION}"; fi \
|
||||
# Begin env-to-ini build
|
||||
RUN go build contrib/environment-to-ini/environment-to-ini.go
|
||||
|
||||
FROM docker.io/library/alpine:3.18
|
||||
FROM docker.io/library/alpine:3.17
|
||||
LABEL maintainer="maintainers@gitea.io"
|
||||
|
||||
EXPOSE 2222 3000
|
||||
|
||||
+5
-7
@@ -5,6 +5,7 @@ Kees de Vries <bouwko@gmail.com> (@Bwko)
|
||||
Kim Carlbäcker <kim.carlbacker@gmail.com> (@bkcsoft)
|
||||
LefsFlare <nobody@nobody.tld> (@LefsFlarey)
|
||||
Lunny Xiao <xiaolunwen@gmail.com> (@lunny)
|
||||
Matthias Loibl <mail@matthiasloibl.com> (@metalmatze)
|
||||
Rachid Zarouali <nobody@nobody.tld> (@xinity)
|
||||
Rémy Boulanouar <admin@dblk.org> (@DblK)
|
||||
Sandro Santilli <strk@kbt.io> (@strk)
|
||||
@@ -41,14 +42,11 @@ Patrick Schratz <patrick.schratz@gmail.com> (@pat-s)
|
||||
Janis Estelmann <admin@oldschoolhack.me> (@KN4CK3R)
|
||||
Steven Kriegler <sk.bunsenbrenner@gmail.com> (@justusbunsi)
|
||||
Jimmy Praet <jimmy.praet@telenet.be> (@jpraet)
|
||||
Leon Hofmeister <dev.lh@web.de> (@delvh)
|
||||
Leon Hofmeister <dev.lh@web.de> (@delvh)
|
||||
Wim <wim@42.be> (@42wim)
|
||||
Xinyu Zhou <i@sourcehut.net> (@xin-u)
|
||||
Jason Song <i@wolfogre.com> (@wolfogre)
|
||||
Yarden Shoham <git@yardenshoham.com> (@yardenshoham)
|
||||
Yarden Shoham <hrsi88@gmail.com> (@yardenshoham)
|
||||
Yu Tian <zettat123@gmail.com> (@Zettat123)
|
||||
Eddie Yang <576951401@qq.com> (@yp05327)
|
||||
Dong Ge <gedong_1994@163.com> (@sillyguodong)
|
||||
Xinyi Gong <hestergong@gmail.com> (@HesterG)
|
||||
wxiaoguang <wxiaoguang@gmail.com> (@wxiaoguang)
|
||||
Gary Moon <gary@garymoon.net> (@garymoon)
|
||||
Philip Peterson <philip.c.peterson@gmail.com> (@philip-peterson)
|
||||
Dong Ge <gedong_1994@163.com> (@sillyguodong)
|
||||
@@ -20,28 +20,28 @@ IMPORT := code.gitea.io/gitea
|
||||
|
||||
GO ?= go
|
||||
SHASUM ?= shasum -a 256
|
||||
HAS_GO := $(shell hash $(GO) > /dev/null 2>&1 && echo yes)
|
||||
HAS_GO = $(shell hash $(GO) > /dev/null 2>&1 && echo "GO" || echo "NOGO" )
|
||||
COMMA := ,
|
||||
|
||||
XGO_VERSION := go-1.20.x
|
||||
|
||||
AIR_PACKAGE ?= github.com/cosmtrek/air@v1.43.0
|
||||
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/cmd/editorconfig-checker@2.7.0
|
||||
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.5.0
|
||||
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.52.2
|
||||
GXZ_PAGAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.11
|
||||
AIR_PACKAGE ?= github.com/cosmtrek/air@v1.40.4
|
||||
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/cmd/editorconfig-checker@2.6.0
|
||||
ERRCHECK_PACKAGE ?= github.com/kisielk/errcheck@v1.6.2
|
||||
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.4.0
|
||||
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.51.0
|
||||
GXZ_PAGAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.10
|
||||
MISSPELL_PACKAGE ?= github.com/client9/misspell/cmd/misspell@v0.3.4
|
||||
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.30.4
|
||||
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.30.3
|
||||
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
|
||||
GO_LICENSES_PACKAGE ?= github.com/google/go-licenses@v1.6.0
|
||||
GO_LICENSES_PACKAGE ?= github.com/google/go-licenses@v1.5.0
|
||||
GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@latest
|
||||
ACTIONLINT_PACKAGE ?= github.com/rhysd/actionlint/cmd/actionlint@latest
|
||||
|
||||
DOCKER_IMAGE ?= gitea/gitea
|
||||
DOCKER_TAG ?= latest
|
||||
DOCKER_REF := $(DOCKER_IMAGE):$(DOCKER_TAG)
|
||||
|
||||
ifeq ($(HAS_GO), yes)
|
||||
ifeq ($(HAS_GO), GO)
|
||||
GOPATH ?= $(shell $(GO) env GOPATH)
|
||||
export PATH := $(GOPATH)/bin:$(PATH)
|
||||
|
||||
@@ -79,21 +79,12 @@ endif
|
||||
STORED_VERSION_FILE := VERSION
|
||||
HUGO_VERSION ?= 0.111.3
|
||||
|
||||
GITHUB_REF_TYPE ?= branch
|
||||
GITHUB_REF_NAME ?= $(shell git rev-parse --abbrev-ref HEAD)
|
||||
|
||||
# backwards compatible to build with Drone
|
||||
ifneq ($(DRONE_TAG),)
|
||||
GITHUB_REF_TYPE := tag
|
||||
GITHUB_REF_NAME := $(DRONE_TAG)
|
||||
endif
|
||||
|
||||
ifneq ($(GITHUB_REF_TYPE),branch)
|
||||
VERSION ?= $(subst v,,$(GITHUB_REF_NAME))
|
||||
VERSION ?= $(subst v,,$(DRONE_TAG))
|
||||
GITEA_VERSION ?= $(VERSION)
|
||||
else
|
||||
ifneq ($(GITHUB_REF_NAME),)
|
||||
VERSION ?= $(subst release/v,,$(GITHUB_REF_NAME))
|
||||
ifneq ($(DRONE_BRANCH),)
|
||||
VERSION ?= $(subst release/v,,$(DRONE_BRANCH))
|
||||
else
|
||||
VERSION ?= main
|
||||
endif
|
||||
@@ -123,7 +114,7 @@ FOMANTIC_WORK_DIR := web_src/fomantic
|
||||
WEBPACK_SOURCES := $(shell find web_src/js web_src/css -type f)
|
||||
WEBPACK_CONFIGS := webpack.config.js
|
||||
WEBPACK_DEST := public/js/index.js public/css/index.css
|
||||
WEBPACK_DEST_ENTRIES := public/js public/css public/fonts public/img/webpack
|
||||
WEBPACK_DEST_ENTRIES := public/js public/css public/fonts public/img/webpack public/serviceworker.js
|
||||
|
||||
BINDATA_DEST := modules/public/bindata.go modules/options/bindata.go modules/templates/bindata.go
|
||||
BINDATA_HASH := $(addsuffix .hash,$(BINDATA_DEST))
|
||||
@@ -145,7 +136,7 @@ TEST_TAGS ?= sqlite sqlite_unlock_notify
|
||||
|
||||
TAR_EXCLUDES := .git data indexers queues log node_modules $(EXECUTABLE) $(FOMANTIC_WORK_DIR)/node_modules $(DIST) $(MAKE_EVIDENCE_DIR) $(AIR_TMP_DIR) $(GO_LICENSE_TMP_DIR)
|
||||
|
||||
GO_DIRS := build cmd models modules routers services tests
|
||||
GO_DIRS := cmd tests models modules routers build services tools
|
||||
WEB_DIRS := web_src/js web_src/css
|
||||
|
||||
GO_SOURCES := $(wildcard *.go)
|
||||
@@ -205,23 +196,9 @@ help:
|
||||
@echo " - deps install dependencies"
|
||||
@echo " - deps-frontend install frontend dependencies"
|
||||
@echo " - deps-backend install backend dependencies"
|
||||
@echo " - deps-tools install tool dependencies"
|
||||
@echo " - lint lint everything"
|
||||
@echo " - lint-fix lint everything and fix issues"
|
||||
@echo " - lint-actions lint action workflow files"
|
||||
@echo " - lint-frontend lint frontend files"
|
||||
@echo " - lint-frontend-fix lint frontend files and fix issues"
|
||||
@echo " - lint-backend lint backend files"
|
||||
@echo " - lint-backend-fix lint backend files and fix issues"
|
||||
@echo " - lint-go lint go files"
|
||||
@echo " - lint-go-fix lint go files and fix issues"
|
||||
@echo " - lint-go-vet lint go files with vet"
|
||||
@echo " - lint-js lint js files"
|
||||
@echo " - lint-js-fix lint js files and fix issues"
|
||||
@echo " - lint-css lint css files"
|
||||
@echo " - lint-css-fix lint css files and fix issues"
|
||||
@echo " - lint-md lint markdown files"
|
||||
@echo " - lint-swagger lint swagger files"
|
||||
@echo " - checks run various consistency checks"
|
||||
@echo " - checks-frontend check frontend files"
|
||||
@echo " - checks-backend check backend files"
|
||||
@@ -239,10 +216,13 @@ help:
|
||||
@echo " - generate-manpage generate manpage"
|
||||
@echo " - generate-swagger generate the swagger spec from code comments"
|
||||
@echo " - swagger-validate check if the swagger spec is valid"
|
||||
@echo " - golangci-lint run golangci-lint linter"
|
||||
@echo " - go-licenses regenerate go licenses"
|
||||
@echo " - vet examines Go source code and reports suspicious constructs"
|
||||
@echo " - tidy run go mod tidy"
|
||||
@echo " - test[\#TestSpecificName] run unit test"
|
||||
@echo " - test-sqlite[\#TestSpecificName] run integration test for sqlite"
|
||||
@echo " - pr#<index> build and start gitea from a PR with integration test data loaded"
|
||||
|
||||
.PHONY: go-check
|
||||
go-check:
|
||||
@@ -293,16 +273,12 @@ clean:
|
||||
fmt:
|
||||
GOFUMPT_PACKAGE=$(GOFUMPT_PACKAGE) $(GO) run build/code-batch-process.go gitea-fmt -w '{file-list}'
|
||||
$(eval TEMPLATES := $(shell find templates -type f -name '*.tmpl'))
|
||||
@# strip whitespace after '{{' or '(' and before '}}' or ')' unless there is only
|
||||
@# whitespace before it
|
||||
@$(SED_INPLACE) \
|
||||
-e 's/{{[ ]\{1,\}/{{/g' -e '/^[ ]\{1,\}}}/! s/[ ]\{1,\}}}/}}/g' \
|
||||
-e 's/([ ]\{1,\}/(/g' -e '/^[ ]\{1,\})/! s/[ ]\{1,\})/)/g' \
|
||||
$(TEMPLATES)
|
||||
@# strip whitespace after '{{' and before `}}` unless there is only whitespace before it
|
||||
@$(SED_INPLACE) -e 's/{{[ ]\{1,\}/{{/g' -e '/^[ ]\{1,\}}}/! s/[ ]\{1,\}}}/}}/g' $(TEMPLATES)
|
||||
|
||||
.PHONY: fmt-check
|
||||
fmt-check: fmt
|
||||
@diff=$$(git diff --color=always $(GO_SOURCES) templates $(WEB_DIRS)); \
|
||||
@diff=$$(git diff $(GO_SOURCES) templates $(WEB_DIRS)); \
|
||||
if [ -n "$$diff" ]; then \
|
||||
echo "Please run 'make fmt' and commit the result:"; \
|
||||
echo "$${diff}"; \
|
||||
@@ -313,6 +289,12 @@ fmt-check: fmt
|
||||
misspell-check:
|
||||
go run $(MISSPELL_PACKAGE) -error $(GO_DIRS) $(WEB_DIRS)
|
||||
|
||||
.PHONY: vet
|
||||
vet:
|
||||
@echo "Running go vet..."
|
||||
@GOOS= GOARCH= $(GO) build code.gitea.io/gitea-vet
|
||||
@$(GO) vet -vettool=gitea-vet $(GO_PACKAGES)
|
||||
|
||||
.PHONY: $(TAGS_EVIDENCE)
|
||||
$(TAGS_EVIDENCE):
|
||||
@mkdir -p $(MAKE_EVIDENCE_DIR)
|
||||
@@ -332,7 +314,7 @@ $(SWAGGER_SPEC): $(GO_SOURCES_NO_BINDATA)
|
||||
|
||||
.PHONY: swagger-check
|
||||
swagger-check: generate-swagger
|
||||
@diff=$$(git diff --color=always '$(SWAGGER_SPEC)'); \
|
||||
@diff=$$(git diff '$(SWAGGER_SPEC)'); \
|
||||
if [ -n "$$diff" ]; then \
|
||||
echo "Please run 'make generate-swagger' and commit the result:"; \
|
||||
echo "$${diff}"; \
|
||||
@@ -345,6 +327,11 @@ swagger-validate:
|
||||
$(GO) run $(SWAGGER_PACKAGE) validate './$(SWAGGER_SPEC)'
|
||||
$(SED_INPLACE) '$(SWAGGER_SPEC_S_TMPL)' './$(SWAGGER_SPEC)'
|
||||
|
||||
.PHONY: errcheck
|
||||
errcheck:
|
||||
@echo "Running errcheck..."
|
||||
$(GO) run $(ERRCHECK_PACKAGE) $(GO_PACKAGES)
|
||||
|
||||
.PHONY: checks
|
||||
checks: checks-frontend checks-backend
|
||||
|
||||
@@ -357,81 +344,23 @@ checks-backend: tidy-check swagger-check fmt-check misspell-check swagger-valida
|
||||
.PHONY: lint
|
||||
lint: lint-frontend lint-backend
|
||||
|
||||
.PHONY: lint-fix
|
||||
lint-fix: lint-frontend-fix lint-backend-fix
|
||||
|
||||
.PHONY: lint-frontend
|
||||
lint-frontend: lint-js lint-css lint-md lint-swagger
|
||||
|
||||
.PHONY: lint-frontend-fix
|
||||
lint-frontend-fix: lint-js-fix lint-css-fix lint-md lint-swagger
|
||||
|
||||
.PHONY: lint-backend
|
||||
lint-backend: lint-go lint-go-vet lint-editorconfig
|
||||
|
||||
.PHONY: lint-backend-fix
|
||||
lint-backend-fix: lint-go-fix lint-go-vet lint-editorconfig
|
||||
|
||||
.PHONY: lint-js
|
||||
lint-js: node_modules
|
||||
lint-frontend: node_modules
|
||||
npx eslint --color --max-warnings=0 --ext js,vue web_src/js build *.config.js tests/e2e
|
||||
|
||||
.PHONY: lint-js-fix
|
||||
lint-js-fix: node_modules
|
||||
npx eslint --color --max-warnings=0 --ext js,vue web_src/js build *.config.js tests/e2e --fix
|
||||
|
||||
.PHONY: lint-css
|
||||
lint-css: node_modules
|
||||
npx stylelint --color --max-warnings=0 web_src/css web_src/js/components/*.vue
|
||||
|
||||
.PHONY: lint-css-fix
|
||||
lint-css-fix: node_modules
|
||||
npx stylelint --color --max-warnings=0 web_src/css web_src/js/components/*.vue --fix
|
||||
|
||||
.PHONY: lint-swagger
|
||||
lint-swagger: node_modules
|
||||
npx stylelint --color --max-warnings=0 web_src/css
|
||||
npx spectral lint -q -F hint $(SWAGGER_SPEC)
|
||||
|
||||
.PHONY: lint-md
|
||||
lint-md: node_modules
|
||||
npx markdownlint docs *.md
|
||||
|
||||
.PHONY: lint-go
|
||||
lint-go:
|
||||
$(GO) run $(GOLANGCI_LINT_PACKAGE) run
|
||||
|
||||
.PHONY: lint-go-fix
|
||||
lint-go-fix:
|
||||
$(GO) run $(GOLANGCI_LINT_PACKAGE) run --fix
|
||||
|
||||
# workaround step for the lint-go-windows CI task because 'go run' can not
|
||||
# have distinct GOOS/GOARCH for its build and run steps
|
||||
.PHONY: lint-go-windows
|
||||
lint-go-windows:
|
||||
@GOOS= GOARCH= $(GO) install $(GOLANGCI_LINT_PACKAGE)
|
||||
golangci-lint run
|
||||
|
||||
.PHONY: lint-go-vet
|
||||
lint-go-vet:
|
||||
@echo "Running go vet..."
|
||||
@GOOS= GOARCH= $(GO) build code.gitea.io/gitea-vet
|
||||
@$(GO) vet -vettool=gitea-vet $(GO_PACKAGES)
|
||||
|
||||
.PHONY: lint-editorconfig
|
||||
lint-editorconfig:
|
||||
$(GO) run $(EDITORCONFIG_CHECKER_PACKAGE) templates .github/workflows
|
||||
|
||||
.PHONY: lint-actions
|
||||
lint-actions:
|
||||
$(GO) run $(ACTIONLINT_PACKAGE)
|
||||
.PHONY: lint-backend
|
||||
lint-backend: golangci-lint vet editorconfig-checker
|
||||
|
||||
.PHONY: watch
|
||||
watch:
|
||||
@bash build/watch.sh
|
||||
bash tools/watch.sh
|
||||
|
||||
.PHONY: watch-frontend
|
||||
watch-frontend: node-check node_modules
|
||||
@rm -rf $(WEBPACK_DEST_ENTRIES)
|
||||
rm -rf $(WEBPACK_DEST_ENTRIES)
|
||||
NODE_ENV=development npx webpack --watch --progress
|
||||
|
||||
.PHONY: watch-backend
|
||||
@@ -490,7 +419,7 @@ vendor: go.mod go.sum
|
||||
|
||||
.PHONY: tidy-check
|
||||
tidy-check: tidy
|
||||
@diff=$$(git diff --color=always go.mod go.sum $(GO_LICENSE_FILE)); \
|
||||
@diff=$$(git diff go.mod go.sum $(GO_LICENSE_FILE)); \
|
||||
if [ -n "$$diff" ]; then \
|
||||
echo "Please run 'make tidy' and commit the result:"; \
|
||||
echo "$${diff}"; \
|
||||
@@ -839,28 +768,28 @@ release-windows: | $(DIST_DIRS)
|
||||
ifeq (,$(findstring gogit,$(TAGS)))
|
||||
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -buildmode exe -dest $(DIST)/binaries -tags 'osusergo gogit $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets 'windows/*' -out gitea-$(VERSION)-gogit .
|
||||
endif
|
||||
ifneq ($(DRONE_TAG),)
|
||||
ifeq ($(CI),true)
|
||||
cp /build/* $(DIST)/binaries
|
||||
endif
|
||||
|
||||
.PHONY: release-linux
|
||||
release-linux: | $(DIST_DIRS)
|
||||
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets '$(LINUX_ARCHS)' -out gitea-$(VERSION) .
|
||||
ifneq ($(DRONE_TAG),)
|
||||
ifeq ($(CI),true)
|
||||
cp /build/* $(DIST)/binaries
|
||||
endif
|
||||
|
||||
.PHONY: release-darwin
|
||||
release-darwin: | $(DIST_DIRS)
|
||||
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '$(LDFLAGS)' -targets 'darwin-10.12/amd64,darwin-10.12/arm64' -out gitea-$(VERSION) .
|
||||
ifneq ($(DRONE_TAG),)
|
||||
ifeq ($(CI),true)
|
||||
cp /build/* $(DIST)/binaries
|
||||
endif
|
||||
|
||||
.PHONY: release-freebsd
|
||||
release-freebsd: | $(DIST_DIRS)
|
||||
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '$(LDFLAGS)' -targets 'freebsd/amd64' -out gitea-$(VERSION) .
|
||||
ifneq ($(DRONE_TAG),)
|
||||
ifeq ($(CI),true)
|
||||
cp /build/* $(DIST)/binaries
|
||||
endif
|
||||
|
||||
@@ -895,7 +824,7 @@ docs:
|
||||
cd docs; bash scripts/trans-copy.sh;
|
||||
|
||||
.PHONY: deps
|
||||
deps: deps-frontend deps-backend deps-tools
|
||||
deps: deps-frontend deps-backend
|
||||
|
||||
.PHONY: deps-frontend
|
||||
deps-frontend: node_modules
|
||||
@@ -903,11 +832,9 @@ deps-frontend: node_modules
|
||||
.PHONY: deps-backend
|
||||
deps-backend:
|
||||
$(GO) mod download
|
||||
|
||||
.PHONY: deps-tools
|
||||
deps-tools:
|
||||
$(GO) install $(AIR_PACKAGE)
|
||||
$(GO) install $(EDITORCONFIG_CHECKER_PACKAGE)
|
||||
$(GO) install $(ERRCHECK_PACKAGE)
|
||||
$(GO) install $(GOFUMPT_PACKAGE)
|
||||
$(GO) install $(GOLANGCI_LINT_PACKAGE)
|
||||
$(GO) install $(GXZ_PAGAGE)
|
||||
@@ -916,7 +843,6 @@ deps-tools:
|
||||
$(GO) install $(XGO_PACKAGE)
|
||||
$(GO) install $(GO_LICENSES_PACKAGE)
|
||||
$(GO) install $(GOVULNCHECK_PACKAGE)
|
||||
$(GO) install $(ACTIONLINT_PACKAGE)
|
||||
|
||||
node_modules: package-lock.json
|
||||
npm install --no-save
|
||||
@@ -958,7 +884,7 @@ svg: node-check | node_modules
|
||||
.PHONY: svg-check
|
||||
svg-check: svg
|
||||
@git add $(SVG_DEST_DIR)
|
||||
@diff=$$(git diff --color=always --cached $(SVG_DEST_DIR)); \
|
||||
@diff=$$(git diff --cached $(SVG_DEST_DIR)); \
|
||||
if [ -n "$$diff" ]; then \
|
||||
echo "Please run 'make svg' and 'git add $(SVG_DEST_DIR)' and commit the result:"; \
|
||||
echo "$${diff}"; \
|
||||
@@ -968,7 +894,7 @@ svg-check: svg
|
||||
.PHONY: lockfile-check
|
||||
lockfile-check:
|
||||
npm install --package-lock-only
|
||||
@diff=$$(git diff --color=always package-lock.json); \
|
||||
@diff=$$(git diff package-lock.json); \
|
||||
if [ -n "$$diff" ]; then \
|
||||
echo "package-lock.json is inconsistent with package.json"; \
|
||||
echo "Please run 'npm install --package-lock-only' and commit the result:"; \
|
||||
@@ -1007,10 +933,33 @@ generate-manpage:
|
||||
@gzip -9 man/man1/gitea.1 && echo man/man1/gitea.1.gz created
|
||||
@#TODO A small script that formats config-cheat-sheet.en-us.md nicely for use as a config man page
|
||||
|
||||
.PHONY: pr\#%
|
||||
pr\#%: clean-all
|
||||
$(GO) run contrib/pr/checkout.go $*
|
||||
|
||||
.PHONY: golangci-lint
|
||||
golangci-lint:
|
||||
$(GO) run $(GOLANGCI_LINT_PACKAGE) run
|
||||
|
||||
# workaround step for the lint-backend-windows CI task because 'go run' can not
|
||||
# have distinct GOOS/GOARCH for its build and run steps
|
||||
.PHONY: golangci-lint-windows
|
||||
golangci-lint-windows:
|
||||
@GOOS= GOARCH= $(GO) install $(GOLANGCI_LINT_PACKAGE)
|
||||
golangci-lint run
|
||||
|
||||
.PHONY: editorconfig-checker
|
||||
editorconfig-checker:
|
||||
$(GO) run $(EDITORCONFIG_CHECKER_PACKAGE) templates
|
||||
|
||||
.PHONY: docker
|
||||
docker:
|
||||
docker build --disable-content-trust=false -t $(DOCKER_REF) .
|
||||
# support also build args docker build --build-arg GITEA_VERSION=v1.2.3 --build-arg TAGS="bindata sqlite sqlite_unlock_notify" .
|
||||
|
||||
.PHONY: docker-build
|
||||
docker-build:
|
||||
docker run -ti --rm -v "$(CURDIR):/srv/app/src/code.gitea.io/gitea" -w /srv/app/src/code.gitea.io/gitea -e TAGS="bindata $(TAGS)" LDFLAGS="$(LDFLAGS)" CGO_EXTRA_CFLAGS="$(CGO_EXTRA_CFLAGS)" webhippie/golang:edge make clean build
|
||||
|
||||
# This endif closes the if at the top of the file
|
||||
endif
|
||||
|
||||
@@ -110,7 +110,7 @@ Translations are done through Crowdin. If you want to translate to a new languag
|
||||
|
||||
You can also just create an issue for adding a language or ask on discord on the #translation channel. If you need context or find some translation issues, you can leave a comment on the string or ask on Discord. For general translation questions there is a section in the docs. Currently a bit empty but we hope to fill it as questions pop up.
|
||||
|
||||
https://docs.gitea.io/en-us/contributing/translation-guidelines/
|
||||
https://docs.gitea.io/en-us/translation-guidelines/
|
||||
|
||||
[](https://crowdin.com/project/gitea)
|
||||
|
||||
@@ -173,8 +173,8 @@ for the full license text.
|
||||
|
||||
Looking for an overview of the interface? Check it out!
|
||||
|
||||
||||
|
||||
||||
|
||||
|:---:|:---:|:---:|
|
||||
||||
|
||||
|||
|
||||
|||
|
||||
||||
|
||||
|||
|
||||
|||
|
||||
|
||||
+4
-4
@@ -91,8 +91,8 @@ Fork -> Patch -> Push -> Pull Request
|
||||
|
||||
## 截图
|
||||
|
||||
||||
|
||||
||||
|
||||
|:---:|:---:|:---:|
|
||||
||||
|
||||
|||
|
||||
|||
|
||||
||||
|
||||
|||
|
||||
|||
|
||||
|
||||
Generated
+11
-91
File diff suppressed because one or more lines are too long
@@ -1,114 +0,0 @@
|
||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
//go:build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if len(os.Args) != 2 {
|
||||
println("usage: backport-locales <to-ref>")
|
||||
println("eg: backport-locales release/v1.19")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
mustNoErr := func(err error) {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
collectInis := func(ref string) map[string]setting.ConfigProvider {
|
||||
inis := map[string]setting.ConfigProvider{}
|
||||
err := filepath.WalkDir("options/locale", func(path string, d os.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if d.IsDir() || !strings.HasSuffix(d.Name(), ".ini") {
|
||||
return nil
|
||||
}
|
||||
cfg, err := setting.NewConfigProviderForLocale(path)
|
||||
mustNoErr(err)
|
||||
inis[path] = cfg
|
||||
fmt.Printf("collecting: %s @ %s\n", path, ref)
|
||||
return nil
|
||||
})
|
||||
mustNoErr(err)
|
||||
return inis
|
||||
}
|
||||
|
||||
// collect new locales from current working directory
|
||||
inisNew := collectInis("HEAD")
|
||||
|
||||
// switch to the target ref, and collect the old locales
|
||||
cmd := exec.Command("git", "checkout", os.Args[1])
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
mustNoErr(cmd.Run())
|
||||
inisOld := collectInis(os.Args[1])
|
||||
|
||||
// use old en-US as the base, and copy the new translations to the old locales
|
||||
enUsOld := inisOld["options/locale/locale_en-US.ini"]
|
||||
brokenWarned := map[string]bool{}
|
||||
for path, iniOld := range inisOld {
|
||||
if iniOld == enUsOld {
|
||||
continue
|
||||
}
|
||||
iniNew := inisNew[path]
|
||||
if iniNew == nil {
|
||||
continue
|
||||
}
|
||||
for _, secEnUS := range enUsOld.Sections() {
|
||||
secOld := iniOld.Section(secEnUS.Name())
|
||||
secNew := iniNew.Section(secEnUS.Name())
|
||||
for _, keyEnUs := range secEnUS.Keys() {
|
||||
if secNew.HasKey(keyEnUs.Name()) {
|
||||
oldStr := secOld.Key(keyEnUs.Name()).String()
|
||||
newStr := secNew.Key(keyEnUs.Name()).String()
|
||||
broken := oldStr != "" && strings.Count(oldStr, "%") != strings.Count(newStr, "%")
|
||||
broken = broken || strings.Contains(oldStr, "\n") || strings.Contains(oldStr, "\n")
|
||||
if broken {
|
||||
brokenWarned[secOld.Name()+"."+keyEnUs.Name()] = true
|
||||
fmt.Println("----")
|
||||
fmt.Printf("WARNING: skip broken locale: %s , [%s] %s\n", path, secEnUS.Name(), keyEnUs.Name())
|
||||
fmt.Printf("\told: %s\n", strings.ReplaceAll(oldStr, "\n", "\\n"))
|
||||
fmt.Printf("\tnew: %s\n", strings.ReplaceAll(newStr, "\n", "\\n"))
|
||||
continue
|
||||
}
|
||||
secOld.Key(keyEnUs.Name()).SetValue(newStr)
|
||||
}
|
||||
}
|
||||
}
|
||||
mustNoErr(iniOld.SaveTo(path))
|
||||
}
|
||||
|
||||
fmt.Println("========")
|
||||
|
||||
for path, iniNew := range inisNew {
|
||||
for _, sec := range iniNew.Sections() {
|
||||
for _, key := range sec.Keys() {
|
||||
str := sec.Key(key.Name()).String()
|
||||
broken := strings.Contains(str, "\n")
|
||||
broken = broken || strings.HasPrefix(str, "`") != strings.HasSuffix(str, "`")
|
||||
broken = broken || strings.HasPrefix(str, "\"`")
|
||||
broken = broken || strings.HasPrefix(str, "`\"")
|
||||
broken = broken || strings.Count(str, `"`)%2 == 1
|
||||
broken = broken || strings.Count(str, "`")%2 == 1
|
||||
if broken && !brokenWarned[sec.Name()+"."+key.Name()] {
|
||||
fmt.Printf("WARNING: found broken locale: %s , [%s] %s\n", path, sec.Name(), key.Name())
|
||||
fmt.Printf("\tstr: %s\n", strings.ReplaceAll(str, "\n", "\\n"))
|
||||
fmt.Println("----")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,7 @@ import (
|
||||
|
||||
var optionLogVerbose bool
|
||||
|
||||
func logVerbose(msg string, args ...any) {
|
||||
func logVerbose(msg string, args ...interface{}) {
|
||||
if optionLogVerbose {
|
||||
log.Printf(msg, args...)
|
||||
}
|
||||
@@ -65,6 +65,7 @@ func newFileCollector(fileFilter string, batchSize int) (*fileCollector, error)
|
||||
"modules",
|
||||
"routers",
|
||||
"services",
|
||||
"tools",
|
||||
}
|
||||
co.includePatterns = append(co.includePatterns, regexp.MustCompile(`.*\.go$`))
|
||||
|
||||
|
||||
@@ -60,13 +60,13 @@ func main() {
|
||||
// generate data
|
||||
buf, err := generate()
|
||||
if err != nil {
|
||||
log.Fatalf("generate err: %v", err)
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// write
|
||||
err = os.WriteFile(*flagOut, buf, 0o644)
|
||||
if err != nil {
|
||||
log.Fatalf("WriteFile err: %v", err)
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,10 +7,9 @@ package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path"
|
||||
goPath "path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"sort"
|
||||
@@ -28,47 +27,14 @@ type LicenseEntry struct {
|
||||
}
|
||||
|
||||
func main() {
|
||||
if len(os.Args) != 3 {
|
||||
fmt.Println("usage: go run generate-go-licenses.go <base-dir> <out-json-file>")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
base, out := os.Args[1], os.Args[2]
|
||||
|
||||
// Add ext for excluded files because license_test.go will be included for some reason.
|
||||
// And there are more files that should be excluded, check with:
|
||||
//
|
||||
// go run github.com/google/go-licenses@v1.6.0 save . --force --save_path=.go-licenses 2>/dev/null
|
||||
// find .go-licenses -type f | while read FILE; do echo "${$(basename $FILE)##*.}"; done | sort -u
|
||||
// AUTHORS
|
||||
// COPYING
|
||||
// LICENSE
|
||||
// Makefile
|
||||
// NOTICE
|
||||
// gitignore
|
||||
// go
|
||||
// md
|
||||
// mod
|
||||
// sum
|
||||
// toml
|
||||
// txt
|
||||
// yml
|
||||
//
|
||||
// It could be removed once we have a better regex.
|
||||
excludedExt := map[string]bool{
|
||||
".gitignore": true,
|
||||
".go": true,
|
||||
".mod": true,
|
||||
".sum": true,
|
||||
".toml": true,
|
||||
".yml": true,
|
||||
}
|
||||
var paths []string
|
||||
paths := []string{}
|
||||
err := filepath.WalkDir(base, func(path string, entry fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if entry.IsDir() || !licenseRe.MatchString(entry.Name()) || excludedExt[filepath.Ext(entry.Name())] {
|
||||
if entry.IsDir() || !licenseRe.MatchString(entry.Name()) {
|
||||
return nil
|
||||
}
|
||||
paths = append(paths, path)
|
||||
@@ -80,27 +46,28 @@ func main() {
|
||||
|
||||
sort.Strings(paths)
|
||||
|
||||
var entries []LicenseEntry
|
||||
for _, filePath := range paths {
|
||||
licenseText, err := os.ReadFile(filePath)
|
||||
entries := []LicenseEntry{}
|
||||
for _, path := range paths {
|
||||
path := filepath.ToSlash(path)
|
||||
|
||||
licenseText, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
pkgPath := filepath.ToSlash(filePath)
|
||||
pkgPath = strings.TrimPrefix(pkgPath, base+"/")
|
||||
pkgName := path.Dir(pkgPath)
|
||||
path = strings.Replace(path, base+"/", "", 1)
|
||||
name := goPath.Dir(path)
|
||||
|
||||
// There might be a bug somewhere in go-licenses that sometimes interprets the
|
||||
// root package as "." and sometimes as "code.gitea.io/gitea". Workaround by
|
||||
// removing both of them for the sake of stable output.
|
||||
if pkgName == "." || pkgName == "code.gitea.io/gitea" {
|
||||
if name == "." || name == "code.gitea.io/gitea" {
|
||||
continue
|
||||
}
|
||||
|
||||
entries = append(entries, LicenseEntry{
|
||||
Name: pkgName,
|
||||
Path: pkgPath,
|
||||
Name: name,
|
||||
Path: path,
|
||||
LicenseText: string(licenseText),
|
||||
})
|
||||
}
|
||||
@@ -110,11 +77,6 @@ func main() {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Ensure file has a final newline
|
||||
if jsonBytes[len(jsonBytes)-1] != '\n' {
|
||||
jsonBytes = append(jsonBytes, '\n')
|
||||
}
|
||||
|
||||
err = os.WriteFile(out, jsonBytes, 0o644)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
||||
+2
-10
@@ -25,22 +25,14 @@ async function processFile(file, {prefix, fullName} = {}) {
|
||||
if (prefix === 'octicon') name = name.replace(/-[0-9]+$/, ''); // chop of '-16' on octicons
|
||||
}
|
||||
|
||||
// Set the `xmlns` attribute so that the files are displayable in standalone documents
|
||||
// The svg backend module will strip the attribute during startup for inline display
|
||||
const {data} = optimize(await readFile(file, 'utf8'), {
|
||||
plugins: [
|
||||
{name: 'preset-default'},
|
||||
{name: 'removeXMLNS'},
|
||||
{name: 'removeDimensions'},
|
||||
{name: 'prefixIds', params: {prefix: () => name}},
|
||||
{name: 'addClassesToSVGElement', params: {classNames: ['svg', name]}},
|
||||
{
|
||||
name: 'addAttributesToSVGElement', params: {
|
||||
attributes: [
|
||||
{'xmlns': 'http://www.w3.org/2000/svg'},
|
||||
{'width': '16'}, {'height': '16'}, {'aria-hidden': 'true'},
|
||||
]
|
||||
}
|
||||
},
|
||||
{name: 'addAttributesToSVGElement', params: {attributes: [{'width': '16'}, {'height': '16'}, {'aria-hidden': 'true'}]}},
|
||||
],
|
||||
});
|
||||
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
//go:build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
_, err := io.Copy(os.Stdout, os.Stdin)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
+4
-33
@@ -1,43 +1,14 @@
|
||||
#!/bin/sh
|
||||
|
||||
# this script runs in alpine image which only has `sh` shell
|
||||
|
||||
set +e
|
||||
if sed --version 2>/dev/null | grep -q GNU; then
|
||||
SED_INPLACE="sed -i"
|
||||
else
|
||||
SED_INPLACE="sed -i ''"
|
||||
fi
|
||||
set -e
|
||||
|
||||
if [ ! -f ./options/locale/locale_en-US.ini ]; then
|
||||
echo "please run this script in the root directory of the project"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mv ./options/locale/locale_en-US.ini ./options/
|
||||
|
||||
# the "ini" library for locale has many quirks, its behavior is different from Crowdin.
|
||||
# see i18n_test.go for more details
|
||||
|
||||
# this script helps to unquote the Crowdin outputs for the quirky ini library
|
||||
# * find all `key="...\"..."` lines
|
||||
# * remove the leading quote
|
||||
# * remove the trailing quote
|
||||
# * unescape the quotes
|
||||
# * eg: key="...\"..." => key=..."...
|
||||
$SED_INPLACE -r -e '/^[-.A-Za-z0-9_]+[ ]*=[ ]*".*"$/ {
|
||||
s/^([-.A-Za-z0-9_]+)[ ]*=[ ]*"/\1=/
|
||||
s/"$//
|
||||
# Make sure to only change lines that have the translation enclosed between quotes
|
||||
sed -i -r -e '/^[a-zA-Z0-9_.-]+[ ]*=[ ]*".*"$/ {
|
||||
s/^([a-zA-Z0-9_.-]+)[ ]*="/\1=/
|
||||
s/\\"/"/g
|
||||
s/"$//
|
||||
}' ./options/locale/*.ini
|
||||
|
||||
# * if the escaped line is incomplete like `key="...` or `key=..."`, quote it with backticks
|
||||
# * eg: key="... => key=`"...`
|
||||
# * eg: key=..." => key=`..."`
|
||||
$SED_INPLACE -r -e 's/^([-.A-Za-z0-9_]+)[ ]*=[ ]*(".*[^"])$/\1=`\2`/' ./options/locale/*.ini
|
||||
$SED_INPLACE -r -e 's/^([-.A-Za-z0-9_]+)[ ]*=[ ]*([^"].*")$/\1=`\2`/' ./options/locale/*.ini
|
||||
|
||||
# Remove translation under 25% of en_us
|
||||
baselines=$(wc -l "./options/locale_en-US.ini" | cut -d" " -f1)
|
||||
baselines=$((baselines / 4))
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
make --no-print-directory watch-frontend &
|
||||
make --no-print-directory watch-backend &
|
||||
|
||||
trap 'kill $(jobs -p)' EXIT
|
||||
wait
|
||||
@@ -1,55 +0,0 @@
|
||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"code.gitea.io/gitea/modules/private"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var (
|
||||
// CmdActions represents the available actions sub-commands.
|
||||
CmdActions = cli.Command{
|
||||
Name: "actions",
|
||||
Usage: "",
|
||||
Description: "Commands for managing Gitea Actions",
|
||||
Subcommands: []cli.Command{
|
||||
subcmdActionsGenRunnerToken,
|
||||
},
|
||||
}
|
||||
|
||||
subcmdActionsGenRunnerToken = cli.Command{
|
||||
Name: "generate-runner-token",
|
||||
Usage: "Generate a new token for a runner to use to register with the server",
|
||||
Action: runGenerateActionsRunnerToken,
|
||||
Aliases: []string{"grt"},
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "scope, s",
|
||||
Value: "",
|
||||
Usage: "{owner}[/{repo}] - leave empty for a global runner",
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func runGenerateActionsRunnerToken(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
setting.MustInstalled()
|
||||
|
||||
scope := c.String("scope")
|
||||
|
||||
respText, extra := private.GenerateActionsRunnerToken(ctx, scope)
|
||||
if extra.HasError() {
|
||||
return handleCliResponseExtra(extra)
|
||||
}
|
||||
_, _ = fmt.Printf("%s\n", respText)
|
||||
return nil
|
||||
}
|
||||
@@ -55,28 +55,17 @@ func runGenerateAccessToken(c *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// construct token with name and user so we can make sure it is unique
|
||||
t := &auth_model.AccessToken{
|
||||
Name: c.String("token-name"),
|
||||
UID: user.ID,
|
||||
}
|
||||
|
||||
exist, err := auth_model.AccessTokenByNameExists(t)
|
||||
accessTokenScope, err := auth_model.AccessTokenScope(c.String("scopes")).Normalize()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if exist {
|
||||
return fmt.Errorf("access token name has been used already")
|
||||
|
||||
t := &auth_model.AccessToken{
|
||||
Name: c.String("token-name"),
|
||||
UID: user.ID,
|
||||
Scope: accessTokenScope,
|
||||
}
|
||||
|
||||
// make sure the scopes are valid
|
||||
accessTokenScope, err := auth_model.AccessTokenScope(c.String("scopes")).Normalize()
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid access token scope provided: %w", err)
|
||||
}
|
||||
t.Scope = accessTokenScope
|
||||
|
||||
// create the token
|
||||
if err := auth_model.NewAccessToken(t); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
+3
-3
@@ -63,7 +63,7 @@ Outputs to 'cert.pem' and 'key.pem' and will overwrite existing files.`,
|
||||
},
|
||||
}
|
||||
|
||||
func publicKey(priv any) any {
|
||||
func publicKey(priv interface{}) interface{} {
|
||||
switch k := priv.(type) {
|
||||
case *rsa.PrivateKey:
|
||||
return &k.PublicKey
|
||||
@@ -74,7 +74,7 @@ func publicKey(priv any) any {
|
||||
}
|
||||
}
|
||||
|
||||
func pemBlockForKey(priv any) *pem.Block {
|
||||
func pemBlockForKey(priv interface{}) *pem.Block {
|
||||
switch k := priv.(type) {
|
||||
case *rsa.PrivateKey:
|
||||
return &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(k)}
|
||||
@@ -94,7 +94,7 @@ func runCert(c *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
var priv any
|
||||
var priv interface{}
|
||||
var err error
|
||||
switch c.String("ecdsa-curve") {
|
||||
case "":
|
||||
|
||||
+3
-33
@@ -9,7 +9,6 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strings"
|
||||
@@ -58,9 +57,10 @@ func confirm() (bool, error) {
|
||||
}
|
||||
|
||||
func initDB(ctx context.Context) error {
|
||||
setting.MustInstalled()
|
||||
setting.InitProviderFromExistingFile()
|
||||
setting.LoadCommonSettings()
|
||||
setting.LoadDBSetting()
|
||||
setting.InitSQLLoggersForCli(log.INFO)
|
||||
setting.InitSQLLog(false)
|
||||
|
||||
if setting.Database.Type == "" {
|
||||
log.Fatal(`Database settings are missing from the configuration file: %q.
|
||||
@@ -94,33 +94,3 @@ func installSignals() (context.Context, context.CancelFunc) {
|
||||
|
||||
return ctx, cancel
|
||||
}
|
||||
|
||||
func setupConsoleLogger(level log.Level, colorize bool, out io.Writer) {
|
||||
if out != os.Stdout && out != os.Stderr {
|
||||
panic("setupConsoleLogger can only be used with os.Stdout or os.Stderr")
|
||||
}
|
||||
|
||||
writeMode := log.WriterMode{
|
||||
Level: level,
|
||||
Colorize: colorize,
|
||||
WriterOption: log.WriterConsoleOption{Stderr: out == os.Stderr},
|
||||
}
|
||||
writer := log.NewEventWriterConsole("console-default", writeMode)
|
||||
log.GetManager().GetLogger(log.DEFAULT).ReplaceAllWriters(writer)
|
||||
}
|
||||
|
||||
// PrepareConsoleLoggerLevel by default, use INFO level for console logger, but some sub-commands (for git/ssh protocol) shouldn't output any log to stdout.
|
||||
// Any log appears in git stdout pipe will break the git protocol, eg: client can't push and hangs forever.
|
||||
func PrepareConsoleLoggerLevel(defaultLevel log.Level) func(*cli.Context) error {
|
||||
return func(c *cli.Context) error {
|
||||
level := defaultLevel
|
||||
if c.Bool("quiet") || c.GlobalBoolT("quiet") {
|
||||
level = log.FATAL
|
||||
}
|
||||
if c.Bool("debug") || c.GlobalBool("debug") || c.Bool("verbose") || c.GlobalBool("verbose") {
|
||||
level = log.TRACE
|
||||
}
|
||||
log.SetConsoleLogger(log.DEFAULT, "console-default", level)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
+61
-32
@@ -4,10 +4,10 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
golog "log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
|
||||
@@ -82,25 +82,24 @@ You should back-up your database before doing this and ensure that your database
|
||||
}
|
||||
|
||||
func runRecreateTable(ctx *cli.Context) error {
|
||||
stdCtx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
// Redirect the default golog to here
|
||||
golog.SetFlags(0)
|
||||
golog.SetPrefix("")
|
||||
golog.SetOutput(log.LoggerToWriter(log.GetLogger(log.DEFAULT).Info))
|
||||
golog.SetOutput(log.NewLoggerAsWriter("INFO", log.GetLogger(log.DEFAULT)))
|
||||
|
||||
debug := ctx.Bool("debug")
|
||||
setting.MustInstalled()
|
||||
setting.InitProviderFromExistingFile()
|
||||
setting.LoadCommonSettings()
|
||||
setting.LoadDBSetting()
|
||||
|
||||
if debug {
|
||||
setting.InitSQLLoggersForCli(log.DEBUG)
|
||||
} else {
|
||||
setting.InitSQLLoggersForCli(log.INFO)
|
||||
}
|
||||
setting.Log.EnableXORMLog = ctx.Bool("debug")
|
||||
setting.Database.LogSQL = ctx.Bool("debug")
|
||||
// FIXME: don't use CfgProvider directly
|
||||
setting.CfgProvider.Section("log").Key("XORM").SetValue(",")
|
||||
|
||||
setting.InitSQLLog(!ctx.Bool("debug"))
|
||||
stdCtx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
setting.Database.LogSQL = debug
|
||||
if err := db.InitEngine(stdCtx); err != nil {
|
||||
fmt.Println(err)
|
||||
fmt.Println("Check if you are using the right config file. You can use a --config directive to specify one.")
|
||||
@@ -127,31 +126,44 @@ func runRecreateTable(ctx *cli.Context) error {
|
||||
})
|
||||
}
|
||||
|
||||
func setupDoctorDefaultLogger(ctx *cli.Context, colorize bool) {
|
||||
// Silence the default loggers
|
||||
setupConsoleLogger(log.FATAL, log.CanColorStderr, os.Stderr)
|
||||
|
||||
func setDoctorLogger(ctx *cli.Context) {
|
||||
logFile := ctx.String("log-file")
|
||||
if !ctx.IsSet("log-file") {
|
||||
logFile = "doctor.log"
|
||||
}
|
||||
colorize := log.CanColorStdout
|
||||
if ctx.IsSet("color") {
|
||||
colorize = ctx.Bool("color")
|
||||
}
|
||||
|
||||
if len(logFile) == 0 {
|
||||
// if no doctor log-file is set, do not show any log from default logger
|
||||
log.NewLogger(1000, "doctor", "console", fmt.Sprintf(`{"level":"NONE","stacktracelevel":"NONE","colorize":%t}`, colorize))
|
||||
return
|
||||
}
|
||||
|
||||
if logFile == "-" {
|
||||
setupConsoleLogger(log.TRACE, colorize, os.Stdout)
|
||||
} else {
|
||||
logFile, _ = filepath.Abs(logFile)
|
||||
writeMode := log.WriterMode{Level: log.TRACE, WriterOption: log.WriterFileOption{FileName: logFile}}
|
||||
writer, err := log.NewEventWriter("console-to-file", "file", writeMode)
|
||||
if err != nil {
|
||||
log.FallbackErrorf("unable to create file log writer: %v", err)
|
||||
defer func() {
|
||||
recovered := recover()
|
||||
if recovered == nil {
|
||||
return
|
||||
}
|
||||
log.GetManager().GetLogger(log.DEFAULT).ReplaceAllWriters(writer)
|
||||
|
||||
err, ok := recovered.(error)
|
||||
if !ok {
|
||||
panic(recovered)
|
||||
}
|
||||
if errors.Is(err, os.ErrPermission) {
|
||||
fmt.Fprintf(os.Stderr, "ERROR: Unable to write logs to provided file due to permissions error: %s\n %v\n", logFile, err)
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "ERROR: Unable to write logs to provided file: %s\n %v\n", logFile, err)
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, "WARN: Logging will be disabled\n Use `--log-file` to configure log file location\n")
|
||||
log.NewLogger(1000, "doctor", "console", fmt.Sprintf(`{"level":"NONE","stacktracelevel":"NONE","colorize":%t}`, colorize))
|
||||
}()
|
||||
|
||||
if logFile == "-" {
|
||||
log.NewLogger(1000, "doctor", "console", fmt.Sprintf(`{"level":"trace","stacktracelevel":"NONE","colorize":%t}`, colorize))
|
||||
} else {
|
||||
log.NewLogger(1000, "doctor", "file", fmt.Sprintf(`{"filename":%q,"level":"trace","stacktracelevel":"NONE"}`, logFile))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,17 +171,22 @@ func runDoctor(ctx *cli.Context) error {
|
||||
stdCtx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
// Silence the default loggers
|
||||
log.DelNamedLogger("console")
|
||||
log.DelNamedLogger(log.DEFAULT)
|
||||
|
||||
// Now setup our own
|
||||
setDoctorLogger(ctx)
|
||||
|
||||
colorize := log.CanColorStdout
|
||||
if ctx.IsSet("color") {
|
||||
colorize = ctx.Bool("color")
|
||||
}
|
||||
|
||||
setupDoctorDefaultLogger(ctx, colorize)
|
||||
|
||||
// Finally redirect the default golang's log to here
|
||||
// Finally redirect the default golog to here
|
||||
golog.SetFlags(0)
|
||||
golog.SetPrefix("")
|
||||
golog.SetOutput(log.LoggerToWriter(log.GetLogger(log.DEFAULT).Info))
|
||||
golog.SetOutput(log.NewLoggerAsWriter("INFO", log.GetLogger(log.DEFAULT)))
|
||||
|
||||
if ctx.IsSet("list") {
|
||||
w := tabwriter.NewWriter(os.Stdout, 0, 8, 1, '\t', 0)
|
||||
@@ -217,5 +234,17 @@ func runDoctor(ctx *cli.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
return doctor.RunChecks(stdCtx, colorize, ctx.Bool("fix"), checks)
|
||||
// Now we can set up our own logger to return information about what the doctor is doing
|
||||
if err := log.NewNamedLogger("doctorouter",
|
||||
0,
|
||||
"console",
|
||||
"console",
|
||||
fmt.Sprintf(`{"level":"INFO","stacktracelevel":"NONE","colorize":%t,"flags":-1}`, colorize)); err != nil {
|
||||
fmt.Println(err)
|
||||
return err
|
||||
}
|
||||
|
||||
logger := log.GetLogger("doctorouter")
|
||||
defer logger.Close()
|
||||
return doctor.RunChecks(stdCtx, logger, ctx.Bool("fix"), checks)
|
||||
}
|
||||
|
||||
+15
-27
@@ -112,10 +112,6 @@ It can be used for backup and capture Gitea server image to send to maintainer`,
|
||||
Name: "verbose, V",
|
||||
Usage: "Show process details",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "quiet, q",
|
||||
Usage: "Only display warnings and errors",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "tempdir, t",
|
||||
Value: os.TempDir(),
|
||||
@@ -161,7 +157,7 @@ It can be used for backup and capture Gitea server image to send to maintainer`,
|
||||
},
|
||||
}
|
||||
|
||||
func fatal(format string, args ...any) {
|
||||
func fatal(format string, args ...interface{}) {
|
||||
fmt.Fprintf(os.Stderr, format+"\n", args...)
|
||||
log.Fatal(format, args...)
|
||||
}
|
||||
@@ -172,7 +168,10 @@ func runDump(ctx *cli.Context) error {
|
||||
outType := ctx.String("type")
|
||||
if fileName == "-" {
|
||||
file = os.Stdout
|
||||
setupConsoleLogger(log.FATAL, log.CanColorStderr, os.Stderr)
|
||||
err := log.DelLogger("console")
|
||||
if err != nil {
|
||||
fatal("Deleting default logger failed. Can not write to stdout: %v", err)
|
||||
}
|
||||
} else {
|
||||
for _, suffix := range outputTypeEnum.Enum {
|
||||
if strings.HasSuffix(fileName, "."+suffix) {
|
||||
@@ -182,7 +181,8 @@ func runDump(ctx *cli.Context) error {
|
||||
}
|
||||
fileName += "." + outType
|
||||
}
|
||||
setting.MustInstalled()
|
||||
setting.InitProviderFromExistingFile()
|
||||
setting.LoadCommonSettings()
|
||||
|
||||
// make sure we are logging to the console no matter what the configuration tells us do to
|
||||
// FIXME: don't use CfgProvider directly
|
||||
@@ -192,25 +192,12 @@ func runDump(ctx *cli.Context) error {
|
||||
if _, err := setting.CfgProvider.Section("log.console").NewKey("STDERR", "true"); err != nil {
|
||||
fatal("Setting console logger to stderr failed: %v", err)
|
||||
}
|
||||
|
||||
// Set loglevel to Warn if quiet-mode is requested
|
||||
if ctx.Bool("quiet") {
|
||||
if _, err := setting.CfgProvider.Section("log.console").NewKey("LEVEL", "Warn"); err != nil {
|
||||
fatal("Setting console log-level failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if !setting.InstallLock {
|
||||
log.Error("Is '%s' really the right config path?\n", setting.CustomConf)
|
||||
return fmt.Errorf("gitea is not initialized")
|
||||
}
|
||||
setting.LoadSettings() // cannot access session settings otherwise
|
||||
|
||||
verbose := ctx.Bool("verbose")
|
||||
if verbose && ctx.Bool("quiet") {
|
||||
return fmt.Errorf("--quiet and --verbose cannot both be set")
|
||||
}
|
||||
|
||||
stdCtx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
@@ -236,7 +223,8 @@ func runDump(ctx *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
var iface any
|
||||
verbose := ctx.Bool("verbose")
|
||||
var iface interface{}
|
||||
if fileName == "-" {
|
||||
iface, err = archiver.ByExtension(fmt.Sprintf(".%s", outType))
|
||||
} else {
|
||||
@@ -264,7 +252,7 @@ func runDump(ctx *cli.Context) error {
|
||||
log.Info("Skip dumping LFS data")
|
||||
} else if !setting.LFS.StartServer {
|
||||
log.Info("LFS isn't enabled. Skip dumping LFS data")
|
||||
} else if err := storage.LFS.IterateObjects("", func(objPath string, object storage.Object) error {
|
||||
} else if err := storage.LFS.IterateObjects(func(objPath string, object storage.Object) error {
|
||||
info, err := object.Stat()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -353,9 +341,9 @@ func runDump(ctx *cli.Context) error {
|
||||
}
|
||||
|
||||
excludes = append(excludes, setting.RepoRootPath)
|
||||
excludes = append(excludes, setting.LFS.Storage.Path)
|
||||
excludes = append(excludes, setting.Attachment.Storage.Path)
|
||||
excludes = append(excludes, setting.Packages.Storage.Path)
|
||||
excludes = append(excludes, setting.LFS.Path)
|
||||
excludes = append(excludes, setting.Attachment.Path)
|
||||
excludes = append(excludes, setting.Packages.Path)
|
||||
excludes = append(excludes, setting.Log.RootPath)
|
||||
excludes = append(excludes, absFileName)
|
||||
if err := addRecursiveExclude(w, "data", setting.AppDataPath, excludes, verbose); err != nil {
|
||||
@@ -365,7 +353,7 @@ func runDump(ctx *cli.Context) error {
|
||||
|
||||
if ctx.IsSet("skip-attachment-data") && ctx.Bool("skip-attachment-data") {
|
||||
log.Info("Skip dumping attachment data")
|
||||
} else if err := storage.Attachments.IterateObjects("", func(objPath string, object storage.Object) error {
|
||||
} else if err := storage.Attachments.IterateObjects(func(objPath string, object storage.Object) error {
|
||||
info, err := object.Stat()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -380,7 +368,7 @@ func runDump(ctx *cli.Context) error {
|
||||
log.Info("Skip dumping package data")
|
||||
} else if !setting.Packages.Enabled {
|
||||
log.Info("Packages isn't enabled. Skip dumping package data")
|
||||
} else if err := storage.Packages.IterateObjects("", func(objPath string, object storage.Object) error {
|
||||
} else if err := storage.Packages.IterateObjects(func(objPath string, object storage.Object) error {
|
||||
info, err := object.Stat()
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
+79
-51
@@ -1,6 +1,8 @@
|
||||
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
//go:build bindata
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
@@ -8,9 +10,9 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/assetfs"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/options"
|
||||
"code.gitea.io/gitea/modules/public"
|
||||
@@ -22,9 +24,9 @@ import (
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
// CmdEmbedded represents the available extract sub-command.
|
||||
// Cmdembedded represents the available extract sub-command.
|
||||
var (
|
||||
CmdEmbedded = cli.Command{
|
||||
Cmdembedded = cli.Command{
|
||||
Name: "embedded",
|
||||
Usage: "Extract embedded resources",
|
||||
Description: "A command for extracting embedded resources, like templates and images",
|
||||
@@ -87,26 +89,50 @@ var (
|
||||
},
|
||||
}
|
||||
|
||||
matchedAssetFiles []assetFile
|
||||
sections map[string]*section
|
||||
assets []asset
|
||||
)
|
||||
|
||||
type assetFile struct {
|
||||
fs *assetfs.LayeredFS
|
||||
name string
|
||||
path string
|
||||
type section struct {
|
||||
Path string
|
||||
Names func() []string
|
||||
IsDir func(string) (bool, error)
|
||||
Asset func(string) ([]byte, error)
|
||||
}
|
||||
|
||||
type asset struct {
|
||||
Section *section
|
||||
Name string
|
||||
Path string
|
||||
}
|
||||
|
||||
func initEmbeddedExtractor(c *cli.Context) error {
|
||||
setupConsoleLogger(log.ERROR, log.CanColorStderr, os.Stderr)
|
||||
// Silence the console logger
|
||||
log.DelNamedLogger("console")
|
||||
log.DelNamedLogger(log.DEFAULT)
|
||||
|
||||
patterns, err := compileCollectPatterns(c.Args())
|
||||
// Read configuration file
|
||||
setting.InitProviderAllowEmpty()
|
||||
setting.LoadCommonSettings()
|
||||
|
||||
pats, err := getPatterns(c.Args())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sections := make(map[string]*section, 3)
|
||||
|
||||
collectAssetFilesByPattern(c, patterns, "options", options.BuiltinAssets())
|
||||
collectAssetFilesByPattern(c, patterns, "public", public.BuiltinAssets())
|
||||
collectAssetFilesByPattern(c, patterns, "templates", templates.BuiltinAssets())
|
||||
sections["public"] = §ion{Path: "public", Names: public.AssetNames, IsDir: public.AssetIsDir, Asset: public.Asset}
|
||||
sections["options"] = §ion{Path: "options", Names: options.AssetNames, IsDir: options.AssetIsDir, Asset: options.Asset}
|
||||
sections["templates"] = §ion{Path: "templates", Names: templates.BuiltinAssetNames, IsDir: templates.BuiltinAssetIsDir, Asset: templates.BuiltinAsset}
|
||||
|
||||
for _, sec := range sections {
|
||||
assets = append(assets, buildAssetList(sec, pats, c)...)
|
||||
}
|
||||
|
||||
// Sort assets
|
||||
sort.SliceStable(assets, func(i, j int) bool {
|
||||
return assets[i].Path < assets[j].Path
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -140,8 +166,8 @@ func runListDo(c *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, a := range matchedAssetFiles {
|
||||
fmt.Println(a.path)
|
||||
for _, a := range assets {
|
||||
fmt.Println(a.Path)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -152,19 +178,19 @@ func runViewDo(c *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(matchedAssetFiles) == 0 {
|
||||
return fmt.Errorf("no files matched the given pattern")
|
||||
} else if len(matchedAssetFiles) > 1 {
|
||||
return fmt.Errorf("too many files matched the given pattern, try to be more specific")
|
||||
if len(assets) == 0 {
|
||||
return fmt.Errorf("No files matched the given pattern")
|
||||
} else if len(assets) > 1 {
|
||||
return fmt.Errorf("Too many files matched the given pattern; try to be more specific")
|
||||
}
|
||||
|
||||
data, err := matchedAssetFiles[0].fs.ReadFile(matchedAssetFiles[0].name)
|
||||
data, err := assets[0].Section.Asset(assets[0].Name)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: %w", matchedAssetFiles[0].path, err)
|
||||
return fmt.Errorf("%s: %w", assets[0].Path, err)
|
||||
}
|
||||
|
||||
if _, err = os.Stdout.Write(data); err != nil {
|
||||
return fmt.Errorf("%s: %w", matchedAssetFiles[0].path, err)
|
||||
return fmt.Errorf("%s: %w", assets[0].Path, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -176,7 +202,7 @@ func runExtractDo(c *cli.Context) error {
|
||||
}
|
||||
|
||||
if len(c.Args()) == 0 {
|
||||
return fmt.Errorf("a list of pattern of files to extract is mandatory (e.g. '**' for all)")
|
||||
return fmt.Errorf("A list of pattern of files to extract is mandatory (e.g. '**' for all)")
|
||||
}
|
||||
|
||||
destdir := "."
|
||||
@@ -201,7 +227,7 @@ func runExtractDo(c *cli.Context) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: %s", destdir, err)
|
||||
} else if !fi.IsDir() {
|
||||
return fmt.Errorf("destination %q is not a directory", destdir)
|
||||
return fmt.Errorf("%s is not a directory.", destdir)
|
||||
}
|
||||
|
||||
fmt.Printf("Extracting to %s:\n", destdir)
|
||||
@@ -209,23 +235,23 @@ func runExtractDo(c *cli.Context) error {
|
||||
overwrite := c.Bool("overwrite")
|
||||
rename := c.Bool("rename")
|
||||
|
||||
for _, a := range matchedAssetFiles {
|
||||
for _, a := range assets {
|
||||
if err := extractAsset(destdir, a, overwrite, rename); err != nil {
|
||||
// Non-fatal error
|
||||
fmt.Fprintf(os.Stderr, "%s: %v", a.path, err)
|
||||
fmt.Fprintf(os.Stderr, "%s: %v", a.Path, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func extractAsset(d string, a assetFile, overwrite, rename bool) error {
|
||||
dest := filepath.Join(d, filepath.FromSlash(a.path))
|
||||
func extractAsset(d string, a asset, overwrite, rename bool) error {
|
||||
dest := filepath.Join(d, filepath.FromSlash(a.Path))
|
||||
dir := filepath.Dir(dest)
|
||||
|
||||
data, err := a.fs.ReadFile(a.name)
|
||||
data, err := a.Section.Asset(a.Name)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: %w", a.path, err)
|
||||
return fmt.Errorf("%s: %w", a.Path, err)
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(dir, os.ModePerm); err != nil {
|
||||
@@ -246,7 +272,7 @@ func extractAsset(d string, a assetFile, overwrite, rename bool) error {
|
||||
return fmt.Errorf("%s already exists, but it's not a regular file", dest)
|
||||
} else if rename {
|
||||
if err := util.Rename(dest, dest+".bak"); err != nil {
|
||||
return fmt.Errorf("error creating backup for %s: %w", dest, err)
|
||||
return fmt.Errorf("Error creating backup for %s: %w", dest, err)
|
||||
}
|
||||
// Attempt to respect file permissions mask (even if user:group will be set anew)
|
||||
perms = fi.Mode()
|
||||
@@ -267,30 +293,32 @@ func extractAsset(d string, a assetFile, overwrite, rename bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func collectAssetFilesByPattern(c *cli.Context, globs []glob.Glob, path string, layer *assetfs.Layer) {
|
||||
fs := assetfs.Layered(layer)
|
||||
files, err := fs.ListAllFiles(".", true)
|
||||
if err != nil {
|
||||
log.Error("Error listing files in %q: %v", path, err)
|
||||
return
|
||||
}
|
||||
for _, name := range files {
|
||||
if path == "public" &&
|
||||
strings.HasPrefix(name, "vendor/") &&
|
||||
!c.Bool("include-vendored") {
|
||||
continue
|
||||
}
|
||||
matchName := path + "/" + name
|
||||
for _, g := range globs {
|
||||
if g.Match(matchName) {
|
||||
matchedAssetFiles = append(matchedAssetFiles, assetFile{fs: fs, name: name, path: path + "/" + name})
|
||||
break
|
||||
func buildAssetList(sec *section, globs []glob.Glob, c *cli.Context) []asset {
|
||||
results := make([]asset, 0, 64)
|
||||
for _, name := range sec.Names() {
|
||||
if isdir, err := sec.IsDir(name); !isdir && err == nil {
|
||||
if sec.Path == "public" &&
|
||||
strings.HasPrefix(name, "vendor/") &&
|
||||
!c.Bool("include-vendored") {
|
||||
continue
|
||||
}
|
||||
matchName := sec.Path + "/" + name
|
||||
for _, g := range globs {
|
||||
if g.Match(matchName) {
|
||||
results = append(results, asset{
|
||||
Section: sec,
|
||||
Name: name,
|
||||
Path: sec.Path + "/" + name,
|
||||
})
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return results
|
||||
}
|
||||
|
||||
func compileCollectPatterns(args []string) ([]glob.Glob, error) {
|
||||
func getPatterns(args []string) ([]glob.Glob, error) {
|
||||
if len(args) == 0 {
|
||||
args = []string{"**"}
|
||||
}
|
||||
@@ -298,7 +326,7 @@ func compileCollectPatterns(args []string) ([]glob.Glob, error) {
|
||||
for i := range args {
|
||||
if g, err := glob.Compile(args[i], '/'); err != nil {
|
||||
return nil, fmt.Errorf("'%s': Invalid glob pattern: %w", args[i], err)
|
||||
} else { //nolint:revive
|
||||
} else {
|
||||
pat[i] = g
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
//go:build !bindata
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
// Cmdembedded represents the available extract sub-command.
|
||||
var (
|
||||
Cmdembedded = cli.Command{
|
||||
Name: "embedded",
|
||||
Usage: "Extract embedded resources",
|
||||
Description: "A command for extracting embedded resources, like templates and images",
|
||||
Action: extractorNotImplemented,
|
||||
}
|
||||
)
|
||||
|
||||
func extractorNotImplemented(c *cli.Context) error {
|
||||
err := fmt.Errorf("Sorry: the 'embedded' subcommand is not available in builds without bindata")
|
||||
fmt.Fprintf(os.Stderr, "%s\n", err)
|
||||
return err
|
||||
}
|
||||
+90
-73
@@ -6,19 +6,19 @@ package cmd
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/private"
|
||||
repo_module "code.gitea.io/gitea/modules/repository"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
@@ -33,7 +33,6 @@ var (
|
||||
Name: "hook",
|
||||
Usage: "Delegate commands to corresponding Git hooks",
|
||||
Description: "This should only be called by Git",
|
||||
Before: PrepareConsoleLoggerLevel(log.FATAL),
|
||||
Subcommands: []cli.Command{
|
||||
subcmdHookPreReceive,
|
||||
subcmdHookUpdate,
|
||||
@@ -142,7 +141,7 @@ func (d *delayWriter) Close() error {
|
||||
if d == nil {
|
||||
return nil
|
||||
}
|
||||
stopped := d.timer.Stop()
|
||||
stopped := util.StopTimer(d.timer)
|
||||
if stopped || d.buf == nil {
|
||||
return nil
|
||||
}
|
||||
@@ -168,11 +167,11 @@ func runHookPreReceive(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
setup(ctx, c.Bool("debug"))
|
||||
setup("hooks/pre-receive.log", c.Bool("debug"))
|
||||
|
||||
if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 {
|
||||
if setting.OnlyAllowPushIfGiteaEnvironmentSet {
|
||||
return fail(ctx, `Rejecting changes as Gitea environment not set.
|
||||
return fail(`Rejecting changes as Gitea environment not set.
|
||||
If you are pushing over SSH you must push with a key managed by
|
||||
Gitea or set your environment appropriately.`, "")
|
||||
}
|
||||
@@ -203,7 +202,7 @@ Gitea or set your environment appropriately.`, "")
|
||||
|
||||
oldCommitIDs := make([]string, hookBatchSize)
|
||||
newCommitIDs := make([]string, hookBatchSize)
|
||||
refFullNames := make([]git.RefName, hookBatchSize)
|
||||
refFullNames := make([]string, hookBatchSize)
|
||||
count := 0
|
||||
total := 0
|
||||
lastline := 0
|
||||
@@ -238,14 +237,14 @@ Gitea or set your environment appropriately.`, "")
|
||||
|
||||
oldCommitID := string(fields[0])
|
||||
newCommitID := string(fields[1])
|
||||
refFullName := git.RefName(fields[2])
|
||||
refFullName := string(fields[2])
|
||||
total++
|
||||
lastline++
|
||||
|
||||
// If the ref is a branch or tag, check if it's protected
|
||||
// if supportProcReceive all ref should be checked because
|
||||
// permission check was delayed
|
||||
if supportProcReceive || refFullName.IsBranch() || refFullName.IsTag() {
|
||||
if supportProcReceive || strings.HasPrefix(refFullName, git.BranchPrefix) || strings.HasPrefix(refFullName, git.TagPrefix) {
|
||||
oldCommitIDs[count] = oldCommitID
|
||||
newCommitIDs[count] = newCommitID
|
||||
refFullNames[count] = refFullName
|
||||
@@ -258,9 +257,14 @@ Gitea or set your environment appropriately.`, "")
|
||||
hookOptions.OldCommitIDs = oldCommitIDs
|
||||
hookOptions.NewCommitIDs = newCommitIDs
|
||||
hookOptions.RefFullNames = refFullNames
|
||||
extra := private.HookPreReceive(ctx, username, reponame, hookOptions)
|
||||
if extra.HasError() {
|
||||
return fail(ctx, extra.UserMsg, "HookPreReceive(batch) failed: %v", extra.Error)
|
||||
statusCode, msg := private.HookPreReceive(ctx, username, reponame, hookOptions)
|
||||
switch statusCode {
|
||||
case http.StatusOK:
|
||||
// no-op
|
||||
case http.StatusInternalServerError:
|
||||
return fail("Internal Server Error", msg)
|
||||
default:
|
||||
return fail(msg, "")
|
||||
}
|
||||
count = 0
|
||||
lastline = 0
|
||||
@@ -281,9 +285,12 @@ Gitea or set your environment appropriately.`, "")
|
||||
|
||||
fmt.Fprintf(out, " Checking %d references\n", count)
|
||||
|
||||
extra := private.HookPreReceive(ctx, username, reponame, hookOptions)
|
||||
if extra.HasError() {
|
||||
return fail(ctx, extra.UserMsg, "HookPreReceive(last) failed: %v", extra.Error)
|
||||
statusCode, msg := private.HookPreReceive(ctx, username, reponame, hookOptions)
|
||||
switch statusCode {
|
||||
case http.StatusInternalServerError:
|
||||
return fail("Internal Server Error", msg)
|
||||
case http.StatusForbidden:
|
||||
return fail(msg, "")
|
||||
}
|
||||
} else if lastline > 0 {
|
||||
fmt.Fprintf(out, "\n")
|
||||
@@ -302,7 +309,7 @@ func runHookPostReceive(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
setup(ctx, c.Bool("debug"))
|
||||
setup("hooks/post-receive.log", c.Bool("debug"))
|
||||
|
||||
// First of all run update-server-info no matter what
|
||||
if _, _, err := git.NewCommand(ctx, "update-server-info").RunStdString(nil); err != nil {
|
||||
@@ -316,7 +323,7 @@ func runHookPostReceive(c *cli.Context) error {
|
||||
|
||||
if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 {
|
||||
if setting.OnlyAllowPushIfGiteaEnvironmentSet {
|
||||
return fail(ctx, `Rejecting changes as Gitea environment not set.
|
||||
return fail(`Rejecting changes as Gitea environment not set.
|
||||
If you are pushing over SSH you must push with a key managed by
|
||||
Gitea or set your environment appropriately.`, "")
|
||||
}
|
||||
@@ -353,7 +360,7 @@ Gitea or set your environment appropriately.`, "")
|
||||
}
|
||||
oldCommitIDs := make([]string, hookBatchSize)
|
||||
newCommitIDs := make([]string, hookBatchSize)
|
||||
refFullNames := make([]git.RefName, hookBatchSize)
|
||||
refFullNames := make([]string, hookBatchSize)
|
||||
count := 0
|
||||
total := 0
|
||||
wasEmpty := false
|
||||
@@ -375,7 +382,7 @@ Gitea or set your environment appropriately.`, "")
|
||||
fmt.Fprintf(out, ".")
|
||||
oldCommitIDs[count] = string(fields[0])
|
||||
newCommitIDs[count] = string(fields[1])
|
||||
refFullNames[count] = git.RefName(fields[2])
|
||||
refFullNames[count] = string(fields[2])
|
||||
if refFullNames[count] == git.BranchPrefix+"master" && newCommitIDs[count] != git.EmptySHA && count == total {
|
||||
masterPushed = true
|
||||
}
|
||||
@@ -387,11 +394,11 @@ Gitea or set your environment appropriately.`, "")
|
||||
hookOptions.OldCommitIDs = oldCommitIDs
|
||||
hookOptions.NewCommitIDs = newCommitIDs
|
||||
hookOptions.RefFullNames = refFullNames
|
||||
resp, extra := private.HookPostReceive(ctx, repoUser, repoName, hookOptions)
|
||||
if extra.HasError() {
|
||||
resp, err := private.HookPostReceive(ctx, repoUser, repoName, hookOptions)
|
||||
if resp == nil {
|
||||
_ = dWriter.Close()
|
||||
hookPrintResults(results)
|
||||
return fail(ctx, extra.UserMsg, "HookPostReceive failed: %v", extra.Error)
|
||||
return fail("Internal Server Error", err)
|
||||
}
|
||||
wasEmpty = wasEmpty || resp.RepoWasEmpty
|
||||
results = append(results, resp.Results...)
|
||||
@@ -402,9 +409,9 @@ Gitea or set your environment appropriately.`, "")
|
||||
if count == 0 {
|
||||
if wasEmpty && masterPushed {
|
||||
// We need to tell the repo to reset the default branch to master
|
||||
extra := private.SetDefaultBranch(ctx, repoUser, repoName, "master")
|
||||
if extra.HasError() {
|
||||
return fail(ctx, extra.UserMsg, "SetDefaultBranch failed: %v", extra.Error)
|
||||
err := private.SetDefaultBranch(ctx, repoUser, repoName, "master")
|
||||
if err != nil {
|
||||
return fail("Internal Server Error", "SetDefaultBranch failed with Error: %v", err)
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(out, "Processed %d references in total\n", total)
|
||||
@@ -420,11 +427,11 @@ Gitea or set your environment appropriately.`, "")
|
||||
|
||||
fmt.Fprintf(out, " Processing %d references\n", count)
|
||||
|
||||
resp, extra := private.HookPostReceive(ctx, repoUser, repoName, hookOptions)
|
||||
resp, err := private.HookPostReceive(ctx, repoUser, repoName, hookOptions)
|
||||
if resp == nil {
|
||||
_ = dWriter.Close()
|
||||
hookPrintResults(results)
|
||||
return fail(ctx, extra.UserMsg, "HookPostReceive failed: %v", extra.Error)
|
||||
return fail("Internal Server Error", err)
|
||||
}
|
||||
wasEmpty = wasEmpty || resp.RepoWasEmpty
|
||||
results = append(results, resp.Results...)
|
||||
@@ -433,9 +440,9 @@ Gitea or set your environment appropriately.`, "")
|
||||
|
||||
if wasEmpty && masterPushed {
|
||||
// We need to tell the repo to reset the default branch to master
|
||||
extra := private.SetDefaultBranch(ctx, repoUser, repoName, "master")
|
||||
if extra.HasError() {
|
||||
return fail(ctx, extra.UserMsg, "SetDefaultBranch failed: %v", extra.Error)
|
||||
err := private.SetDefaultBranch(ctx, repoUser, repoName, "master")
|
||||
if err != nil {
|
||||
return fail("Internal Server Error", "SetDefaultBranch failed with Error: %v", err)
|
||||
}
|
||||
}
|
||||
_ = dWriter.Close()
|
||||
@@ -478,22 +485,22 @@ func pushOptions() map[string]string {
|
||||
}
|
||||
|
||||
func runHookProcReceive(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
setup(ctx, c.Bool("debug"))
|
||||
setup("hooks/proc-receive.log", c.Bool("debug"))
|
||||
|
||||
if len(os.Getenv("SSH_ORIGINAL_COMMAND")) == 0 {
|
||||
if setting.OnlyAllowPushIfGiteaEnvironmentSet {
|
||||
return fail(ctx, `Rejecting changes as Gitea environment not set.
|
||||
return fail(`Rejecting changes as Gitea environment not set.
|
||||
If you are pushing over SSH you must push with a key managed by
|
||||
Gitea or set your environment appropriately.`, "")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if git.CheckGitVersionAtLeast("2.29") != nil {
|
||||
return fail(ctx, "No proc-receive support", "current git version doesn't support proc-receive.")
|
||||
return fail("Internal Server Error", "git not support proc-receive.")
|
||||
}
|
||||
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
@@ -508,7 +515,7 @@ Gitea or set your environment appropriately.`, "")
|
||||
// H: PKT-LINE(version=1\0push-options...)
|
||||
// H: flush-pkt
|
||||
|
||||
rs, err := readPktLine(ctx, reader, pktLineTypeData)
|
||||
rs, err := readPktLine(reader, pktLineTypeData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -523,19 +530,19 @@ Gitea or set your environment appropriately.`, "")
|
||||
|
||||
index := bytes.IndexByte(rs.Data, byte(0))
|
||||
if index >= len(rs.Data) {
|
||||
return fail(ctx, "Protocol: format error", "pkt-line: format error "+fmt.Sprint(rs.Data))
|
||||
return fail("Internal Server Error", "pkt-line: format error "+fmt.Sprint(rs.Data))
|
||||
}
|
||||
|
||||
if index < 0 {
|
||||
if len(rs.Data) == 10 && rs.Data[9] == '\n' {
|
||||
index = 9
|
||||
} else {
|
||||
return fail(ctx, "Protocol: format error", "pkt-line: format error "+fmt.Sprint(rs.Data))
|
||||
return fail("Internal Server Error", "pkt-line: format error "+fmt.Sprint(rs.Data))
|
||||
}
|
||||
}
|
||||
|
||||
if string(rs.Data[0:index]) != VersionHead {
|
||||
return fail(ctx, "Protocol: version error", "Received unsupported version: %s", string(rs.Data[0:index]))
|
||||
return fail("Internal Server Error", "Received unsupported version: %s", string(rs.Data[0:index]))
|
||||
}
|
||||
requestOptions = strings.Split(string(rs.Data[index+1:]), " ")
|
||||
|
||||
@@ -548,17 +555,17 @@ Gitea or set your environment appropriately.`, "")
|
||||
}
|
||||
response = append(response, '\n')
|
||||
|
||||
_, err = readPktLine(ctx, reader, pktLineTypeFlush)
|
||||
_, err = readPktLine(reader, pktLineTypeFlush)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = writeDataPktLine(ctx, os.Stdout, response)
|
||||
err = writeDataPktLine(os.Stdout, response)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = writeFlushPktLine(ctx, os.Stdout)
|
||||
err = writeFlushPktLine(os.Stdout)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -577,11 +584,11 @@ Gitea or set your environment appropriately.`, "")
|
||||
}
|
||||
hookOptions.OldCommitIDs = make([]string, 0, hookBatchSize)
|
||||
hookOptions.NewCommitIDs = make([]string, 0, hookBatchSize)
|
||||
hookOptions.RefFullNames = make([]git.RefName, 0, hookBatchSize)
|
||||
hookOptions.RefFullNames = make([]string, 0, hookBatchSize)
|
||||
|
||||
for {
|
||||
// note: pktLineTypeUnknow means pktLineTypeFlush and pktLineTypeData all allowed
|
||||
rs, err = readPktLine(ctx, reader, pktLineTypeUnknow)
|
||||
rs, err = readPktLine(reader, pktLineTypeUnknow)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -595,14 +602,14 @@ Gitea or set your environment appropriately.`, "")
|
||||
}
|
||||
hookOptions.OldCommitIDs = append(hookOptions.OldCommitIDs, t[0])
|
||||
hookOptions.NewCommitIDs = append(hookOptions.NewCommitIDs, t[1])
|
||||
hookOptions.RefFullNames = append(hookOptions.RefFullNames, git.RefName(t[2]))
|
||||
hookOptions.RefFullNames = append(hookOptions.RefFullNames, t[2])
|
||||
}
|
||||
|
||||
hookOptions.GitPushOptions = make(map[string]string)
|
||||
|
||||
if hasPushOptions {
|
||||
for {
|
||||
rs, err = readPktLine(ctx, reader, pktLineTypeUnknow)
|
||||
rs, err = readPktLine(reader, pktLineTypeUnknow)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -619,9 +626,9 @@ Gitea or set your environment appropriately.`, "")
|
||||
}
|
||||
|
||||
// 3. run hook
|
||||
resp, extra := private.HookProcReceive(ctx, repoUser, repoName, hookOptions)
|
||||
if extra.HasError() {
|
||||
return fail(ctx, extra.UserMsg, "HookProcReceive failed: %v", extra.Error)
|
||||
resp, err := private.HookProcReceive(ctx, repoUser, repoName, hookOptions)
|
||||
if err != nil {
|
||||
return fail("Internal Server Error", "run proc-receive hook failed :%v", err)
|
||||
}
|
||||
|
||||
// 4. response result to service
|
||||
@@ -642,7 +649,7 @@ Gitea or set your environment appropriately.`, "")
|
||||
|
||||
for _, rs := range resp.Results {
|
||||
if len(rs.Err) > 0 {
|
||||
err = writeDataPktLine(ctx, os.Stdout, []byte("ng "+rs.OriginalRef.String()+" "+rs.Err))
|
||||
err = writeDataPktLine(os.Stdout, []byte("ng "+rs.OriginalRef+" "+rs.Err))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -650,43 +657,43 @@ Gitea or set your environment appropriately.`, "")
|
||||
}
|
||||
|
||||
if rs.IsNotMatched {
|
||||
err = writeDataPktLine(ctx, os.Stdout, []byte("ok "+rs.OriginalRef.String()))
|
||||
err = writeDataPktLine(os.Stdout, []byte("ok "+rs.OriginalRef))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = writeDataPktLine(ctx, os.Stdout, []byte("option fall-through"))
|
||||
err = writeDataPktLine(os.Stdout, []byte("option fall-through"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
err = writeDataPktLine(ctx, os.Stdout, []byte("ok "+rs.OriginalRef))
|
||||
err = writeDataPktLine(os.Stdout, []byte("ok "+rs.OriginalRef))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = writeDataPktLine(ctx, os.Stdout, []byte("option refname "+rs.Ref))
|
||||
err = writeDataPktLine(os.Stdout, []byte("option refname "+rs.Ref))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if rs.OldOID != git.EmptySHA {
|
||||
err = writeDataPktLine(ctx, os.Stdout, []byte("option old-oid "+rs.OldOID))
|
||||
err = writeDataPktLine(os.Stdout, []byte("option old-oid "+rs.OldOID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
err = writeDataPktLine(ctx, os.Stdout, []byte("option new-oid "+rs.NewOID))
|
||||
err = writeDataPktLine(os.Stdout, []byte("option new-oid "+rs.NewOID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if rs.IsForcePush {
|
||||
err = writeDataPktLine(ctx, os.Stdout, []byte("option forced-update"))
|
||||
err = writeDataPktLine(os.Stdout, []byte("option forced-update"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
err = writeFlushPktLine(ctx, os.Stdout)
|
||||
err = writeFlushPktLine(os.Stdout)
|
||||
|
||||
return err
|
||||
}
|
||||
@@ -711,7 +718,7 @@ type gitPktLine struct {
|
||||
Data []byte
|
||||
}
|
||||
|
||||
func readPktLine(ctx context.Context, in *bufio.Reader, requestType pktLineType) (*gitPktLine, error) {
|
||||
func readPktLine(in *bufio.Reader, requestType pktLineType) (*gitPktLine, error) {
|
||||
var (
|
||||
err error
|
||||
r *gitPktLine
|
||||
@@ -722,33 +729,33 @@ func readPktLine(ctx context.Context, in *bufio.Reader, requestType pktLineType)
|
||||
for i := 0; i < 4; i++ {
|
||||
lengthBytes[i], err = in.ReadByte()
|
||||
if err != nil {
|
||||
return nil, fail(ctx, "Protocol: stdin error", "Pkt-Line: read stdin failed : %v", err)
|
||||
return nil, fail("Internal Server Error", "Pkt-Line: read stdin failed : %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
r = new(gitPktLine)
|
||||
r.Length, err = strconv.ParseUint(string(lengthBytes), 16, 32)
|
||||
if err != nil {
|
||||
return nil, fail(ctx, "Protocol: format parse error", "Pkt-Line format is wrong :%v", err)
|
||||
return nil, fail("Internal Server Error", "Pkt-Line format is wrong :%v", err)
|
||||
}
|
||||
|
||||
if r.Length == 0 {
|
||||
if requestType == pktLineTypeData {
|
||||
return nil, fail(ctx, "Protocol: format data error", "Pkt-Line format is wrong")
|
||||
return nil, fail("Internal Server Error", "Pkt-Line format is wrong")
|
||||
}
|
||||
r.Type = pktLineTypeFlush
|
||||
return r, nil
|
||||
}
|
||||
|
||||
if r.Length <= 4 || r.Length > 65520 || requestType == pktLineTypeFlush {
|
||||
return nil, fail(ctx, "Protocol: format length error", "Pkt-Line format is wrong")
|
||||
return nil, fail("Internal Server Error", "Pkt-Line format is wrong")
|
||||
}
|
||||
|
||||
r.Data = make([]byte, r.Length-4)
|
||||
for i := range r.Data {
|
||||
r.Data[i], err = in.ReadByte()
|
||||
if err != nil {
|
||||
return nil, fail(ctx, "Protocol: data error", "Pkt-Line: read stdin failed : %v", err)
|
||||
return nil, fail("Internal Server Error", "Pkt-Line: read stdin failed : %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -757,15 +764,19 @@ func readPktLine(ctx context.Context, in *bufio.Reader, requestType pktLineType)
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func writeFlushPktLine(ctx context.Context, out io.Writer) error {
|
||||
func writeFlushPktLine(out io.Writer) error {
|
||||
l, err := out.Write([]byte("0000"))
|
||||
if err != nil || l != 4 {
|
||||
return fail(ctx, "Protocol: write error", "Pkt-Line response failed: %v", err)
|
||||
if err != nil {
|
||||
return fail("Internal Server Error", "Pkt-Line response failed: %v", err)
|
||||
}
|
||||
if l != 4 {
|
||||
return fail("Internal Server Error", "Pkt-Line response failed: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func writeDataPktLine(ctx context.Context, out io.Writer, data []byte) error {
|
||||
func writeDataPktLine(out io.Writer, data []byte) error {
|
||||
hexchar := []byte("0123456789abcdef")
|
||||
hex := func(n uint64) byte {
|
||||
return hexchar[(n)&15]
|
||||
@@ -779,13 +790,19 @@ func writeDataPktLine(ctx context.Context, out io.Writer, data []byte) error {
|
||||
tmp[3] = hex(length)
|
||||
|
||||
lr, err := out.Write(tmp)
|
||||
if err != nil || lr != 4 {
|
||||
return fail(ctx, "Protocol: write error", "Pkt-Line response failed: %v", err)
|
||||
if err != nil {
|
||||
return fail("Internal Server Error", "Pkt-Line response failed: %v", err)
|
||||
}
|
||||
if lr != 4 {
|
||||
return fail("Internal Server Error", "Pkt-Line response failed: %v", err)
|
||||
}
|
||||
|
||||
lr, err = out.Write(data)
|
||||
if err != nil || int(length-4) != lr {
|
||||
return fail(ctx, "Protocol: write error", "Pkt-Line response failed: %v", err)
|
||||
if err != nil {
|
||||
return fail("Internal Server Error", "Pkt-Line response failed: %v", err)
|
||||
}
|
||||
if int(length-4) != lr {
|
||||
return fail("Internal Server Error", "Pkt-Line response failed: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
+4
-6
@@ -6,7 +6,6 @@ package cmd
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
@@ -15,28 +14,27 @@ import (
|
||||
|
||||
func TestPktLine(t *testing.T) {
|
||||
// test read
|
||||
ctx := context.Background()
|
||||
s := strings.NewReader("0000")
|
||||
r := bufio.NewReader(s)
|
||||
result, err := readPktLine(ctx, r, pktLineTypeFlush)
|
||||
result, err := readPktLine(r, pktLineTypeFlush)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, pktLineTypeFlush, result.Type)
|
||||
|
||||
s = strings.NewReader("0006a\n")
|
||||
r = bufio.NewReader(s)
|
||||
result, err = readPktLine(ctx, r, pktLineTypeData)
|
||||
result, err = readPktLine(r, pktLineTypeData)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, pktLineTypeData, result.Type)
|
||||
assert.Equal(t, []byte("a\n"), result.Data)
|
||||
|
||||
// test write
|
||||
w := bytes.NewBuffer([]byte{})
|
||||
err = writeFlushPktLine(ctx, w)
|
||||
err = writeFlushPktLine(w)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []byte("0000"), w.Bytes())
|
||||
|
||||
w.Reset()
|
||||
err = writeDataPktLine(ctx, w, []byte("a\nb"))
|
||||
err = writeDataPktLine(w, []byte("a\nb"))
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []byte("0007a\nb"), w.Bytes())
|
||||
}
|
||||
|
||||
+4
-7
@@ -8,7 +8,6 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/private"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
@@ -18,7 +17,6 @@ import (
|
||||
var CmdKeys = cli.Command{
|
||||
Name: "keys",
|
||||
Usage: "This command queries the Gitea database to get the authorized command for a given ssh key fingerprint",
|
||||
Before: PrepareConsoleLoggerLevel(log.FATAL),
|
||||
Action: runKeys,
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
@@ -66,12 +64,11 @@ func runKeys(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
setup(ctx, false)
|
||||
setup("keys.log", false)
|
||||
|
||||
authorizedString, extra := private.AuthorizedPublicKeyByContent(ctx, content)
|
||||
// do not use handleCliResponseExtra or cli.NewExitError, if it exists immediately, it breaks some tests like Test_CmdKeys
|
||||
if extra.Error != nil {
|
||||
return extra.Error
|
||||
authorizedString, err := private.AuthorizedPublicKeyByContent(ctx, content)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println(strings.TrimSpace(authorizedString))
|
||||
return nil
|
||||
|
||||
+10
-5
@@ -5,6 +5,7 @@ package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"code.gitea.io/gitea/modules/private"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
@@ -16,7 +17,8 @@ func runSendMail(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
setting.MustInstalled()
|
||||
setting.InitProviderFromExistingFile()
|
||||
setting.LoadCommonSettings()
|
||||
|
||||
if err := argsSet(c, "title"); err != nil {
|
||||
return err
|
||||
@@ -41,10 +43,13 @@ func runSendMail(c *cli.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
respText, extra := private.SendEmail(ctx, subject, body, nil)
|
||||
if extra.HasError() {
|
||||
return handleCliResponseExtra(extra)
|
||||
status, message := private.SendEmail(ctx, subject, body, nil)
|
||||
if status != http.StatusOK {
|
||||
fmt.Printf("error: %s\n", message)
|
||||
return nil
|
||||
}
|
||||
_, _ = fmt.Printf("Sent %s email(s) to all users\n", respText)
|
||||
|
||||
fmt.Printf("Success: %s\n", message)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -7,8 +7,14 @@ import (
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
)
|
||||
|
||||
func init() {
|
||||
setting.SetCustomPathAndConf("", "", "")
|
||||
setting.InitProviderAndLoadCommonSettingsForTest()
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: "..",
|
||||
|
||||
+36
-31
@@ -4,6 +4,8 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
@@ -21,7 +23,6 @@ var (
|
||||
Subcommands: []cli.Command{
|
||||
subcmdShutdown,
|
||||
subcmdRestart,
|
||||
subcmdReloadTemplates,
|
||||
subcmdFlushQueues,
|
||||
subcmdLogging,
|
||||
subCmdProcesses,
|
||||
@@ -47,16 +48,6 @@ var (
|
||||
},
|
||||
Action: runRestart,
|
||||
}
|
||||
subcmdReloadTemplates = cli.Command{
|
||||
Name: "reload-templates",
|
||||
Usage: "Reload template files in the running process",
|
||||
Flags: []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "debug",
|
||||
},
|
||||
},
|
||||
Action: runReloadTemplates,
|
||||
}
|
||||
subcmdFlushQueues = cli.Command{
|
||||
Name: "flush-queues",
|
||||
Usage: "Flush queues in the running process",
|
||||
@@ -112,43 +103,57 @@ func runShutdown(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
setup(ctx, c.Bool("debug"))
|
||||
extra := private.Shutdown(ctx)
|
||||
return handleCliResponseExtra(extra)
|
||||
setup("manager", c.Bool("debug"))
|
||||
statusCode, msg := private.Shutdown(ctx)
|
||||
switch statusCode {
|
||||
case http.StatusInternalServerError:
|
||||
return fail("InternalServerError", msg)
|
||||
}
|
||||
|
||||
fmt.Fprintln(os.Stdout, msg)
|
||||
return nil
|
||||
}
|
||||
|
||||
func runRestart(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
setup(ctx, c.Bool("debug"))
|
||||
extra := private.Restart(ctx)
|
||||
return handleCliResponseExtra(extra)
|
||||
}
|
||||
setup("manager", c.Bool("debug"))
|
||||
statusCode, msg := private.Restart(ctx)
|
||||
switch statusCode {
|
||||
case http.StatusInternalServerError:
|
||||
return fail("InternalServerError", msg)
|
||||
}
|
||||
|
||||
func runReloadTemplates(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
setup(ctx, c.Bool("debug"))
|
||||
extra := private.ReloadTemplates(ctx)
|
||||
return handleCliResponseExtra(extra)
|
||||
fmt.Fprintln(os.Stdout, msg)
|
||||
return nil
|
||||
}
|
||||
|
||||
func runFlushQueues(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
setup(ctx, c.Bool("debug"))
|
||||
extra := private.FlushQueues(ctx, c.Duration("timeout"), c.Bool("non-blocking"))
|
||||
return handleCliResponseExtra(extra)
|
||||
setup("manager", c.Bool("debug"))
|
||||
statusCode, msg := private.FlushQueues(ctx, c.Duration("timeout"), c.Bool("non-blocking"))
|
||||
switch statusCode {
|
||||
case http.StatusInternalServerError:
|
||||
return fail("InternalServerError", msg)
|
||||
}
|
||||
|
||||
fmt.Fprintln(os.Stdout, msg)
|
||||
return nil
|
||||
}
|
||||
|
||||
func runProcesses(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
setup(ctx, c.Bool("debug"))
|
||||
extra := private.Processes(ctx, os.Stdout, c.Bool("flat"), c.Bool("no-system"), c.Bool("stacktraces"), c.Bool("json"), c.String("cancel"))
|
||||
return handleCliResponseExtra(extra)
|
||||
setup("manager", c.Bool("debug"))
|
||||
statusCode, msg := private.Processes(ctx, os.Stdout, c.Bool("flat"), c.Bool("no-system"), c.Bool("stacktraces"), c.Bool("json"), c.String("cancel"))
|
||||
switch statusCode {
|
||||
case http.StatusInternalServerError:
|
||||
return fail("InternalServerError", msg)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
+146
-47
@@ -5,6 +5,7 @@ package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
@@ -16,13 +17,13 @@ import (
|
||||
var (
|
||||
defaultLoggingFlags = []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "logger",
|
||||
Usage: `Logger name - will default to "default"`,
|
||||
Name: "group, g",
|
||||
Usage: "Group to add logger to - will default to \"default\"",
|
||||
}, cli.StringFlag{
|
||||
Name: "writer",
|
||||
Usage: "Name of the log writer - will default to mode",
|
||||
Name: "name, n",
|
||||
Usage: "Name of the new logger - will default to mode",
|
||||
}, cli.StringFlag{
|
||||
Name: "level",
|
||||
Name: "level, l",
|
||||
Usage: "Logging level for the new logger",
|
||||
}, cli.StringFlag{
|
||||
Name: "stacktrace-level, L",
|
||||
@@ -83,8 +84,8 @@ var (
|
||||
cli.BoolFlag{
|
||||
Name: "debug",
|
||||
}, cli.StringFlag{
|
||||
Name: "logger",
|
||||
Usage: `Logger name - will default to "default"`,
|
||||
Name: "group, g",
|
||||
Usage: "Group to add logger to - will default to \"default\"",
|
||||
},
|
||||
},
|
||||
Action: runRemoveLogger,
|
||||
@@ -93,6 +94,15 @@ var (
|
||||
Usage: "Add a logger",
|
||||
Subcommands: []cli.Command{
|
||||
{
|
||||
Name: "console",
|
||||
Usage: "Add a console logger",
|
||||
Flags: append(defaultLoggingFlags,
|
||||
cli.BoolFlag{
|
||||
Name: "stderr",
|
||||
Usage: "Output console logs to stderr - only relevant for console",
|
||||
}),
|
||||
Action: runAddConsoleLogger,
|
||||
}, {
|
||||
Name: "file",
|
||||
Usage: "Add a file logger",
|
||||
Flags: append(defaultLoggingFlags, []cli.Flag{
|
||||
@@ -139,6 +149,28 @@ var (
|
||||
},
|
||||
}...),
|
||||
Action: runAddConnLogger,
|
||||
}, {
|
||||
Name: "smtp",
|
||||
Usage: "Add an SMTP logger",
|
||||
Flags: append(defaultLoggingFlags, []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "username, u",
|
||||
Usage: "Mail server username",
|
||||
}, cli.StringFlag{
|
||||
Name: "password, P",
|
||||
Usage: "Mail server password",
|
||||
}, cli.StringFlag{
|
||||
Name: "host, H",
|
||||
Usage: "Mail server host (defaults to: 127.0.0.1:25)",
|
||||
}, cli.StringSliceFlag{
|
||||
Name: "send-to, s",
|
||||
Usage: "Email address(es) to send to",
|
||||
}, cli.StringFlag{
|
||||
Name: "subject, S",
|
||||
Usage: "Subject header of sent emails",
|
||||
},
|
||||
}...),
|
||||
Action: runAddSMTPLogger,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
@@ -159,26 +191,59 @@ var (
|
||||
)
|
||||
|
||||
func runRemoveLogger(c *cli.Context) error {
|
||||
setup("manager", c.Bool("debug"))
|
||||
group := c.String("group")
|
||||
if len(group) == 0 {
|
||||
group = log.DEFAULT
|
||||
}
|
||||
name := c.Args().First()
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
setup(ctx, c.Bool("debug"))
|
||||
logger := c.String("logger")
|
||||
if len(logger) == 0 {
|
||||
logger = log.DEFAULT
|
||||
statusCode, msg := private.RemoveLogger(ctx, group, name)
|
||||
switch statusCode {
|
||||
case http.StatusInternalServerError:
|
||||
return fail("InternalServerError", msg)
|
||||
}
|
||||
writer := c.Args().First()
|
||||
|
||||
extra := private.RemoveLogger(ctx, logger, writer)
|
||||
return handleCliResponseExtra(extra)
|
||||
fmt.Fprintln(os.Stdout, msg)
|
||||
return nil
|
||||
}
|
||||
|
||||
func runAddSMTPLogger(c *cli.Context) error {
|
||||
setup("manager", c.Bool("debug"))
|
||||
vals := map[string]interface{}{}
|
||||
mode := "smtp"
|
||||
if c.IsSet("host") {
|
||||
vals["host"] = c.String("host")
|
||||
} else {
|
||||
vals["host"] = "127.0.0.1:25"
|
||||
}
|
||||
|
||||
if c.IsSet("username") {
|
||||
vals["username"] = c.String("username")
|
||||
}
|
||||
if c.IsSet("password") {
|
||||
vals["password"] = c.String("password")
|
||||
}
|
||||
|
||||
if !c.IsSet("send-to") {
|
||||
return fmt.Errorf("Some recipients must be provided")
|
||||
}
|
||||
vals["sendTos"] = c.StringSlice("send-to")
|
||||
|
||||
if c.IsSet("subject") {
|
||||
vals["subject"] = c.String("subject")
|
||||
} else {
|
||||
vals["subject"] = "Diagnostic message from Gitea"
|
||||
}
|
||||
|
||||
return commonAddLogger(c, mode, vals)
|
||||
}
|
||||
|
||||
func runAddConnLogger(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
setup(ctx, c.Bool("debug"))
|
||||
vals := map[string]any{}
|
||||
setup("manager", c.Bool("debug"))
|
||||
vals := map[string]interface{}{}
|
||||
mode := "conn"
|
||||
vals["net"] = "tcp"
|
||||
if c.IsSet("protocol") {
|
||||
@@ -204,11 +269,8 @@ func runAddConnLogger(c *cli.Context) error {
|
||||
}
|
||||
|
||||
func runAddFileLogger(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
setup(ctx, c.Bool("debug"))
|
||||
vals := map[string]any{}
|
||||
setup("manager", c.Bool("debug"))
|
||||
vals := map[string]interface{}{}
|
||||
mode := "file"
|
||||
if c.IsSet("filename") {
|
||||
vals["filename"] = c.String("filename")
|
||||
@@ -236,12 +298,22 @@ func runAddFileLogger(c *cli.Context) error {
|
||||
return commonAddLogger(c, mode, vals)
|
||||
}
|
||||
|
||||
func commonAddLogger(c *cli.Context, mode string, vals map[string]any) error {
|
||||
func runAddConsoleLogger(c *cli.Context) error {
|
||||
setup("manager", c.Bool("debug"))
|
||||
vals := map[string]interface{}{}
|
||||
mode := "console"
|
||||
if c.IsSet("stderr") && c.Bool("stderr") {
|
||||
vals["stderr"] = c.Bool("stderr")
|
||||
}
|
||||
return commonAddLogger(c, mode, vals)
|
||||
}
|
||||
|
||||
func commonAddLogger(c *cli.Context, mode string, vals map[string]interface{}) error {
|
||||
if len(c.String("level")) > 0 {
|
||||
vals["level"] = log.LevelFromString(c.String("level")).String()
|
||||
vals["level"] = log.FromString(c.String("level")).String()
|
||||
}
|
||||
if len(c.String("stacktrace-level")) > 0 {
|
||||
vals["stacktraceLevel"] = log.LevelFromString(c.String("stacktrace-level")).String()
|
||||
vals["stacktraceLevel"] = log.FromString(c.String("stacktrace-level")).String()
|
||||
}
|
||||
if len(c.String("expression")) > 0 {
|
||||
vals["expression"] = c.String("expression")
|
||||
@@ -255,28 +327,39 @@ func commonAddLogger(c *cli.Context, mode string, vals map[string]any) error {
|
||||
if c.IsSet("color") {
|
||||
vals["colorize"] = c.Bool("color")
|
||||
}
|
||||
logger := log.DEFAULT
|
||||
if c.IsSet("logger") {
|
||||
logger = c.String("logger")
|
||||
group := "default"
|
||||
if c.IsSet("group") {
|
||||
group = c.String("group")
|
||||
}
|
||||
writer := mode
|
||||
if c.IsSet("writer") {
|
||||
writer = c.String("writer")
|
||||
name := mode
|
||||
if c.IsSet("name") {
|
||||
name = c.String("name")
|
||||
}
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
extra := private.AddLogger(ctx, logger, writer, mode, vals)
|
||||
return handleCliResponseExtra(extra)
|
||||
statusCode, msg := private.AddLogger(ctx, group, name, mode, vals)
|
||||
switch statusCode {
|
||||
case http.StatusInternalServerError:
|
||||
return fail("InternalServerError", msg)
|
||||
}
|
||||
|
||||
fmt.Fprintln(os.Stdout, msg)
|
||||
return nil
|
||||
}
|
||||
|
||||
func runPauseLogging(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
setup(ctx, c.Bool("debug"))
|
||||
userMsg := private.PauseLogging(ctx)
|
||||
_, _ = fmt.Fprintln(os.Stdout, userMsg)
|
||||
setup("manager", c.Bool("debug"))
|
||||
statusCode, msg := private.PauseLogging(ctx)
|
||||
switch statusCode {
|
||||
case http.StatusInternalServerError:
|
||||
return fail("InternalServerError", msg)
|
||||
}
|
||||
|
||||
fmt.Fprintln(os.Stdout, msg)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -284,9 +367,14 @@ func runResumeLogging(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
setup(ctx, c.Bool("debug"))
|
||||
userMsg := private.ResumeLogging(ctx)
|
||||
_, _ = fmt.Fprintln(os.Stdout, userMsg)
|
||||
setup("manager", c.Bool("debug"))
|
||||
statusCode, msg := private.ResumeLogging(ctx)
|
||||
switch statusCode {
|
||||
case http.StatusInternalServerError:
|
||||
return fail("InternalServerError", msg)
|
||||
}
|
||||
|
||||
fmt.Fprintln(os.Stdout, msg)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -294,17 +382,28 @@ func runReleaseReopenLogging(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
setup(ctx, c.Bool("debug"))
|
||||
userMsg := private.ReleaseReopenLogging(ctx)
|
||||
_, _ = fmt.Fprintln(os.Stdout, userMsg)
|
||||
setup("manager", c.Bool("debug"))
|
||||
statusCode, msg := private.ReleaseReopenLogging(ctx)
|
||||
switch statusCode {
|
||||
case http.StatusInternalServerError:
|
||||
return fail("InternalServerError", msg)
|
||||
}
|
||||
|
||||
fmt.Fprintln(os.Stdout, msg)
|
||||
return nil
|
||||
}
|
||||
|
||||
func runSetLogSQL(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
setup(ctx, c.Bool("debug"))
|
||||
setup("manager", c.Bool("debug"))
|
||||
|
||||
extra := private.SetLogSQL(ctx, !c.Bool("off"))
|
||||
return handleCliResponseExtra(extra)
|
||||
statusCode, msg := private.SetLogSQL(ctx, !c.Bool("off"))
|
||||
switch statusCode {
|
||||
case http.StatusInternalServerError:
|
||||
return fail("InternalServerError", msg)
|
||||
}
|
||||
|
||||
fmt.Fprintln(os.Stdout, msg)
|
||||
return nil
|
||||
}
|
||||
|
||||
+14
-34
@@ -8,7 +8,6 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
actions_model "code.gitea.io/gitea/models/actions"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
git_model "code.gitea.io/gitea/models/git"
|
||||
"code.gitea.io/gitea/models/migrations"
|
||||
@@ -33,7 +32,7 @@ var CmdMigrateStorage = cli.Command{
|
||||
cli.StringFlag{
|
||||
Name: "type, t",
|
||||
Value: "",
|
||||
Usage: "Type of stored files to copy. Allowed types: 'attachments', 'lfs', 'avatars', 'repo-avatars', 'repo-archivers', 'packages', 'actions-log'",
|
||||
Usage: "Type of stored files to copy. Allowed types: 'attachments', 'lfs', 'avatars', 'repo-avatars', 'repo-archivers', 'packages'",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "storage, s",
|
||||
@@ -135,22 +134,6 @@ func migratePackages(ctx context.Context, dstStorage storage.ObjectStorage) erro
|
||||
})
|
||||
}
|
||||
|
||||
func migrateActionsLog(ctx context.Context, dstStorage storage.ObjectStorage) error {
|
||||
return db.Iterate(ctx, nil, func(ctx context.Context, task *actions_model.ActionTask) error {
|
||||
if task.LogExpired {
|
||||
// the log has been cleared
|
||||
return nil
|
||||
}
|
||||
if !task.LogInStorage {
|
||||
// running tasks store logs in DBFS
|
||||
return nil
|
||||
}
|
||||
p := task.LogFilename
|
||||
_, err := storage.Copy(dstStorage, p, storage.Actions, p)
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
func runMigrateStorage(ctx *cli.Context) error {
|
||||
stdCtx, cancel := installSignals()
|
||||
defer cancel()
|
||||
@@ -179,7 +162,7 @@ func runMigrateStorage(ctx *cli.Context) error {
|
||||
switch strings.ToLower(ctx.String("storage")) {
|
||||
case "":
|
||||
fallthrough
|
||||
case string(setting.LocalStorageType):
|
||||
case string(storage.LocalStorageType):
|
||||
p := ctx.String("path")
|
||||
if p == "" {
|
||||
log.Fatal("Path must be given when storage is loal")
|
||||
@@ -187,24 +170,22 @@ func runMigrateStorage(ctx *cli.Context) error {
|
||||
}
|
||||
dstStorage, err = storage.NewLocalStorage(
|
||||
stdCtx,
|
||||
&setting.Storage{
|
||||
storage.LocalStorageConfig{
|
||||
Path: p,
|
||||
})
|
||||
case string(setting.MinioStorageType):
|
||||
case string(storage.MinioStorageType):
|
||||
dstStorage, err = storage.NewMinioStorage(
|
||||
stdCtx,
|
||||
&setting.Storage{
|
||||
MinioConfig: setting.MinioStorageConfig{
|
||||
Endpoint: ctx.String("minio-endpoint"),
|
||||
AccessKeyID: ctx.String("minio-access-key-id"),
|
||||
SecretAccessKey: ctx.String("minio-secret-access-key"),
|
||||
Bucket: ctx.String("minio-bucket"),
|
||||
Location: ctx.String("minio-location"),
|
||||
BasePath: ctx.String("minio-base-path"),
|
||||
UseSSL: ctx.Bool("minio-use-ssl"),
|
||||
InsecureSkipVerify: ctx.Bool("minio-insecure-skip-verify"),
|
||||
ChecksumAlgorithm: ctx.String("minio-checksum-algorithm"),
|
||||
},
|
||||
storage.MinioStorageConfig{
|
||||
Endpoint: ctx.String("minio-endpoint"),
|
||||
AccessKeyID: ctx.String("minio-access-key-id"),
|
||||
SecretAccessKey: ctx.String("minio-secret-access-key"),
|
||||
Bucket: ctx.String("minio-bucket"),
|
||||
Location: ctx.String("minio-location"),
|
||||
BasePath: ctx.String("minio-base-path"),
|
||||
UseSSL: ctx.Bool("minio-use-ssl"),
|
||||
InsecureSkipVerify: ctx.Bool("minio-insecure-skip-verify"),
|
||||
ChecksumAlgorithm: ctx.String("minio-checksum-algorithm"),
|
||||
})
|
||||
default:
|
||||
return fmt.Errorf("unsupported storage type: %s", ctx.String("storage"))
|
||||
@@ -220,7 +201,6 @@ func runMigrateStorage(ctx *cli.Context) error {
|
||||
"repo-avatars": migrateRepoAvatars,
|
||||
"repo-archivers": migrateRepoArchivers,
|
||||
"packages": migratePackages,
|
||||
"actions-log": migrateActionsLog,
|
||||
}
|
||||
|
||||
tp := strings.ToLower(ctx.String("type"))
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
packages_module "code.gitea.io/gitea/modules/packages"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/storage"
|
||||
packages_service "code.gitea.io/gitea/services/packages"
|
||||
|
||||
@@ -26,7 +25,7 @@ func TestMigratePackages(t *testing.T) {
|
||||
creator := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||
|
||||
content := "package main\n\nfunc main() {\nfmt.Println(\"hi\")\n}\n"
|
||||
buf, err := packages_module.CreateHashedBufferFromReaderWithSize(strings.NewReader(content), 1024)
|
||||
buf, err := packages_module.CreateHashedBufferFromReader(strings.NewReader(content), 1024)
|
||||
assert.NoError(t, err)
|
||||
defer buf.Close()
|
||||
|
||||
@@ -58,7 +57,7 @@ func TestMigratePackages(t *testing.T) {
|
||||
|
||||
dstStorage, err := storage.NewLocalStorage(
|
||||
ctx,
|
||||
&setting.Storage{
|
||||
storage.LocalStorageConfig{
|
||||
Path: p,
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
@@ -68,7 +67,7 @@ func TestMigratePackages(t *testing.T) {
|
||||
|
||||
entries, err := os.ReadDir(p)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, entries, 2)
|
||||
assert.EqualValues(t, 2, len(entries))
|
||||
assert.EqualValues(t, "01", entries[0].Name())
|
||||
assert.EqualValues(t, "tmp", entries[1].Name())
|
||||
}
|
||||
|
||||
+12
-3
@@ -4,8 +4,11 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/private"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
@@ -51,12 +54,13 @@ func runRestoreRepository(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
setting.MustInstalled()
|
||||
setting.InitProviderFromExistingFile()
|
||||
setting.LoadCommonSettings()
|
||||
var units []string
|
||||
if s := c.String("units"); s != "" {
|
||||
units = strings.Split(s, ",")
|
||||
}
|
||||
extra := private.RestoreRepo(
|
||||
statusCode, errStr := private.RestoreRepo(
|
||||
ctx,
|
||||
c.String("repo_dir"),
|
||||
c.String("owner_name"),
|
||||
@@ -64,5 +68,10 @@ func runRestoreRepository(c *cli.Context) error {
|
||||
units,
|
||||
c.Bool("validation"),
|
||||
)
|
||||
return handleCliResponseExtra(extra)
|
||||
if statusCode == http.StatusOK {
|
||||
return nil
|
||||
}
|
||||
|
||||
log.Fatal("Failed to restore repository: %v", errStr)
|
||||
return errors.New(errStr)
|
||||
}
|
||||
|
||||
+47
-61
@@ -7,6 +7,7 @@ package cmd
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
@@ -15,7 +16,6 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode"
|
||||
|
||||
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||
git_model "code.gitea.io/gitea/models/git"
|
||||
@@ -44,7 +44,6 @@ var CmdServ = cli.Command{
|
||||
Name: "serv",
|
||||
Usage: "This command should only be called by SSH shell",
|
||||
Description: "Serv provides access auth for repositories",
|
||||
Before: PrepareConsoleLoggerLevel(log.FATAL),
|
||||
Action: runServ,
|
||||
Flags: []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
@@ -56,13 +55,15 @@ var CmdServ = cli.Command{
|
||||
},
|
||||
}
|
||||
|
||||
func setup(ctx context.Context, debug bool) {
|
||||
func setup(logPath string, debug bool) {
|
||||
_ = log.DelLogger("console")
|
||||
if debug {
|
||||
setupConsoleLogger(log.TRACE, false, os.Stderr)
|
||||
_ = log.NewLogger(1000, "console", "console", `{"level":"trace","stacktracelevel":"NONE","stderr":true}`)
|
||||
} else {
|
||||
setupConsoleLogger(log.FATAL, false, os.Stderr)
|
||||
_ = log.NewLogger(1000, "console", "console", `{"level":"fatal","stacktracelevel":"NONE","stderr":true}`)
|
||||
}
|
||||
setting.MustInstalled()
|
||||
setting.InitProviderFromExistingFile()
|
||||
setting.LoadCommonSettings()
|
||||
if debug {
|
||||
setting.RunMode = "dev"
|
||||
}
|
||||
@@ -71,15 +72,15 @@ func setup(ctx context.Context, debug bool) {
|
||||
// `[repository]` `ROOT` is a relative path and $GITEA_WORK_DIR isn't passed to the SSH connection.
|
||||
if _, err := os.Stat(setting.RepoRootPath); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
_ = fail(ctx, "Incorrect configuration, no repository directory.", "Directory `[repository].ROOT` %q was not found, please check if $GITEA_WORK_DIR is passed to the SSH connection or make `[repository].ROOT` an absolute value.", setting.RepoRootPath)
|
||||
_ = fail("Incorrect configuration, no repository directory.", "Directory `[repository].ROOT` %q was not found, please check if $GITEA_WORK_DIR is passed to the SSH connection or make `[repository].ROOT` an absolute value.", setting.RepoRootPath)
|
||||
} else {
|
||||
_ = fail(ctx, "Incorrect configuration, repository directory is inaccessible", "Directory `[repository].ROOT` %q is inaccessible. err: %v", setting.RepoRootPath, err)
|
||||
_ = fail("Incorrect configuration, repository directory is inaccessible", "Directory `[repository].ROOT` %q is inaccessible. err: %v", setting.RepoRootPath, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if err := git.InitSimple(context.Background()); err != nil {
|
||||
_ = fail(ctx, "Failed to init git", "Failed to init git, err: %v", err)
|
||||
_ = fail("Failed to init git", "Failed to init git, err: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,54 +94,32 @@ var (
|
||||
alphaDashDotPattern = regexp.MustCompile(`[^\w-\.]`)
|
||||
)
|
||||
|
||||
// fail prints message to stdout, it's mainly used for git serv and git hook commands.
|
||||
// The output will be passed to git client and shown to user.
|
||||
func fail(ctx context.Context, userMessage, logMsgFmt string, args ...any) error {
|
||||
if userMessage == "" {
|
||||
userMessage = "Internal Server Error (no specific error)"
|
||||
}
|
||||
|
||||
func fail(userMessage, logMessage string, args ...interface{}) error {
|
||||
// There appears to be a chance to cause a zombie process and failure to read the Exit status
|
||||
// if nothing is outputted on stdout.
|
||||
_, _ = fmt.Fprintln(os.Stdout, "")
|
||||
_, _ = fmt.Fprintln(os.Stderr, "Gitea:", userMessage)
|
||||
|
||||
if logMsgFmt != "" {
|
||||
logMsg := fmt.Sprintf(logMsgFmt, args...)
|
||||
if len(logMessage) > 0 {
|
||||
if !setting.IsProd {
|
||||
_, _ = fmt.Fprintln(os.Stderr, "Gitea:", logMsg)
|
||||
_, _ = fmt.Fprintf(os.Stderr, logMessage+"\n", args...)
|
||||
}
|
||||
if userMessage != "" {
|
||||
if unicode.IsPunct(rune(userMessage[len(userMessage)-1])) {
|
||||
logMsg = userMessage + " " + logMsg
|
||||
} else {
|
||||
logMsg = userMessage + ". " + logMsg
|
||||
}
|
||||
}
|
||||
_ = private.SSHLog(ctx, true, logMsg)
|
||||
}
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if len(logMessage) > 0 {
|
||||
_ = private.SSHLog(ctx, true, fmt.Sprintf(logMessage+": ", args...))
|
||||
}
|
||||
return cli.NewExitError("", 1)
|
||||
}
|
||||
|
||||
// handleCliResponseExtra handles the extra response from the cli sub-commands
|
||||
// If there is a user message it will be printed to stdout
|
||||
// If the command failed it will return an error (the error will be printed by cli framework)
|
||||
func handleCliResponseExtra(extra private.ResponseExtra) error {
|
||||
if extra.UserMsg != "" {
|
||||
_, _ = fmt.Fprintln(os.Stdout, extra.UserMsg)
|
||||
}
|
||||
if extra.HasError() {
|
||||
return cli.NewExitError(extra.Error, 1)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func runServ(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
// FIXME: This needs to internationalised
|
||||
setup(ctx, c.Bool("debug"))
|
||||
setup("serv.log", c.Bool("debug"))
|
||||
|
||||
if setting.SSH.Disabled {
|
||||
println("Gitea: SSH has been disabled")
|
||||
@@ -156,18 +135,18 @@ func runServ(c *cli.Context) error {
|
||||
|
||||
keys := strings.Split(c.Args()[0], "-")
|
||||
if len(keys) != 2 || keys[0] != "key" {
|
||||
return fail(ctx, "Key ID format error", "Invalid key argument: %s", c.Args()[0])
|
||||
return fail("Key ID format error", "Invalid key argument: %s", c.Args()[0])
|
||||
}
|
||||
keyID, err := strconv.ParseInt(keys[1], 10, 64)
|
||||
if err != nil {
|
||||
return fail(ctx, "Key ID parsing error", "Invalid key argument: %s", c.Args()[1])
|
||||
return fail("Key ID format error", "Invalid key argument: %s", c.Args()[1])
|
||||
}
|
||||
|
||||
cmd := os.Getenv("SSH_ORIGINAL_COMMAND")
|
||||
if len(cmd) == 0 {
|
||||
key, user, err := private.ServNoCommand(ctx, keyID)
|
||||
if err != nil {
|
||||
return fail(ctx, "Key check failed", "Failed to check provided key: %v", err)
|
||||
return fail("Internal error", "Failed to check provided key: %v", err)
|
||||
}
|
||||
switch key.Type {
|
||||
case asymkey_model.KeyTypeDeploy:
|
||||
@@ -185,7 +164,7 @@ func runServ(c *cli.Context) error {
|
||||
|
||||
words, err := shellquote.Split(cmd)
|
||||
if err != nil {
|
||||
return fail(ctx, "Error parsing arguments", "Failed to parse arguments: %v", err)
|
||||
return fail("Error parsing arguments", "Failed to parse arguments: %v", err)
|
||||
}
|
||||
|
||||
if len(words) < 2 {
|
||||
@@ -196,7 +175,7 @@ func runServ(c *cli.Context) error {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return fail(ctx, "Too few arguments", "Too few arguments in cmd: %s", cmd)
|
||||
return fail("Too few arguments", "Too few arguments in cmd: %s", cmd)
|
||||
}
|
||||
|
||||
verb := words[0]
|
||||
@@ -208,7 +187,7 @@ func runServ(c *cli.Context) error {
|
||||
var lfsVerb string
|
||||
if verb == lfsAuthenticateVerb {
|
||||
if !setting.LFS.StartServer {
|
||||
return fail(ctx, "Unknown git command", "LFS authentication request over SSH denied, LFS support is disabled")
|
||||
return fail("Unknown git command", "LFS authentication request over SSH denied, LFS support is disabled")
|
||||
}
|
||||
|
||||
if len(words) > 2 {
|
||||
@@ -221,37 +200,37 @@ func runServ(c *cli.Context) error {
|
||||
|
||||
rr := strings.SplitN(repoPath, "/", 2)
|
||||
if len(rr) != 2 {
|
||||
return fail(ctx, "Invalid repository path", "Invalid repository path: %v", repoPath)
|
||||
return fail("Invalid repository path", "Invalid repository path: %v", repoPath)
|
||||
}
|
||||
|
||||
username := strings.ToLower(rr[0])
|
||||
reponame := strings.ToLower(strings.TrimSuffix(rr[1], ".git"))
|
||||
|
||||
if alphaDashDotPattern.MatchString(reponame) {
|
||||
return fail(ctx, "Invalid repo name", "Invalid repo name: %s", reponame)
|
||||
return fail("Invalid repo name", "Invalid repo name: %s", reponame)
|
||||
}
|
||||
|
||||
if c.Bool("enable-pprof") {
|
||||
if err := os.MkdirAll(setting.PprofDataPath, os.ModePerm); err != nil {
|
||||
return fail(ctx, "Error while trying to create PPROF_DATA_PATH", "Error while trying to create PPROF_DATA_PATH: %v", err)
|
||||
return fail("Error while trying to create PPROF_DATA_PATH", "Error while trying to create PPROF_DATA_PATH: %v", err)
|
||||
}
|
||||
|
||||
stopCPUProfiler, err := pprof.DumpCPUProfileForUsername(setting.PprofDataPath, username)
|
||||
if err != nil {
|
||||
return fail(ctx, "Unable to start CPU profiler", "Unable to start CPU profile: %v", err)
|
||||
return fail("Internal Server Error", "Unable to start CPU profile: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
stopCPUProfiler()
|
||||
err := pprof.DumpMemProfileForUsername(setting.PprofDataPath, username)
|
||||
if err != nil {
|
||||
_ = fail(ctx, "Unable to dump Mem profile", "Unable to dump Mem Profile: %v", err)
|
||||
_ = fail("Internal Server Error", "Unable to dump Mem Profile: %v", err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
requestedMode, has := allowedCommands[verb]
|
||||
if !has {
|
||||
return fail(ctx, "Unknown git command", "Unknown git command %s", verb)
|
||||
return fail("Unknown git command", "Unknown git command %s", verb)
|
||||
}
|
||||
|
||||
if verb == lfsAuthenticateVerb {
|
||||
@@ -260,13 +239,20 @@ func runServ(c *cli.Context) error {
|
||||
} else if lfsVerb == "download" {
|
||||
requestedMode = perm.AccessModeRead
|
||||
} else {
|
||||
return fail(ctx, "Unknown LFS verb", "Unknown lfs verb %s", lfsVerb)
|
||||
return fail("Unknown LFS verb", "Unknown lfs verb %s", lfsVerb)
|
||||
}
|
||||
}
|
||||
|
||||
results, extra := private.ServCommand(ctx, keyID, username, reponame, requestedMode, verb, lfsVerb)
|
||||
if extra.HasError() {
|
||||
return fail(ctx, extra.UserMsg, "ServCommand failed: %s", extra.Error)
|
||||
results, err := private.ServCommand(ctx, keyID, username, reponame, requestedMode, verb, lfsVerb)
|
||||
if err != nil {
|
||||
if private.IsErrServCommand(err) {
|
||||
errServCommand := err.(private.ErrServCommand)
|
||||
if errServCommand.StatusCode != http.StatusInternalServerError {
|
||||
return fail("Unauthorized", "%s", errServCommand.Error())
|
||||
}
|
||||
return fail("Internal Server Error", "%s", errServCommand.Error())
|
||||
}
|
||||
return fail("Internal Server Error", "%s", err.Error())
|
||||
}
|
||||
|
||||
// LFS token authentication
|
||||
@@ -288,7 +274,7 @@ func runServ(c *cli.Context) error {
|
||||
// Sign and get the complete encoded token as a string using the secret
|
||||
tokenString, err := token.SignedString(setting.LFS.JWTSecretBytes)
|
||||
if err != nil {
|
||||
return fail(ctx, "Failed to sign JWT Token", "Failed to sign JWT token: %v", err)
|
||||
return fail("Internal error", "Failed to sign JWT token: %v", err)
|
||||
}
|
||||
|
||||
tokenAuthentication := &git_model.LFSTokenResponse{
|
||||
@@ -300,7 +286,7 @@ func runServ(c *cli.Context) error {
|
||||
enc := json.NewEncoder(os.Stdout)
|
||||
err = enc.Encode(tokenAuthentication)
|
||||
if err != nil {
|
||||
return fail(ctx, "Failed to encode LFS json response", "Failed to encode LFS json response: %v", err)
|
||||
return fail("Internal error", "Failed to encode LFS json response: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -346,13 +332,13 @@ func runServ(c *cli.Context) error {
|
||||
gitcmd.Env = append(gitcmd.Env, git.CommonCmdServEnvs()...)
|
||||
|
||||
if err = gitcmd.Run(); err != nil {
|
||||
return fail(ctx, "Failed to execute git command", "Failed to execute git command: %v", err)
|
||||
return fail("Internal error", "Failed to execute git command: %v", err)
|
||||
}
|
||||
|
||||
// Update user key activity.
|
||||
if results.KeyID > 0 {
|
||||
if err = private.UpdatePublicKeyInRepo(ctx, results.KeyID, results.RepoID); err != nil {
|
||||
return fail(ctx, "Failed to update public key", "UpdatePublicKeyInRepo: %v", err)
|
||||
return fail("Internal error", "UpdatePublicKeyInRepo: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+77
-142
@@ -9,8 +9,6 @@ import (
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
_ "net/http/pprof" // Used for debugging if enabled and a web server is running
|
||||
@@ -24,18 +22,15 @@ import (
|
||||
|
||||
"github.com/felixge/fgprof"
|
||||
"github.com/urfave/cli"
|
||||
ini "gopkg.in/ini.v1"
|
||||
)
|
||||
|
||||
// PIDFile could be set from build tag
|
||||
var PIDFile = "/run/gitea.pid"
|
||||
|
||||
// CmdWeb represents the available web sub-command.
|
||||
var CmdWeb = cli.Command{
|
||||
Name: "web",
|
||||
Usage: "Start Gitea web server",
|
||||
Description: `Gitea web server is the only thing you need to run,
|
||||
and it takes care of all the other things for you`,
|
||||
Before: PrepareConsoleLoggerLevel(log.INFO),
|
||||
Action: runWeb,
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
@@ -50,7 +45,7 @@ and it takes care of all the other things for you`,
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "pid, P",
|
||||
Value: PIDFile,
|
||||
Value: setting.PIDFile,
|
||||
Usage: "Custom pid file path",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
@@ -86,127 +81,14 @@ func runHTTPRedirector() {
|
||||
}
|
||||
}
|
||||
|
||||
func createPIDFile(pidPath string) {
|
||||
currentPid := os.Getpid()
|
||||
if err := os.MkdirAll(filepath.Dir(pidPath), os.ModePerm); err != nil {
|
||||
log.Fatal("Failed to create PID folder: %v", err)
|
||||
}
|
||||
|
||||
file, err := os.Create(pidPath)
|
||||
if err != nil {
|
||||
log.Fatal("Failed to create PID file: %v", err)
|
||||
}
|
||||
defer file.Close()
|
||||
if _, err := file.WriteString(strconv.FormatInt(int64(currentPid), 10)); err != nil {
|
||||
log.Fatal("Failed to write PID information: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func serveInstall(ctx *cli.Context) error {
|
||||
log.Info("Gitea version: %s%s", setting.AppVer, setting.AppBuiltWith)
|
||||
log.Info("App path: %s", setting.AppPath)
|
||||
log.Info("Work path: %s", setting.AppWorkPath)
|
||||
log.Info("Custom path: %s", setting.CustomPath)
|
||||
log.Info("Config file: %s", setting.CustomConf)
|
||||
log.Info("Prepare to run install page")
|
||||
|
||||
routers.InitWebInstallPage(graceful.GetManager().HammerContext())
|
||||
|
||||
// Flag for port number in case first time run conflict
|
||||
if ctx.IsSet("port") {
|
||||
if err := setPort(ctx.String("port")); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if ctx.IsSet("install-port") {
|
||||
if err := setPort(ctx.String("install-port")); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
c := install.Routes()
|
||||
err := listen(c, false)
|
||||
if err != nil {
|
||||
log.Critical("Unable to open listener for installer. Is Gitea already running?")
|
||||
graceful.GetManager().DoGracefulShutdown()
|
||||
}
|
||||
select {
|
||||
case <-graceful.GetManager().IsShutdown():
|
||||
<-graceful.GetManager().Done()
|
||||
log.Info("PID: %d Gitea Web Finished", os.Getpid())
|
||||
log.GetManager().Close()
|
||||
return err
|
||||
default:
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func serveInstalled(ctx *cli.Context) error {
|
||||
setting.InitCfgProvider(setting.CustomConf)
|
||||
setting.LoadCommonSettings()
|
||||
setting.MustInstalled()
|
||||
|
||||
log.Info("Gitea version: %s%s", setting.AppVer, setting.AppBuiltWith)
|
||||
log.Info("App path: %s", setting.AppPath)
|
||||
log.Info("Work path: %s", setting.AppWorkPath)
|
||||
log.Info("Custom path: %s", setting.CustomPath)
|
||||
log.Info("Config file: %s", setting.CustomConf)
|
||||
log.Info("Run mode: %s", setting.RunMode)
|
||||
log.Info("Prepare to run web server")
|
||||
|
||||
if setting.AppWorkPathMismatch {
|
||||
log.Error("WORK_PATH from config %q doesn't match other paths from environment variables or command arguments. "+
|
||||
"Only WORK_PATH in config should be set and used. Please remove the other outdated work paths from environment variables and command arguments", setting.CustomConf)
|
||||
}
|
||||
|
||||
rootCfg := setting.CfgProvider
|
||||
if rootCfg.Section("").Key("WORK_PATH").String() == "" {
|
||||
saveCfg, err := rootCfg.PrepareSaving()
|
||||
if err != nil {
|
||||
log.Error("Unable to prepare saving WORK_PATH=%s to config %q: %v\nYou must set it manually, otherwise there might be bugs when accessing the git repositories.", setting.AppWorkPath, setting.CustomConf, err)
|
||||
} else {
|
||||
rootCfg.Section("").Key("WORK_PATH").SetValue(setting.AppWorkPath)
|
||||
saveCfg.Section("").Key("WORK_PATH").SetValue(setting.AppWorkPath)
|
||||
if err = saveCfg.Save(); err != nil {
|
||||
log.Error("Unable to update WORK_PATH=%s to config %q: %v\nYou must set it manually, otherwise there might be bugs when accessing the git repositories.", setting.AppWorkPath, setting.CustomConf, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
routers.InitWebInstalled(graceful.GetManager().HammerContext())
|
||||
|
||||
// We check that AppDataPath exists here (it should have been created during installation)
|
||||
// We can't check it in `InitWebInstalled`, because some integration tests
|
||||
// use cmd -> InitWebInstalled, but the AppDataPath doesn't exist during those tests.
|
||||
if _, err := os.Stat(setting.AppDataPath); err != nil {
|
||||
log.Fatal("Can not find APP_DATA_PATH %q", setting.AppDataPath)
|
||||
}
|
||||
|
||||
// Override the provided port number within the configuration
|
||||
if ctx.IsSet("port") {
|
||||
if err := setPort(ctx.String("port")); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Set up Chi routes
|
||||
c := routers.NormalRoutes(graceful.GetManager().HammerContext())
|
||||
err := listen(c, true)
|
||||
<-graceful.GetManager().Done()
|
||||
log.Info("PID: %d Gitea Web Finished", os.Getpid())
|
||||
log.GetManager().Close()
|
||||
return err
|
||||
}
|
||||
|
||||
func servePprof() {
|
||||
http.DefaultServeMux.Handle("/debug/fgprof", fgprof.Handler())
|
||||
_, _, finished := process.GetManager().AddTypedContext(context.Background(), "Web: PProf Server", process.SystemProcessType, true)
|
||||
// The pprof server is for debug purpose only, it shouldn't be exposed on public network. At the moment it's not worth to introduce a configurable option for it.
|
||||
log.Info("Starting pprof server on localhost:6060")
|
||||
log.Info("Stopped pprof server: %v", http.ListenAndServe("localhost:6060", nil))
|
||||
finished()
|
||||
}
|
||||
|
||||
func runWeb(ctx *cli.Context) error {
|
||||
if ctx.Bool("verbose") {
|
||||
_ = log.DelLogger("console")
|
||||
log.NewLogger(0, "console", "console", fmt.Sprintf(`{"level": "trace", "colorize": %t, "stacktraceLevel": "none"}`, log.CanColorStdout))
|
||||
} else if ctx.Bool("quiet") {
|
||||
_ = log.DelLogger("console")
|
||||
log.NewLogger(0, "console", "console", fmt.Sprintf(`{"level": "fatal", "colorize": %t, "stacktraceLevel": "none"}`, log.CanColorStdout))
|
||||
}
|
||||
defer func() {
|
||||
if panicked := recover(); panicked != nil {
|
||||
log.Fatal("PANIC: %v\n%s", panicked, log.Stack(2))
|
||||
@@ -225,22 +107,82 @@ func runWeb(ctx *cli.Context) error {
|
||||
|
||||
// Set pid file setting
|
||||
if ctx.IsSet("pid") {
|
||||
createPIDFile(ctx.String("pid"))
|
||||
setting.PIDFile = ctx.String("pid")
|
||||
setting.WritePIDFile = true
|
||||
}
|
||||
|
||||
if !setting.InstallLock {
|
||||
if err := serveInstall(ctx); err != nil {
|
||||
// Perform pre-initialization
|
||||
needsInstall := install.PreloadSettings(graceful.GetManager().HammerContext())
|
||||
if needsInstall {
|
||||
// Flag for port number in case first time run conflict
|
||||
if ctx.IsSet("port") {
|
||||
if err := setPort(ctx.String("port")); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if ctx.IsSet("install-port") {
|
||||
if err := setPort(ctx.String("install-port")); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
installCtx, cancel := context.WithCancel(graceful.GetManager().HammerContext())
|
||||
c := install.Routes(installCtx)
|
||||
err := listen(c, false)
|
||||
cancel()
|
||||
if err != nil {
|
||||
log.Critical("Unable to open listener for installer. Is Gitea already running?")
|
||||
graceful.GetManager().DoGracefulShutdown()
|
||||
}
|
||||
select {
|
||||
case <-graceful.GetManager().IsShutdown():
|
||||
<-graceful.GetManager().Done()
|
||||
log.Info("PID: %d Gitea Web Finished", os.Getpid())
|
||||
log.Close()
|
||||
return err
|
||||
default:
|
||||
}
|
||||
} else {
|
||||
NoInstallListener()
|
||||
}
|
||||
|
||||
if setting.EnablePprof {
|
||||
go servePprof()
|
||||
go func() {
|
||||
http.DefaultServeMux.Handle("/debug/fgprof", fgprof.Handler())
|
||||
_, _, finished := process.GetManager().AddTypedContext(context.Background(), "Web: PProf Server", process.SystemProcessType, true)
|
||||
// The pprof server is for debug purpose only, it shouldn't be exposed on public network. At the moment it's not worth to introduce a configurable option for it.
|
||||
log.Info("Starting pprof server on localhost:6060")
|
||||
log.Info("Stopped pprof server: %v", http.ListenAndServe("localhost:6060", nil))
|
||||
finished()
|
||||
}()
|
||||
}
|
||||
|
||||
return serveInstalled(ctx)
|
||||
log.Info("Global init")
|
||||
// Perform global initialization
|
||||
setting.InitProviderFromExistingFile()
|
||||
setting.LoadCommonSettings()
|
||||
routers.GlobalInitInstalled(graceful.GetManager().HammerContext())
|
||||
|
||||
// We check that AppDataPath exists here (it should have been created during installation)
|
||||
// We can't check it in `GlobalInitInstalled`, because some integration tests
|
||||
// use cmd -> GlobalInitInstalled, but the AppDataPath doesn't exist during those tests.
|
||||
if _, err := os.Stat(setting.AppDataPath); err != nil {
|
||||
log.Fatal("Can not find APP_DATA_PATH '%s'", setting.AppDataPath)
|
||||
}
|
||||
|
||||
// Override the provided port number within the configuration
|
||||
if ctx.IsSet("port") {
|
||||
if err := setPort(ctx.String("port")); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Set up Chi routes
|
||||
c := routers.NormalRoutes(graceful.GetManager().HammerContext())
|
||||
err := listen(c, true)
|
||||
<-graceful.GetManager().Done()
|
||||
log.Info("PID: %d Gitea Web Finished", os.Getpid())
|
||||
log.Close()
|
||||
return err
|
||||
}
|
||||
|
||||
func setPort(port string) error {
|
||||
@@ -261,16 +203,9 @@ func setPort(port string) error {
|
||||
defaultLocalURL += ":" + setting.HTTPPort + "/"
|
||||
|
||||
// Save LOCAL_ROOT_URL if port changed
|
||||
rootCfg := setting.CfgProvider
|
||||
saveCfg, err := rootCfg.PrepareSaving()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to save config file: %v", err)
|
||||
}
|
||||
rootCfg.Section("server").Key("LOCAL_ROOT_URL").SetValue(defaultLocalURL)
|
||||
saveCfg.Section("server").Key("LOCAL_ROOT_URL").SetValue(defaultLocalURL)
|
||||
if err = saveCfg.Save(); err != nil {
|
||||
return fmt.Errorf("failed to save config file: %v", err)
|
||||
}
|
||||
setting.CreateOrAppendToCustomConf("server.LOCAL_ROOT_URL", func(cfg *ini.File) {
|
||||
cfg.Section("server").Key("LOCAL_ROOT_URL").SetValue(defaultLocalURL)
|
||||
})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Executable
+2
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
su git -c "/home/git/gogs/scripts/gogs_supervisord.sh restart"
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
//nolint:forbidigo
|
||||
package main
|
||||
|
||||
import (
|
||||
@@ -17,7 +16,7 @@ import (
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/google/go-github/v52/github"
|
||||
"github.com/google/go-github/v45/github"
|
||||
"github.com/urfave/cli"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
@@ -5,13 +5,21 @@ package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
ini "gopkg.in/ini.v1"
|
||||
)
|
||||
|
||||
// EnvironmentPrefix environment variables prefixed with this represent ini values to write
|
||||
const EnvironmentPrefix = "GITEA"
|
||||
|
||||
func main() {
|
||||
app := cli.NewApp()
|
||||
app.Name = "environment-to-ini"
|
||||
@@ -24,10 +32,6 @@ func main() {
|
||||
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"
|
||||
will be mapped to the ini section "[section_name]" and the key
|
||||
"KEY_NAME" with the value loaded from the specified file.
|
||||
|
||||
Environment variables are usually restricted to a reduced character
|
||||
set "0-9A-Z_" - in order to allow the setting of sections with
|
||||
characters outside of that set, they should be escaped as following:
|
||||
@@ -66,8 +70,19 @@ func main() {
|
||||
Value: "",
|
||||
Usage: "Destination file to write to",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "clear",
|
||||
Usage: "Clears the matched variables from the environment",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "prefix, p",
|
||||
Value: EnvironmentPrefix,
|
||||
Usage: "Environment prefix to look for - will be suffixed by __ (2 underscores)",
|
||||
},
|
||||
}
|
||||
app.Action = runEnvironmentToIni
|
||||
setting.SetCustomPathAndConf("", "", "")
|
||||
|
||||
err := app.Run(os.Args)
|
||||
if err != nil {
|
||||
log.Fatal("Failed to run app with %s: %v", os.Args, err)
|
||||
@@ -75,22 +90,66 @@ func main() {
|
||||
}
|
||||
|
||||
func runEnvironmentToIni(c *cli.Context) error {
|
||||
// the config system may change the environment variables, so get a copy first, to be used later
|
||||
env := append([]string{}, os.Environ()...)
|
||||
setting.InitWorkPathAndCfgProvider(os.Getenv, setting.ArgWorkPathAndCustomConf{
|
||||
WorkPath: c.String("work-path"),
|
||||
CustomPath: c.String("custom-path"),
|
||||
CustomConf: c.String("config"),
|
||||
})
|
||||
providedCustom := c.String("custom-path")
|
||||
providedConf := c.String("config")
|
||||
providedWorkPath := c.String("work-path")
|
||||
setting.SetCustomPathAndConf(providedCustom, providedConf, providedWorkPath)
|
||||
|
||||
cfg, err := setting.NewConfigProviderFromFile(setting.CustomConf)
|
||||
cfg := ini.Empty()
|
||||
isFile, err := util.IsFile(setting.CustomConf)
|
||||
if err != nil {
|
||||
log.Fatal("Failed to load custom conf '%s': %v", setting.CustomConf, err)
|
||||
log.Fatal("Unable to check if %s is a file. Error: %v", setting.CustomConf, err)
|
||||
}
|
||||
if isFile {
|
||||
if err := cfg.Append(setting.CustomConf); err != nil {
|
||||
log.Fatal("Failed to load custom conf '%s': %v", setting.CustomConf, err)
|
||||
}
|
||||
} else {
|
||||
log.Warn("Custom config '%s' not found, ignore this if you're running first time", setting.CustomConf)
|
||||
}
|
||||
cfg.NameMapper = ini.SnackCase
|
||||
|
||||
changed := setting.EnvironmentToConfig(cfg, env)
|
||||
changed := false
|
||||
|
||||
// try to save the config file
|
||||
prefix := c.String("prefix") + "__"
|
||||
|
||||
for _, kv := range os.Environ() {
|
||||
idx := strings.IndexByte(kv, '=')
|
||||
if idx < 0 {
|
||||
continue
|
||||
}
|
||||
eKey := kv[:idx]
|
||||
value := kv[idx+1:]
|
||||
if !strings.HasPrefix(eKey, prefix) {
|
||||
continue
|
||||
}
|
||||
eKey = eKey[len(prefix):]
|
||||
sectionName, keyName := DecodeSectionKey(eKey)
|
||||
if len(keyName) == 0 {
|
||||
continue
|
||||
}
|
||||
section, err := cfg.GetSection(sectionName)
|
||||
if err != nil {
|
||||
section, err = cfg.NewSection(sectionName)
|
||||
if err != nil {
|
||||
log.Error("Error creating section: %s : %v", sectionName, err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
key := section.Key(keyName)
|
||||
if key == nil {
|
||||
key, err = section.NewKey(keyName, value)
|
||||
if err != nil {
|
||||
log.Error("Error creating key: %s in section: %s with value: %s : %v", keyName, sectionName, value, err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
oldValue := key.Value()
|
||||
if !changed && oldValue != value {
|
||||
changed = true
|
||||
}
|
||||
key.SetValue(value)
|
||||
}
|
||||
destination := c.String("out")
|
||||
if len(destination) == 0 {
|
||||
destination = setting.CustomConf
|
||||
@@ -102,6 +161,76 @@ func runEnvironmentToIni(c *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if c.Bool("clear") {
|
||||
for _, kv := range os.Environ() {
|
||||
idx := strings.IndexByte(kv, '=')
|
||||
if idx < 0 {
|
||||
continue
|
||||
}
|
||||
eKey := kv[:idx]
|
||||
if strings.HasPrefix(eKey, prefix) {
|
||||
_ = os.Unsetenv(eKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
const escapeRegexpString = "_0[xX](([0-9a-fA-F][0-9a-fA-F])+)_"
|
||||
|
||||
var escapeRegex = regexp.MustCompile(escapeRegexpString)
|
||||
|
||||
// DecodeSectionKey will decode a portable string encoded Section__Key pair
|
||||
// Portable strings are considered to be of the form [A-Z0-9_]*
|
||||
// We will encode a disallowed value as the UTF8 byte string preceded by _0X and
|
||||
// followed by _. E.g. _0X2C_ for a '-' and _0X2E_ for '.'
|
||||
// Section and Key are separated by a plain '__'.
|
||||
// The entire section can be encoded as a UTF8 byte string
|
||||
func DecodeSectionKey(encoded string) (string, string) {
|
||||
section := ""
|
||||
key := ""
|
||||
|
||||
inKey := false
|
||||
last := 0
|
||||
escapeStringIndices := escapeRegex.FindAllStringIndex(encoded, -1)
|
||||
for _, unescapeIdx := range escapeStringIndices {
|
||||
preceding := encoded[last:unescapeIdx[0]]
|
||||
if !inKey {
|
||||
if splitter := strings.Index(preceding, "__"); splitter > -1 {
|
||||
section += preceding[:splitter]
|
||||
inKey = true
|
||||
key += preceding[splitter+2:]
|
||||
} else {
|
||||
section += preceding
|
||||
}
|
||||
} else {
|
||||
key += preceding
|
||||
}
|
||||
toDecode := encoded[unescapeIdx[0]+3 : unescapeIdx[1]-1]
|
||||
decodedBytes := make([]byte, len(toDecode)/2)
|
||||
for i := 0; i < len(toDecode)/2; i++ {
|
||||
// Can ignore error here as we know these should be hexadecimal from the regexp
|
||||
byteInt, _ := strconv.ParseInt(toDecode[2*i:2*i+2], 16, 0)
|
||||
decodedBytes[i] = byte(byteInt)
|
||||
}
|
||||
if inKey {
|
||||
key += string(decodedBytes)
|
||||
} else {
|
||||
section += string(decodedBytes)
|
||||
}
|
||||
last = unescapeIdx[1]
|
||||
}
|
||||
remaining := encoded[last:]
|
||||
if !inKey {
|
||||
if splitter := strings.Index(remaining, "__"); splitter > -1 {
|
||||
section += remaining[:splitter]
|
||||
key += remaining[splitter+2:]
|
||||
} else {
|
||||
section += remaining
|
||||
}
|
||||
} else {
|
||||
key += remaining
|
||||
}
|
||||
section = strings.ToLower(section)
|
||||
return section, key
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
//nolint:forbidigo
|
||||
package main
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
#!/bin/sh
|
||||
### BEGIN INIT INFO
|
||||
# Provides: gitea
|
||||
# Required-Start: $syslog $network
|
||||
# Required-Stop: $syslog
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: A self-hosted Git service written in Go.
|
||||
# Description: A self-hosted Git service written in Go.
|
||||
### END INIT INFO
|
||||
|
||||
# Do NOT "set -e"
|
||||
|
||||
# PATH should only include /usr/* if it runs after the mountnfs.sh script
|
||||
PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin
|
||||
DESC="Gitea - Git with a cup of tea"
|
||||
NAME=gitea
|
||||
SERVICEVERBOSE=yes
|
||||
PIDFILE=/run/$NAME.pid
|
||||
SCRIPTNAME=/etc/init.d/$NAME
|
||||
WORKINGDIR=/var/lib/$NAME
|
||||
DAEMON=/usr/local/bin/$NAME
|
||||
DAEMON_ARGS="web -c /etc/$NAME/app.ini"
|
||||
USER=git
|
||||
STOP_SCHEDULE="${STOP_SCHEDULE:-QUIT/5/TERM/1/KILL/5}"
|
||||
|
||||
# Read configuration variable file if it is present
|
||||
[ -r /etc/default/$NAME ] && . /etc/default/$NAME
|
||||
|
||||
# Exit if the package is not installed
|
||||
[ -x "$DAEMON" ] || exit 0
|
||||
|
||||
do_start()
|
||||
{
|
||||
GITEA_ENVS="USER=$USER GITEA_WORK_DIR=$WORKINGDIR HOME=/home/$USER"
|
||||
GITEA_EXEC="$DAEMON -- $DAEMON_ARGS"
|
||||
sh -c "start-stop-daemon --start --quiet --pidfile $PIDFILE --make-pidfile \\
|
||||
--background --chdir $WORKINGDIR --chuid $USER \\
|
||||
--exec /bin/bash -- -c '/usr/bin/env $GITEA_ENVS $GITEA_EXEC'"
|
||||
}
|
||||
|
||||
do_stop()
|
||||
{
|
||||
start-stop-daemon --stop --quiet --retry=$STOP_SCHEDULE --pidfile $PIDFILE --name $NAME --oknodo
|
||||
rm -f $PIDFILE
|
||||
}
|
||||
|
||||
do_status()
|
||||
{
|
||||
if [ -f $PIDFILE ]; then
|
||||
if kill -0 $(cat "$PIDFILE"); then
|
||||
echo "$NAME is running, PID is $(cat $PIDFILE)"
|
||||
else
|
||||
echo "$NAME process is dead, but pidfile exists"
|
||||
fi
|
||||
else
|
||||
echo "$NAME is not running"
|
||||
fi
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
echo "Starting $DESC" "$NAME"
|
||||
do_start
|
||||
;;
|
||||
stop)
|
||||
echo "Stopping $DESC" "$NAME"
|
||||
do_stop
|
||||
;;
|
||||
status)
|
||||
do_status
|
||||
;;
|
||||
restart)
|
||||
echo "Restarting $DESC" "$NAME"
|
||||
do_stop
|
||||
do_start
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $SCRIPTNAME {start|stop|status|restart}" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
@@ -0,0 +1,2 @@
|
||||
DROP DATABASE IF EXISTS gitea;
|
||||
CREATE DATABASE IF NOT EXISTS gitea CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
|
||||
@@ -0,0 +1,267 @@
|
||||
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package main
|
||||
|
||||
/*
|
||||
Checkout a PR and load the tests data into sqlite database
|
||||
*/
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/user"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
gitea_git "code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/graceful"
|
||||
"code.gitea.io/gitea/modules/markup"
|
||||
"code.gitea.io/gitea/modules/markup/external"
|
||||
repo_module "code.gitea.io/gitea/modules/repository"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"code.gitea.io/gitea/routers"
|
||||
markup_service "code.gitea.io/gitea/services/markup"
|
||||
|
||||
"github.com/go-git/go-git/v5"
|
||||
"github.com/go-git/go-git/v5/config"
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
var codeFilePath = "contrib/pr/checkout.go"
|
||||
|
||||
func runPR() {
|
||||
log.Printf("[PR] Starting gitea ...\n")
|
||||
curDir, err := os.Getwd()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
setting.SetCustomPathAndConf("", "", "")
|
||||
setting.InitProviderAllowEmpty()
|
||||
setting.LoadCommonSettings()
|
||||
|
||||
setting.RepoRootPath, err = os.MkdirTemp(os.TempDir(), "repos")
|
||||
if err != nil {
|
||||
log.Fatalf("TempDir: %v\n", err)
|
||||
}
|
||||
setting.AppDataPath, err = os.MkdirTemp(os.TempDir(), "appdata")
|
||||
if err != nil {
|
||||
log.Fatalf("TempDir: %v\n", err)
|
||||
}
|
||||
setting.AppWorkPath = curDir
|
||||
setting.StaticRootPath = curDir
|
||||
setting.GravatarSource = "https://secure.gravatar.com/avatar/"
|
||||
setting.AppURL = "http://localhost:8080/"
|
||||
setting.HTTPPort = "8080"
|
||||
setting.SSH.Domain = "localhost"
|
||||
setting.SSH.Port = 3000
|
||||
setting.InstallLock = true
|
||||
setting.SecretKey = "9pCviYTWSb"
|
||||
setting.InternalToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE0OTI3OTU5ODN9.OQkH5UmzID2XBdwQ9TAI6Jj2t1X-wElVTjbE7aoN4I8"
|
||||
curUser, err := user.Current()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
setting.RunUser = curUser.Username
|
||||
|
||||
log.Printf("[PR] Loading fixtures data ...\n")
|
||||
//models.LoadConfigs()
|
||||
/*
|
||||
setting.Database.Type = "sqlite3"
|
||||
setting.Database.Path = ":memory:"
|
||||
setting.Database.Timeout = 500
|
||||
*/
|
||||
dbCfg := setting.CfgProvider.Section("database")
|
||||
dbCfg.NewKey("DB_TYPE", "sqlite3")
|
||||
dbCfg.NewKey("PATH", ":memory:")
|
||||
|
||||
routers.InitGitServices()
|
||||
setting.Database.LogSQL = true
|
||||
// x, err = xorm.NewEngine("sqlite3", "file::memory:?cache=shared")
|
||||
|
||||
db.InitEngineWithMigration(context.Background(), func(_ *xorm.Engine) error {
|
||||
return nil
|
||||
})
|
||||
db.HasEngine = true
|
||||
// x.ShowSQL(true)
|
||||
err = unittest.InitFixtures(
|
||||
unittest.FixturesOptions{
|
||||
Dir: path.Join(curDir, "models/fixtures/"),
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Printf("Error initializing test database: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
unittest.LoadFixtures()
|
||||
util.RemoveAll(setting.RepoRootPath)
|
||||
util.RemoveAll(repo_module.LocalCopyPath())
|
||||
unittest.CopyDir(path.Join(curDir, "tests/gitea-repositories-meta"), setting.RepoRootPath)
|
||||
|
||||
log.Printf("[PR] Setting up router\n")
|
||||
// routers.GlobalInit()
|
||||
external.RegisterRenderers()
|
||||
markup.Init(markup_service.ProcessorHelper())
|
||||
c := routers.NormalRoutes(graceful.GetManager().HammerContext())
|
||||
|
||||
log.Printf("[PR] Ready for testing !\n")
|
||||
log.Printf("[PR] Login with user1, user2, user3, ... with pass: password\n")
|
||||
/*
|
||||
log.Info("Listen: %v://%s%s", setting.Protocol, listenAddr, setting.AppSubURL)
|
||||
|
||||
if setting.LFS.StartServer {
|
||||
log.Info("LFS server enabled")
|
||||
}
|
||||
|
||||
if setting.EnablePprof {
|
||||
go func() {
|
||||
log.Info("Starting pprof server on localhost:6060")
|
||||
log.Info("%v", http.ListenAndServe("localhost:6060", nil))
|
||||
}()
|
||||
}
|
||||
*/
|
||||
|
||||
// Start the server
|
||||
http.ListenAndServe(":8080", c)
|
||||
|
||||
log.Printf("[PR] Cleaning up ...\n")
|
||||
/*
|
||||
if err = util.RemoveAll(setting.Indexer.IssuePath); err != nil {
|
||||
fmt.Printf("util.RemoveAll: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
if err = util.RemoveAll(setting.Indexer.RepoPath); err != nil {
|
||||
fmt.Printf("Unable to remove repo indexer: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
*/
|
||||
if err = util.RemoveAll(setting.RepoRootPath); err != nil {
|
||||
log.Fatalf("util.RemoveAll: %v\n", err)
|
||||
}
|
||||
if err = util.RemoveAll(setting.AppDataPath); err != nil {
|
||||
log.Fatalf("util.RemoveAll: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
runPRFlag := flag.Bool("run", false, "Run the PR code")
|
||||
flag.Parse()
|
||||
if *runPRFlag {
|
||||
runPR()
|
||||
return
|
||||
}
|
||||
|
||||
// To force checkout (e.g. Windows complains about unclean work tree) set env variable FORCE=true
|
||||
force, err := strconv.ParseBool(os.Getenv("FORCE"))
|
||||
if err != nil {
|
||||
force = false
|
||||
}
|
||||
|
||||
// Otherwise checkout PR
|
||||
if len(os.Args) != 2 {
|
||||
log.Fatal("Need only one arg: the PR number")
|
||||
}
|
||||
pr := os.Args[1]
|
||||
|
||||
codeFilePath = filepath.FromSlash(codeFilePath) // Convert to running OS
|
||||
|
||||
// Copy this file if it will not exist in the PR branch
|
||||
dat, err := os.ReadFile(codeFilePath)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to cache this code file : %v", err)
|
||||
}
|
||||
|
||||
repo, err := git.PlainOpen(".")
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to open the repo : %v", err)
|
||||
}
|
||||
|
||||
// Find remote upstream
|
||||
remotes, err := repo.Remotes()
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to list remotes of repo : %v", err)
|
||||
}
|
||||
remoteUpstream := "origin" // Default
|
||||
for _, r := range remotes {
|
||||
if r.Config().URLs[0] == "https://github.com/go-gitea/gitea.git" ||
|
||||
r.Config().URLs[0] == "https://github.com/go-gitea/gitea" ||
|
||||
r.Config().URLs[0] == "git@github.com:go-gitea/gitea.git" { // fetch at index 0
|
||||
remoteUpstream = r.Config().Name
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
branch := fmt.Sprintf("pr-%s-%d", pr, time.Now().Unix())
|
||||
branchRef := plumbing.NewBranchReferenceName(branch)
|
||||
|
||||
log.Printf("Fetching PR #%s in %s\n", pr, branch)
|
||||
if runtime.GOOS == "windows" {
|
||||
// Use git cli command for windows
|
||||
runCmd("git", "fetch", remoteUpstream, fmt.Sprintf("pull/%s/head:%s", pr, branch))
|
||||
} else {
|
||||
ref := fmt.Sprintf("%s%s/head:%s", gitea_git.PullPrefix, pr, branchRef)
|
||||
err = repo.Fetch(&git.FetchOptions{
|
||||
RemoteName: remoteUpstream,
|
||||
RefSpecs: []config.RefSpec{
|
||||
config.RefSpec(ref),
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to fetch %s from %s : %v", ref, remoteUpstream, err)
|
||||
}
|
||||
}
|
||||
|
||||
tree, err := repo.Worktree()
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to parse git tree : %v", err)
|
||||
}
|
||||
log.Printf("Checkout PR #%s in %s\n", pr, branch)
|
||||
err = tree.Checkout(&git.CheckoutOptions{
|
||||
Branch: branchRef,
|
||||
Force: force,
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to checkout %s : %v", branch, err)
|
||||
}
|
||||
|
||||
// Copy this file if not exist
|
||||
if _, err := os.Stat(codeFilePath); os.IsNotExist(err) {
|
||||
err = os.MkdirAll(filepath.Dir(codeFilePath), 0o755)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to duplicate this code file in PR : %v", err)
|
||||
}
|
||||
err = os.WriteFile(codeFilePath, dat, 0o644)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to duplicate this code file in PR : %v", err)
|
||||
}
|
||||
}
|
||||
// Force build of js, css, bin, ...
|
||||
runCmd("make", "build")
|
||||
// Start with integration test
|
||||
runCmd("go", "run", "-mod", "vendor", "-tags", "sqlite sqlite_unlock_notify", codeFilePath, "-run")
|
||||
}
|
||||
|
||||
func runCmd(cmd ...string) {
|
||||
log.Printf("Executing : %s ...\n", cmd)
|
||||
c := exec.Command(cmd[0], cmd[1:]...)
|
||||
c.Stdout = os.Stdout
|
||||
c.Stderr = os.Stderr
|
||||
if err := c.Start(); err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
if err := c.Wait(); err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
}
|
||||
@@ -52,7 +52,7 @@ After=network.target
|
||||
# Uncomment the next line if you have repos with lots of files and get a HTTP 500 error because of that
|
||||
# LimitNOFILE=524288:524288
|
||||
RestartSec=2s
|
||||
Type=notify
|
||||
Type=simple
|
||||
User=git
|
||||
Group=git
|
||||
WorkingDirectory=/var/lib/gitea/
|
||||
@@ -62,7 +62,6 @@ WorkingDirectory=/var/lib/gitea/
|
||||
ExecStart=/usr/local/bin/gitea web --config /etc/gitea/app.ini
|
||||
Restart=always
|
||||
Environment=USER=git HOME=/home/git GITEA_WORK_DIR=/var/lib/gitea
|
||||
WatchdogSec=30s
|
||||
# If you install Git to directory prefix other than default PATH (which happens
|
||||
# for example if you install other versions of Git side-to-side with
|
||||
# distribution version), uncomment below line and add that prefix to PATH
|
||||
|
||||
+3
-12
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
# This is an update script for gitea installed via the binary distribution
|
||||
# from dl.gitea.com on linux as systemd service. It performs a backup and updates
|
||||
# from dl.gitea.io on linux as systemd service. It performs a backup and updates
|
||||
# Gitea in place.
|
||||
# NOTE: This adds the GPG Signing Key of the Gitea maintainers to the keyring.
|
||||
# Depends on: bash, curl, xz, sha256sum. optionally jq, gpg
|
||||
@@ -10,15 +10,6 @@
|
||||
# upgrade.sh 1.15.10
|
||||
# giteahome=/opt/gitea giteaconf=$giteahome/app.ini upgrade.sh
|
||||
|
||||
# Check if gitea service is running
|
||||
if ! pidof gitea &> /dev/null; then
|
||||
echo "Error: gitea is not running."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Continue with rest of the script if gitea is running
|
||||
echo "Gitea is running. Continuing with rest of script..."
|
||||
|
||||
# apply variables from environment
|
||||
: "${giteabin:="/usr/local/bin/gitea"}"
|
||||
: "${giteahome:="/var/lib/gitea"}"
|
||||
@@ -78,7 +69,7 @@ require curl xz sha256sum "$sudocmd"
|
||||
# select version to install
|
||||
if [[ -z "${giteaversion:-}" ]]; then
|
||||
require jq
|
||||
giteaversion=$(curl --connect-timeout 10 -sL https://dl.gitea.com/gitea/version.json | jq -r .latest.version)
|
||||
giteaversion=$(curl --connect-timeout 10 -sL https://dl.gitea.io/gitea/version.json | jq -r .latest.version)
|
||||
echo "Latest available version is $giteaversion"
|
||||
fi
|
||||
|
||||
@@ -100,7 +91,7 @@ cd "$giteahome" # needed for gitea dump later
|
||||
|
||||
# download new binary
|
||||
binname="gitea-${giteaversion}-${arch}"
|
||||
binurl="https://dl.gitea.com/gitea/${giteaversion}/${binname}.xz"
|
||||
binurl="https://dl.gitea.io/gitea/${giteaversion}/${binname}.xz"
|
||||
echo "Downloading $binurl..."
|
||||
curl --connect-timeout 10 --silent --show-error --fail --location -O "$binurl{,.sha256,.asc}"
|
||||
|
||||
|
||||
+184
-138
@@ -16,23 +16,26 @@
|
||||
;;
|
||||
;; - _`AppPath`_: This is the absolute path of the running gitea binary.
|
||||
;; - _`AppWorkPath`_: This refers to "working path" of the `gitea` binary. It is determined by using the first set thing in the following hierarchy:
|
||||
;; - The "WORK_PATH" option in "app.ini" file
|
||||
;; - The `--work-path` flag passed to the binary
|
||||
;; - The environment variable `$GITEA_WORK_DIR`
|
||||
;; - A built-in value set at build time (see building from source)
|
||||
;; - Otherwise it defaults to the directory of the _`AppPath`_
|
||||
;; - If any of the above are relative paths then they are made absolute against the directory of the _`AppPath`_
|
||||
;; - _`CustomPath`_: This is the base directory for custom templates and other options. It is determined by using the first set thing in the following hierarchy:
|
||||
;; - If any of the above are relative paths then they are made absolute against the
|
||||
;; the directory of the _`AppPath`_
|
||||
;; - _`CustomPath`_: This is the base directory for custom templates and other options.
|
||||
;; It is determined by using the first set thing in the following hierarchy:
|
||||
;; - The `--custom-path` flag passed to the binary
|
||||
;; - The environment variable `$GITEA_CUSTOM`
|
||||
;; - A built-in value set at build time (see building from source)
|
||||
;; - Otherwise it defaults to _`AppWorkPath`_`/custom`
|
||||
;; - If any of the above are relative paths then they are made absolute against the directory of the _`AppWorkPath`_
|
||||
;; - If any of the above are relative paths then they are made absolute against the
|
||||
;; the directory of the _`AppWorkPath`_
|
||||
;; - _`CustomConf`_: This is the path to the `app.ini` file.
|
||||
;; - The `--config` flag passed to the binary
|
||||
;; - A built-in value set at build time (see building from source)
|
||||
;; - Otherwise it defaults to _`CustomPath`_`/conf/app.ini`
|
||||
;; - If any of the above are relative paths then they are made absolute against the directory of the _`CustomPath`_
|
||||
;; - If any of the above are relative paths then they are made absolute against the
|
||||
;; the directory of the _`CustomPath`_
|
||||
;;
|
||||
;; In addition there is _`StaticRootPath`_ which can be set as a built-in at build time, but will otherwise default to _`AppWorkPath`_
|
||||
|
||||
@@ -46,12 +49,8 @@ APP_NAME = ; Gitea: Git with a cup of tea
|
||||
;; RUN_USER will automatically detect the current user - but you can set it here change it if you run locally
|
||||
RUN_USER = ; git
|
||||
;;
|
||||
;; Application run mode, affects performance and debugging: "dev" or "prod", default is "prod"
|
||||
;; Mode "dev" makes Gitea easier to develop and debug, values other than "dev" are treated as "prod" which is for production use.
|
||||
;RUN_MODE = prod
|
||||
;;
|
||||
;; The working directory, see the comment of AppWorkPath above
|
||||
;WORK_PATH =
|
||||
;; Application run mode, affects performance and debugging. Either "dev", "prod" or "test", default is "prod"
|
||||
RUN_MODE = ; prod
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
@@ -187,8 +186,8 @@ RUN_USER = ; git
|
||||
;; default is the system temporary directory.
|
||||
;SSH_KEY_TEST_PATH =
|
||||
;;
|
||||
;; Use `ssh-keygen` to parse public SSH keys. The value is passed to the shell. By default, Gitea does the parsing itself.
|
||||
;SSH_KEYGEN_PATH =
|
||||
;; Path to ssh-keygen, default is 'ssh-keygen' which means the shell is responsible for finding out which one to call.
|
||||
;SSH_KEYGEN_PATH = ssh-keygen
|
||||
;;
|
||||
;; Enable SSH Authorized Key Backup when rewriting all keys, default is true
|
||||
;SSH_AUTHORIZED_KEYS_BACKUP = true
|
||||
@@ -231,6 +230,7 @@ RUN_USER = ; git
|
||||
;;
|
||||
;; Disable CDN even in "prod" mode
|
||||
;OFFLINE_MODE = false
|
||||
;DISABLE_ROUTER_LOG = false
|
||||
;;
|
||||
;; TLS Settings: Either ACME or manual
|
||||
;; (Other common TLS configuration are found before)
|
||||
@@ -303,7 +303,7 @@ RUN_USER = ; git
|
||||
LFS_JWT_SECRET =
|
||||
;;
|
||||
;; LFS authentication validity period (in time.Duration), pushes taking longer than this may fail.
|
||||
;LFS_HTTP_AUTH_EXPIRY = 24h
|
||||
;LFS_HTTP_AUTH_EXPIRY = 20m
|
||||
;;
|
||||
;; Maximum allowed LFS file size in bytes (Set to 0 for no limit).
|
||||
;LFS_MAX_FILE_SIZE = 0
|
||||
@@ -387,7 +387,7 @@ USER = root
|
||||
;ITERATE_BUFFER_SIZE = 50
|
||||
;;
|
||||
;; Show the database generated SQL
|
||||
;LOG_SQL = false
|
||||
LOG_SQL = false ; if unset defaults to true
|
||||
;;
|
||||
;; Maximum number of DB Connect retries
|
||||
;DB_RETRIES = 10
|
||||
@@ -550,67 +550,78 @@ ENABLE = true
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Main Logger
|
||||
;;
|
||||
;; Either "console", "file" or "conn", default is "console"
|
||||
;; Either "console", "file", "conn", "smtp" or "database", default is "console"
|
||||
;; Use comma to separate multiple modes, e.g. "console, file"
|
||||
MODE = console
|
||||
;;
|
||||
;; Either "Trace", "Debug", "Info", "Warn", "Error" or "None", default is "Info"
|
||||
;; Either "Trace", "Debug", "Info", "Warn", "Error", "Critical" or "None", default is "Info"
|
||||
LEVEL = Info
|
||||
;;
|
||||
;; Print Stacktrace with logs (rarely helpful, do not set) Either "Trace", "Debug", "Info", "Warn", "Error", default is "None"
|
||||
;STACKTRACE_LEVEL = None
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Router Logger
|
||||
;;
|
||||
;; Buffer length of the channel, keep it as it is if you don't know what it is.
|
||||
;BUFFER_LEN = 10000
|
||||
;; Switch off the router log
|
||||
;DISABLE_ROUTER_LOG=false
|
||||
;;
|
||||
;; Sub logger modes, a single comma means use default MODE above, empty means disable it
|
||||
;logger.access.MODE=
|
||||
;logger.router.MODE=,
|
||||
;logger.xorm.MODE=,
|
||||
;; Set the log "modes" for the router log (if file is set the log file will default to router.log)
|
||||
ROUTER = console
|
||||
;;
|
||||
;; Collect SSH logs (Creates log from ssh git request)
|
||||
;; The router will log different things at different levels.
|
||||
;;
|
||||
;ENABLE_SSH_LOG = false
|
||||
;; * started messages will be logged at TRACE level
|
||||
;; * polling/completed routers will be logged at INFO
|
||||
;; * slow routers will be logged at WARN
|
||||
;; * failed routers will be logged at WARN
|
||||
;;
|
||||
;; The routing level will default to that of the system but individual router level can be set in
|
||||
;; [log.<mode>.router] LEVEL
|
||||
;;
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;
|
||||
;; Access Logger (Creates log in NCSA common log format)
|
||||
;;
|
||||
;; Print request id which parsed from request headers in access log, when access log is enabled.
|
||||
;; * E.g:
|
||||
;; * In request Header: X-Request-ID: test-id-123
|
||||
;; * Configuration in app.ini: REQUEST_ID_HEADERS = X-Request-ID
|
||||
;; * Print in log: 127.0.0.1:58384 - - [14/Feb/2023:16:33:51 +0800] "test-id-123"
|
||||
;ENABLE_ACCESS_LOG = false
|
||||
;;
|
||||
;; If you configure more than one in the .ini file, it will match in the order of configuration,
|
||||
;; and the first match will be finally printed in the log.
|
||||
;; * E.g:
|
||||
;; * In request Header: X-Trace-ID: trace-id-1q2w3e4r
|
||||
;; * Configuration in app.ini: REQUEST_ID_HEADERS = X-Request-ID, X-Trace-ID, X-Req-ID
|
||||
;; * Print in log: 127.0.0.1:58384 - - [14/Feb/2023:16:33:51 +0800] "trace-id-1q2w3e4r"
|
||||
;;
|
||||
;REQUEST_ID_HEADERS =
|
||||
;; Set the log "modes" for the access log (if file is set the log file will default to access.log)
|
||||
;ACCESS = file
|
||||
;;
|
||||
;; Sets the template used to create the access log.
|
||||
;ACCESS_LOG_TEMPLATE = {{.Ctx.RemoteHost}} - {{.Identity}} {{.Start.Format "[02/Jan/2006:15:04:05 -0700]" }} "{{.Ctx.Req.Method}} {{.Ctx.Req.URL.RequestURI}} {{.Ctx.Req.Proto}}" {{.ResponseWriter.Status}} {{.ResponseWriter.Size}} "{{.Ctx.Req.Referer}}" "{{.Ctx.Req.UserAgent}}"
|
||||
|
||||
;ACCESS_LOG_TEMPLATE = {{.Ctx.RemoteAddr}} - {{.Identity}} {{.Start.Format "[02/Jan/2006:15:04:05 -0700]" }} "{{.Ctx.Req.Method}} {{.Ctx.Req.URL.RequestURI}} {{.Ctx.Req.Proto}}" {{.ResponseWriter.Status}} {{.ResponseWriter.Size}} "{{.Ctx.Req.Referer}}\" \"{{.Ctx.Req.UserAgent}}"
|
||||
;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;
|
||||
;; Log modes (aka log writers)
|
||||
;; SSH log (Creates log from ssh git request)
|
||||
;;
|
||||
;[log.%(WriterMode)]
|
||||
;MODE=console/file/conn/...
|
||||
;ENABLE_SSH_LOG = false
|
||||
;;
|
||||
;; Other Settings
|
||||
;;
|
||||
;; Print Stacktraces with logs. (Rarely helpful.) Either "Trace", "Debug", "Info", "Warn", "Error", "Critical", default is "None"
|
||||
;STACKTRACE_LEVEL = None
|
||||
;;
|
||||
;; Buffer length of the channel, keep it as it is if you don't know what it is.
|
||||
;BUFFER_LEN = 10000
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Creating specific log configuration
|
||||
;;
|
||||
;; You can set specific configuration for individual modes and subloggers
|
||||
;;
|
||||
;; Configuration available to all log modes/subloggers
|
||||
;LEVEL=
|
||||
;FLAGS = stdflags
|
||||
;EXPRESSION =
|
||||
;PREFIX =
|
||||
;COLORIZE = false
|
||||
;;
|
||||
;[log.console]
|
||||
;; For "console" mode only
|
||||
;STDERR = false
|
||||
;;
|
||||
;[log.file]
|
||||
;; Set the file_name for the logger. If this is a relative path this will be relative to ROOT_PATH
|
||||
;; For "file" mode only
|
||||
;LEVEL =
|
||||
;; Set the file_name for the logger. If this is a relative path this
|
||||
;; will be relative to ROOT_PATH
|
||||
;FILE_NAME =
|
||||
;; This enables automated log rotate(switch of following options), default is true
|
||||
;LOG_ROTATE = true
|
||||
@@ -624,8 +635,9 @@ LEVEL = Info
|
||||
;COMPRESS = true
|
||||
;; compression level see godoc for compress/gzip
|
||||
;COMPRESSION_LEVEL = -1
|
||||
;;
|
||||
;[log.conn]
|
||||
;
|
||||
;; For "conn" mode only
|
||||
;LEVEL =
|
||||
;; Reconnect host for every single message, default is false
|
||||
;RECONNECT_ON_MSG = false
|
||||
;; Try to reconnect when connection is lost, default is false
|
||||
@@ -634,6 +646,19 @@ LEVEL = Info
|
||||
;PROTOCOL = tcp
|
||||
;; Host address
|
||||
;ADDR =
|
||||
;
|
||||
;; For "smtp" mode only
|
||||
;LEVEL =
|
||||
;; Name displayed in mail title, default is "Diagnostic message from server"
|
||||
;SUBJECT = Diagnostic message from server
|
||||
;; Mail server
|
||||
;HOST =
|
||||
;; Mailer user name and password
|
||||
;USER =
|
||||
;; Use PASSWD = `your password` for quoting if you use special characters in the password.
|
||||
;PASSWD =
|
||||
;; Receivers, can be one or more, e.g. 1@example.com,2@example.com
|
||||
;RECEIVERS =
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
@@ -683,24 +708,6 @@ LEVEL = Info
|
||||
;; Disable the usage of using partial clones for git.
|
||||
;DISABLE_PARTIAL_CLONE = false
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Git Operation timeout in seconds
|
||||
;[git.timeout]
|
||||
;DEFAULT = 360
|
||||
;MIGRATE = 600
|
||||
;MIRROR = 300
|
||||
;CLONE = 300
|
||||
;PULL = 300
|
||||
;GC = 60
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Git config options
|
||||
;; This section only does "set" config, a removed config key from this section won't be removed from git config automatically. The format is `some.configKey = value`.
|
||||
;[git.config]
|
||||
;diff.algorithm = histogram
|
||||
;core.logAllRefUpdates = true
|
||||
;gc.reflogExpire = 90
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
[service]
|
||||
@@ -719,11 +726,11 @@ LEVEL = Info
|
||||
;; Whether a new user needs to be confirmed manually after registration. (Requires `REGISTER_EMAIL_CONFIRM` to be disabled.)
|
||||
;REGISTER_MANUAL_CONFIRM = false
|
||||
;;
|
||||
;; List of domain names that are allowed to be used to register on a Gitea instance, wildcard is supported
|
||||
;; eg: gitea.io,example.com,*.mydomain.com
|
||||
;EMAIL_DOMAIN_ALLOWLIST =
|
||||
;; List of domain names that are allowed to be used to register on a Gitea instance
|
||||
;; gitea.io,example.com
|
||||
;EMAIL_DOMAIN_WHITELIST =
|
||||
;;
|
||||
;; Comma-separated list of domain names that are not allowed to be used to register on a Gitea instance, wildcard is supported
|
||||
;; Comma-separated list of domain names that are not allowed to be used to register on a Gitea instance
|
||||
;EMAIL_DOMAIN_BLOCKLIST =
|
||||
;;
|
||||
;; Disallow registration, only allow admins to create accounts.
|
||||
@@ -903,6 +910,12 @@ LEVEL = Info
|
||||
;; Global limit of repositories per user, applied at creation time. -1 means no limit
|
||||
;MAX_CREATION_LIMIT = -1
|
||||
;;
|
||||
;; Mirror sync queue length, increase if mirror syncing starts hanging (DEPRECATED: please use [queue.mirror] LENGTH instead)
|
||||
;MIRROR_QUEUE_LENGTH = 1000
|
||||
;;
|
||||
;; Patch test queue length, increase if pull request patch testing starts hanging (DEPRECATED: please use [queue.pr_patch_checker] LENGTH instead)
|
||||
;PULL_REQUEST_QUEUE_LENGTH = 1000
|
||||
;;
|
||||
;; Preferred Licenses to place at the top of the List
|
||||
;; The name here must match the filename in options/license or custom/options/license
|
||||
;PREFERRED_LICENSES = Apache License 2.0,MIT License
|
||||
@@ -917,9 +930,6 @@ LEVEL = Info
|
||||
;; Force ssh:// clone url instead of scp-style uri when default SSH port is used
|
||||
;USE_COMPAT_SSH_URI = false
|
||||
;;
|
||||
;; Value for the "go get" request returns the repository url as https or ssh, default is https
|
||||
;GO_GET_CLONE_URL_PROTOCOL = https
|
||||
;;
|
||||
;; Close issues as long as a commit on any branch marks it as fixed
|
||||
;; Comma separated list of globally disabled repo units. Allowed values: repo.issues, repo.ext_issues, repo.pulls, repo.wiki, repo.ext_wiki, repo.projects, repo.packages, repo.actions.
|
||||
;DISABLED_REPO_UNITS =
|
||||
@@ -966,7 +976,11 @@ LEVEL = Info
|
||||
;;
|
||||
;; List of file extensions for which lines should be wrapped in the Monaco editor
|
||||
;; Separate extensions with a comma. To line wrap files without an extension, just put a comma
|
||||
;LINE_WRAP_EXTENSIONS = .txt,.md,.markdown,.mdown,.mkd,.livemd,
|
||||
;LINE_WRAP_EXTENSIONS = .txt,.md,.markdown,.mdown,.mkd,
|
||||
;;
|
||||
;; Valid file modes that have a preview API associated with them, such as api/v1/markdown
|
||||
;; Separate the values by commas. The preview tab in edit mode won't be displayed if the file extension doesn't match
|
||||
;PREVIEWABLE_FILE_MODES = markdown
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
@@ -1044,9 +1058,6 @@ LEVEL = Info
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; List of reasons why a Pull Request or Issue can be locked
|
||||
;LOCK_REASONS = Too heated,Off-topic,Resolved,Spam
|
||||
;; Maximum number of pinned Issues per repo
|
||||
;; Set to 0 to disable pinning Issues
|
||||
;MAX_PINNED = 3
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
@@ -1180,6 +1191,10 @@ LEVEL = Info
|
||||
;; Number of line of codes shown for a code comment
|
||||
;CODE_COMMENT_LINES = 4
|
||||
;;
|
||||
;; Value of `theme-color` meta tag, used by some mobile browers for chrome and
|
||||
;; out-of-viewport areas. Default is unset which uses body color.
|
||||
;THEME_COLOR_META_TAG =
|
||||
;;
|
||||
;; Max size of files to be displayed (default is 8MiB)
|
||||
;MAX_DISPLAY_FILE_SIZE = 8388608
|
||||
;;
|
||||
@@ -1208,6 +1223,9 @@ LEVEL = Info
|
||||
;; Whether to search within description at repository search on explore page.
|
||||
;SEARCH_REPO_DESCRIPTION = true
|
||||
;;
|
||||
;; Whether to enable a Service Worker to cache frontend assets
|
||||
;USE_SERVICE_WORKER = false
|
||||
;;
|
||||
;; Whether to only show relevant repos on the explore page when no keyword is specified and default sorting is used.
|
||||
;; A repo is considered irrelevant if it's a fork or if it has no metadata (no description, no icon, no topic).
|
||||
;ONLY_SHOW_RELEVANT_REPOS = false
|
||||
@@ -1300,12 +1318,11 @@ LEVEL = Info
|
||||
;; Comma separated list of custom URL-Schemes that are allowed as links when rendering Markdown
|
||||
;; for example git,magnet,ftp (more at https://en.wikipedia.org/wiki/List_of_URI_schemes)
|
||||
;; URLs starting with http and https are always displayed, whatever is put in this entry.
|
||||
;; If this entry is empty, all URL schemes are allowed.
|
||||
;CUSTOM_URL_SCHEMES =
|
||||
;;
|
||||
;; List of file extensions that should be rendered/edited as Markdown
|
||||
;; Separate the extensions with a comma. To render files without any extension as markdown, just put a comma
|
||||
;FILE_EXTENSIONS = .md,.markdown,.mdown,.mkd,.livemd
|
||||
;FILE_EXTENSIONS = .md,.markdown,.mdown,.mkd
|
||||
;;
|
||||
;; Enables math inline and block detection
|
||||
;ENABLE_MATH = true
|
||||
@@ -1331,13 +1348,13 @@ LEVEL = Info
|
||||
;; Issue Indexer settings
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;
|
||||
;; Issue indexer type, currently support: bleve, db, elasticsearch or meilisearch default is bleve
|
||||
;; Issue indexer type, currently support: bleve, db or elasticsearch, default is bleve
|
||||
;ISSUE_INDEXER_TYPE = bleve
|
||||
;;
|
||||
;; Issue indexer storage path, available when ISSUE_INDEXER_TYPE is bleve
|
||||
;ISSUE_INDEXER_PATH = indexers/issues.bleve ; Relative paths will be made absolute against _`AppWorkPath`_.
|
||||
;;
|
||||
;; Issue indexer connection string, available when ISSUE_INDEXER_TYPE is elasticsearch or meilisearch
|
||||
;; Issue indexer connection string, available when ISSUE_INDEXER_TYPE is elasticsearch
|
||||
;ISSUE_INDEXER_CONN_STR = http://elastic:changeme@localhost:9200
|
||||
;;
|
||||
;; Issue indexer name, available when ISSUE_INDEXER_TYPE is elasticsearch
|
||||
@@ -1347,6 +1364,22 @@ LEVEL = Info
|
||||
;; Set to -1 to disable timeout.
|
||||
;STARTUP_TIMEOUT = 30s
|
||||
;;
|
||||
;; Issue indexer queue, currently support: channel, levelqueue or redis, default is levelqueue (deprecated - use [queue.issue_indexer])
|
||||
;ISSUE_INDEXER_QUEUE_TYPE = levelqueue; **DEPRECATED** use settings in `[queue.issue_indexer]`.
|
||||
;;
|
||||
;; When ISSUE_INDEXER_QUEUE_TYPE is levelqueue, this will be the path where the queue will be saved.
|
||||
;; This can be overridden by `ISSUE_INDEXER_QUEUE_CONN_STR`.
|
||||
;; default is queues/common
|
||||
;ISSUE_INDEXER_QUEUE_DIR = queues/common; **DEPRECATED** use settings in `[queue.issue_indexer]`. Relative paths will be made absolute against `%(APP_DATA_PATH)s`.
|
||||
;;
|
||||
;; When `ISSUE_INDEXER_QUEUE_TYPE` is `redis`, this will store the redis connection string.
|
||||
;; When `ISSUE_INDEXER_QUEUE_TYPE` is `levelqueue`, this is a directory or additional options of
|
||||
;; the form `leveldb://path/to/db?option=value&....`, and overrides `ISSUE_INDEXER_QUEUE_DIR`.
|
||||
;ISSUE_INDEXER_QUEUE_CONN_STR = "addrs=127.0.0.1:6379 db=0"; **DEPRECATED** use settings in `[queue.issue_indexer]`.
|
||||
;;
|
||||
;; Batch queue number, default is 20
|
||||
;ISSUE_INDEXER_QUEUE_BATCH_NUMBER = 20; **DEPRECATED** use settings in `[queue.issue_indexer]`.
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Repository Indexer settings
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
@@ -1354,10 +1387,6 @@ LEVEL = Info
|
||||
;; repo indexer by default disabled, since it uses a lot of disk space
|
||||
;REPO_INDEXER_ENABLED = false
|
||||
;;
|
||||
;; repo indexer units, the items to index, could be `sources`, `forks`, `mirrors`, `templates` or any combination of them separated by a comma.
|
||||
;; If empty then it defaults to `sources` only, as if you'd like to disable fully please see REPO_INDEXER_ENABLED.
|
||||
;REPO_INDEXER_REPO_TYPES = sources,forks,mirrors,templates
|
||||
;;
|
||||
;; Code search engine type, could be `bleve` or `elasticsearch`.
|
||||
;REPO_INDEXER_TYPE = bleve
|
||||
;;
|
||||
@@ -1377,6 +1406,8 @@ LEVEL = Info
|
||||
;; A comma separated list of glob patterns to exclude from the index; ; default is empty
|
||||
;REPO_INDEXER_EXCLUDE =
|
||||
;;
|
||||
;;
|
||||
;UPDATE_BUFFER_LEN = 20; **DEPRECATED** use settings in `[queue.issue_indexer]`.
|
||||
;MAX_FILE_SIZE = 1048576
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
@@ -1398,15 +1429,15 @@ LEVEL = Info
|
||||
;DATADIR = queues/ ; Relative paths will be made absolute against `%(APP_DATA_PATH)s`.
|
||||
;;
|
||||
;; Default queue length before a channel queue will block
|
||||
;LENGTH = 100
|
||||
;LENGTH = 20
|
||||
;;
|
||||
;; Batch size to send for batched queues
|
||||
;BATCH_LENGTH = 20
|
||||
;;
|
||||
;; Connection string for redis queues this will store the redis or redis-cluster connection string.
|
||||
;; Connection string for redis queues this will store the redis connection string.
|
||||
;; When `TYPE` is `persistable-channel`, this provides a directory for the underlying leveldb
|
||||
;; or additional options of the form `leveldb://path/to/db?option=value&....`, and will override `DATADIR`.
|
||||
;CONN_STR = "redis://127.0.0.1:6379/0"
|
||||
;CONN_STR = "addrs=127.0.0.1:6379 db=0"
|
||||
;;
|
||||
;; Provides the suffix of the default redis/disk queue name - specific queues can be overridden within in their [queue.name] sections.
|
||||
;QUEUE_NAME = "_queue"
|
||||
@@ -1414,8 +1445,29 @@ LEVEL = Info
|
||||
;; Provides the suffix of the default redis/disk unique queue set name - specific queues can be overridden within in their [queue.name] sections.
|
||||
;SET_NAME = "_unique"
|
||||
;;
|
||||
;; Maximum number of worker go-routines for the queue. Default value is "CpuNum/2" clipped to between 1 and 10.
|
||||
;MAX_WORKERS = ; (dynamic)
|
||||
;; If the queue cannot be created at startup - level queues may need a timeout at startup - wrap the queue:
|
||||
;WRAP_IF_NECESSARY = true
|
||||
;;
|
||||
;; Attempt to create the wrapped queue at max
|
||||
;MAX_ATTEMPTS = 10
|
||||
;;
|
||||
;; Timeout queue creation
|
||||
;TIMEOUT = 15m30s
|
||||
;;
|
||||
;; Create a pool with this many workers
|
||||
;WORKERS = 0
|
||||
;;
|
||||
;; Dynamically scale the worker pool to at this many workers
|
||||
;MAX_WORKERS = 10
|
||||
;;
|
||||
;; Add boost workers when the queue blocks for BLOCK_TIMEOUT
|
||||
;BLOCK_TIMEOUT = 1s
|
||||
;;
|
||||
;; Remove the boost workers after BOOST_TIMEOUT
|
||||
;BOOST_TIMEOUT = 5m
|
||||
;;
|
||||
;; During a boost add BOOST_WORKERS
|
||||
;BOOST_WORKERS = 1
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
@@ -1675,9 +1727,8 @@ LEVEL = Info
|
||||
;; For "memory" only, GC interval in seconds, default is 60
|
||||
;INTERVAL = 60
|
||||
;;
|
||||
;; For "redis", "redis-cluster" and "memcache", connection host address
|
||||
;; For "redis" and "memcache", connection host address
|
||||
;; redis: `redis://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s`
|
||||
;; redis-cluster: `redis+cluster://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s`
|
||||
;; memcache: `127.0.0.1:11211`
|
||||
;; twoqueue: `{"size":50000,"recent_ratio":0.25,"ghost_ratio":0.5}` or `50000`
|
||||
;HOST =
|
||||
@@ -1709,7 +1760,7 @@ LEVEL = Info
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;
|
||||
;; Either "memory", "file", "redis", "redis-cluster", "db", "mysql", "couchbase", "memcache" or "postgres"
|
||||
;; Either "memory", "file", "redis", "db", "mysql", "couchbase", "memcache" or "postgres"
|
||||
;; Default is "memory". "db" will reuse the configuration in [database]
|
||||
;PROVIDER = memory
|
||||
;;
|
||||
@@ -1717,7 +1768,6 @@ LEVEL = Info
|
||||
;; memory: doesn't have any config yet
|
||||
;; file: session file path, e.g. `data/sessions`
|
||||
;; redis: `redis://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s`
|
||||
;; redis-cluster: `redis+cluster://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s`
|
||||
;; mysql: go-sql-driver/mysql dsn config string, e.g. `root:password@/session_table`
|
||||
;PROVIDER_CONFIG = data/sessions ; Relative paths will be made absolute against _`AppWorkPath`_.
|
||||
;;
|
||||
@@ -1753,19 +1803,16 @@ LEVEL = Info
|
||||
;; Max Width and Height of uploaded avatars.
|
||||
;; This is to limit the amount of RAM used when resizing the image.
|
||||
;AVATAR_MAX_WIDTH = 4096
|
||||
;AVATAR_MAX_HEIGHT = 4096
|
||||
;AVATAR_MAX_HEIGHT = 3072
|
||||
;;
|
||||
;; The multiplication factor for rendered avatar images.
|
||||
;; Larger values result in finer rendering on HiDPI devices.
|
||||
;AVATAR_RENDERED_SIZE_FACTOR = 2
|
||||
;AVATAR_RENDERED_SIZE_FACTOR = 3
|
||||
;;
|
||||
;; Maximum allowed file size for uploaded avatars.
|
||||
;; This is to limit the amount of RAM used when resizing the image.
|
||||
;AVATAR_MAX_FILE_SIZE = 1048576
|
||||
;;
|
||||
;; If the uploaded file is not larger than this byte size, the image will be used as is, without resizing/converting.
|
||||
;AVATAR_MAX_ORIGIN_SIZE = 262144
|
||||
;;
|
||||
;; Chinese users can choose "duoshuo"
|
||||
;; or a custom avatar source, like: http://cn.gravatar.com/avatar/
|
||||
;GRAVATAR_SOURCE = gravatar
|
||||
@@ -1840,6 +1887,11 @@ LEVEL = Info
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;
|
||||
;; Specifies the format for fully outputted dates. Defaults to RFC1123
|
||||
;; Special supported values are ANSIC, UnixDate, RubyDate, RFC822, RFC822Z, RFC850, RFC1123, RFC1123Z, RFC3339, RFC3339Nano, Kitchen, Stamp, StampMilli, StampMicro and StampNano
|
||||
;; For more information about the format see http://golang.org/pkg/time/#pkg-constants
|
||||
;FORMAT =
|
||||
;;
|
||||
;; Location the UI time display i.e. Asia/Shanghai
|
||||
;; Empty means server's location setting
|
||||
;DEFAULT_UI_LOCATION =
|
||||
@@ -2159,7 +2211,7 @@ LEVEL = Info
|
||||
;RUN_AT_START = false
|
||||
;ENABLE_SUCCESS_NOTICE = false
|
||||
;SCHEDULE = @every 168h
|
||||
;HTTP_ENDPOINT = https://dl.gitea.com/gitea/version.json
|
||||
;HTTP_ENDPOINT = https://dl.gitea.io/gitea/version.json
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
@@ -2195,6 +2247,32 @@ LEVEL = Info
|
||||
;Check at least this proportion of LFSMetaObjects per repo. (This may cause all stale LFSMetaObjects to be checked.)
|
||||
;PROPORTION_TO_CHECK_PER_REPO = 0.6
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Git Operation timeout in seconds
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;[git.timeout]
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;DEFAULT = 360
|
||||
;MIGRATE = 600
|
||||
;MIRROR = 300
|
||||
;CLONE = 300
|
||||
;PULL = 300
|
||||
;GC = 60
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Git Reflog timeout in days
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;[git.reflog]
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;ENABLED = true
|
||||
;EXPIRATION = 90
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;[mirror]
|
||||
@@ -2249,6 +2327,7 @@ LEVEL = Info
|
||||
;[other]
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;SHOW_FOOTER_BRANDING = false
|
||||
;; Show version information about Gitea and Go in the footer
|
||||
;SHOW_FOOTER_VERSION = true
|
||||
;; Show template execution time in the footer
|
||||
@@ -2325,7 +2404,7 @@ LEVEL = Info
|
||||
;QUEUE_LENGTH = 1000
|
||||
;;
|
||||
;; Task queue connection string, available only when `QUEUE_TYPE` is `redis`.
|
||||
;; If there is a password of redis, use `redis://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s` or `redis+cluster://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s` for `redis-clsuter`.
|
||||
;; If there is a password of redis, use `redis://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s`.
|
||||
;QUEUE_CONN_STR = "redis://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s"
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
@@ -2392,10 +2471,6 @@ LEVEL = Info
|
||||
;; Enable/Disable package registry capabilities
|
||||
;ENABLED = true
|
||||
;;
|
||||
;STORAGE_TYPE = local
|
||||
;; override the minio base path if storage type is minio
|
||||
;MINIO_BASE_PATH = packages/
|
||||
;;
|
||||
;; Path for chunked uploads. Defaults to APP_DATA_PATH + `tmp/package-upload`
|
||||
;CHUNKED_UPLOAD_PATH = tmp/package-upload
|
||||
;;
|
||||
@@ -2403,8 +2478,6 @@ LEVEL = Info
|
||||
;LIMIT_TOTAL_OWNER_COUNT = -1
|
||||
;; Maximum size of packages a single owner can use (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||
;LIMIT_TOTAL_OWNER_SIZE = -1
|
||||
;; Maximum size of an Alpine upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||
;LIMIT_SIZE_ALPINE = -1
|
||||
;; Maximum size of a Cargo upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||
;LIMIT_SIZE_CARGO = -1
|
||||
;; Maximum size of a Chef upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||
@@ -2417,14 +2490,8 @@ LEVEL = Info
|
||||
;LIMIT_SIZE_CONDA = -1
|
||||
;; Maximum size of a Container upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||
;LIMIT_SIZE_CONTAINER = -1
|
||||
;; Maximum size of a CRAN upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||
;LIMIT_SIZE_CRAN = -1
|
||||
;; Maximum size of a Debian upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||
;LIMIT_SIZE_DEBIAN = -1
|
||||
;; Maximum size of a Generic upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||
;LIMIT_SIZE_GENERIC = -1
|
||||
;; Maximum size of a Go upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||
;LIMIT_SIZE_GO = -1
|
||||
;; Maximum size of a Helm upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||
;LIMIT_SIZE_HELM = -1
|
||||
;; Maximum size of a Maven upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||
@@ -2437,12 +2504,8 @@ LEVEL = Info
|
||||
;LIMIT_SIZE_PUB = -1
|
||||
;; Maximum size of a PyPI upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||
;LIMIT_SIZE_PYPI = -1
|
||||
;; Maximum size of a RPM upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||
;LIMIT_SIZE_RPM = -1
|
||||
;; Maximum size of a RubyGems upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||
;LIMIT_SIZE_RUBYGEMS = -1
|
||||
;; Maximum size of a Swift upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||
;LIMIT_SIZE_SWIFT = -1
|
||||
;; Maximum size of a Vagrant upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||
;LIMIT_SIZE_VAGRANT = -1
|
||||
|
||||
@@ -2456,19 +2519,6 @@ LEVEL = Info
|
||||
;; storage type
|
||||
;STORAGE_TYPE = local
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; repo-archive storage will override storage
|
||||
;;
|
||||
;[repo-archive]
|
||||
;STORAGE_TYPE = local
|
||||
;;
|
||||
;; Where your lfs files reside, default is data/lfs.
|
||||
;PATH = data/repo-archive
|
||||
;;
|
||||
;; override the minio base path if storage type is minio
|
||||
;MINIO_BASE_PATH = repo-archive/
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; settings for repository archives, will override storage setting
|
||||
@@ -2488,9 +2538,6 @@ LEVEL = Info
|
||||
;;
|
||||
;; Where your lfs files reside, default is data/lfs.
|
||||
;PATH = data/lfs
|
||||
;;
|
||||
;; override the minio base path if storage type is minio
|
||||
;MINIO_BASE_PATH = lfs/
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
@@ -2540,9 +2587,8 @@ LEVEL = Info
|
||||
; [actions]
|
||||
;; Enable/Disable actions capabilities
|
||||
;ENABLED = false
|
||||
;;
|
||||
;; Default platform to get action plugins, `github` for `https://github.com`, `self` for the current Gitea instance.
|
||||
;DEFAULT_ACTIONS_URL = github
|
||||
;; Default address to get action plugins, e.g. the default value means downloading from "https://gitea.com/actions/checkout" for "uses: actions/checkout@v3"
|
||||
;DEFAULT_ACTIONS_URL = https://gitea.com
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
@@ -5,7 +5,6 @@ tags:
|
||||
{{#each build.tags}}
|
||||
- {{this}}-rootless
|
||||
{{/each}}
|
||||
- "latest-rootless"
|
||||
{{/unless}}
|
||||
{{/if}}
|
||||
manifests:
|
||||
|
||||
@@ -5,7 +5,6 @@ tags:
|
||||
{{#each build.tags}}
|
||||
- {{this}}
|
||||
{{/each}}
|
||||
- "latest"
|
||||
{{/unless}}
|
||||
{{/if}}
|
||||
manifests:
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#
|
||||
# And place the original in /usr/lib/gitea with working files in /data/gitea
|
||||
GITEA="/app/gitea/gitea"
|
||||
WORK_DIR="/data/gitea"
|
||||
WORK_DIR="/app/gitea"
|
||||
CUSTOM_PATH="/data/gitea"
|
||||
|
||||
# Provide docker defaults
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
[](https://discord.gg/Gitea)
|
||||
[](http://microbadger.com/images/gitea/docs "Get your own image badge on microbadger.com")
|
||||
|
||||
These docs are ingested by our [docs repo](https://gitea.com/gitea/gitea-docusaurus).
|
||||
https://gitea.com/gitea/gitea-docusaurus
|
||||
|
||||
## Authors
|
||||
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
---
|
||||
date: "2023-04-27T14:00:00+08:00"
|
||||
title: "Actions"
|
||||
slug: "actions"
|
||||
sidebar_position: 36
|
||||
toc: false
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
name: "Usage - Actions"
|
||||
sidebar_position: 31
|
||||
identifier: "actions"
|
||||
---
|
||||
@@ -5,8 +5,6 @@ slug: adding-legal-pages
|
||||
sidebar_position: 110
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /en-us/adding-legal-pages
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
|
||||
@@ -5,8 +5,6 @@ slug: "backup-and-restore"
|
||||
sidebar_position: 11
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /en-us/backup-and-restore
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
@@ -42,9 +40,9 @@ directory. There should be some output similar to the following:
|
||||
|
||||
Inside the `gitea-dump-1482906742.zip` file, will be the following:
|
||||
|
||||
- `app.ini` - Optional copy of configuration file if originally stored outside the default `custom/` directory
|
||||
- `app.ini` - Optional copy of configuration file if originally stored outside of the default `custom/` directory
|
||||
- `custom` - All config or customization files in `custom/`.
|
||||
- `data` - Data directory (APP_DATA_PATH), except sessions if you are using file session. This directory includes `attachments`, `avatars`, `lfs`, `indexers`, SQLite file if you are using SQLite.
|
||||
- `data` - Data directory in `<GITEA_WORK_DIR>`, except sessions if you are using file session. This directory includes `attachments`, `avatars`, `lfs`, `indexers`, SQLite file if you are using SQLite.
|
||||
- `gitea-db.sql` - SQL dump of database
|
||||
- `gitea-repo.zip` - Complete copy of the repository directory.
|
||||
- `log/` - Various logs. They are not needed for a recovery or migration.
|
||||
@@ -135,6 +133,16 @@ chown -R git:git /data
|
||||
|
||||
The default user in the gitea container is `git` (1000:1000). Please replace `2a83b293548e` with your gitea container id or name.
|
||||
|
||||
These are the default paths used in the container:
|
||||
|
||||
```text
|
||||
DEFAULT CONFIGURATION:
|
||||
CustomPath: /data/gitea (GITEA_CUSTOM)
|
||||
CustomConf: /data/gitea/conf/app.ini
|
||||
AppPath: /usr/local/bin/gitea
|
||||
AppWorkPath: /usr/local/bin
|
||||
```
|
||||
|
||||
### Using Docker-rootless (`restore`)
|
||||
|
||||
The restore workflow in Docker-rootless containers differs only in the directories to be used:
|
||||
|
||||
@@ -5,8 +5,6 @@ slug: "backup-and-restore"
|
||||
sidebar_position: 11
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /zh-cn/backup-and-restore
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
|
||||
@@ -5,8 +5,6 @@ slug: "backup-and-restore"
|
||||
sidebar_position: 11
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /zh-tw/backup-and-restore
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
|
||||
@@ -5,8 +5,6 @@ slug: "cmd-embedded"
|
||||
sidebar_position: 20
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /en-us/cmd-embedded
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
@@ -36,7 +34,7 @@ gitea embedded list [--include-vendored] [patterns...]
|
||||
|
||||
The `--include-vendored` flag makes the command include vendored files, which are
|
||||
normally excluded; that is, files from external libraries that are required for Gitea
|
||||
(e.g. [octicons](https://octicons.github.com/), etc).
|
||||
(e.g. [font-awesome](https://fontawesome.com/), [octicons](https://octicons.github.com/), etc).
|
||||
|
||||
A list of file search patterns can be provided. Gitea uses [gobwas/glob](https://github.com/gobwas/glob)
|
||||
for its glob syntax. Here are some examples:
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
---
|
||||
date: "2017-01-01T16:00:00+02:00"
|
||||
title: "Gitea Command Line"
|
||||
title: "Command Line"
|
||||
slug: "command-line"
|
||||
sidebar_position: 1
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /en-us/command-line
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
@@ -27,9 +25,9 @@ All global options can be placed at the command level.
|
||||
|
||||
- `--help`, `-h`: Show help text and exit. Optional.
|
||||
- `--version`, `-v`: Show version and exit. Optional. (example: `Gitea version 1.1.0+218-g7b907ed built with: bindata, sqlite`).
|
||||
- `--work-path path`, `-w path`: Gitea's work path. Optional. (default: the binary's path or `$GITEA_WORK_DIR`)
|
||||
- `--custom-path path`, `-C path`: Gitea's custom folder path. Optional. (default: `WorkPath`/custom or `$GITEA_CUSTOM`).
|
||||
- `--config path`, `-c path`: Gitea configuration file path. Optional. (default: `CustomPath`/conf/app.ini).
|
||||
- `--custom-path path`, `-C path`: Location of the Gitea custom folder. Optional. (default: `AppWorkPath`/custom or `$GITEA_CUSTOM`).
|
||||
- `--config path`, `-c path`: Gitea configuration file path. Optional. (default: `custom`/conf/app.ini).
|
||||
- `--work-path path`, `-w path`: Gitea `AppWorkPath`. Optional. (default: LOCATION_OF_GITEA_BINARY or `$GITEA_WORK_DIR`)
|
||||
|
||||
NB: The defaults custom-path, config and work-path can also be
|
||||
changed at build time (if preferred).
|
||||
@@ -104,14 +102,6 @@ Admin operations:
|
||||
- `--all`, `-A`: Force a password change for all users
|
||||
- `--exclude username`, `-e username`: Exclude the given user. Can be set multiple times.
|
||||
- `--unset`: Revoke forced password change for the given users
|
||||
- `generate-access-token`:
|
||||
- Options:
|
||||
- `--username value`, `-u value`: Username. Required.
|
||||
- `--token-name value`, `-t value`: Token name. Required.
|
||||
- `--scopes value`: Comma-separated list of scopes. Scopes follow the format `[read|write]:<block>` or `all` where `<block>` is one of the available visual groups you can see when opening the API page showing the available routes (for example `repo`).
|
||||
- Examples:
|
||||
- `gitea admin user generate-access-token --username myname --token-name mytoken`
|
||||
- `gitea admin user generate-access-token --help`
|
||||
- `regenerate`
|
||||
- Options:
|
||||
- `hooks`: Regenerate Git Hooks for all repositories
|
||||
@@ -229,7 +219,7 @@ Admin operations:
|
||||
- `--synchronize-users`: Enable user synchronization.
|
||||
- `--page-size value`: Search page size.
|
||||
- Examples:
|
||||
- `gitea admin auth add-ldap --name ldap --security-protocol unencrypted --host mydomain.org --port 389 --user-search-base "ou=Users,dc=mydomain,dc=org" --user-filter "(&(objectClass=posixAccount)(|(uid=%[1]s)(mail=%[1]s)))" --email-attribute mail`
|
||||
- `gitea admin auth add-ldap --name ldap --security-protocol unencrypted --host mydomain.org --port 389 --user-search-base "ou=Users,dc=mydomain,dc=org" --user-filter "(&(objectClass=posixAccount)(uid=%s))" --email-attribute mail`
|
||||
- `update-ldap`: Update existing LDAP (via Bind DN) authentication source
|
||||
- Options:
|
||||
- `--id value`: ID of authentication source. Required.
|
||||
@@ -557,28 +547,3 @@ Restore-repo restore repository data from disk dir:
|
||||
- `--owner_name lunny`: Restore destination owner name
|
||||
- `--repo_name tango`: Restore destination repository name
|
||||
- `--units <units>`: Which items will be restored, one or more units should be separated as comma. wiki, issues, labels, releases, release_assets, milestones, pull_requests, comments are allowed. Empty means all units.
|
||||
|
||||
### actions generate-runner-token
|
||||
|
||||
Generate a new token for a runner to use to register with the server
|
||||
|
||||
- Options:
|
||||
- `--scope {owner}[/{repo}]`, `-s {owner}[/{repo}]`: To limit the scope of the runner, no scope means the runner can be used for all repos, but you can also limit it to a specific repo or owner
|
||||
|
||||
To register a global runner:
|
||||
|
||||
```
|
||||
gitea actions generate-runner-token
|
||||
```
|
||||
|
||||
To register a runner for a specific organization, in this case `org`:
|
||||
|
||||
```
|
||||
gitea actions generate-runner-token -s org
|
||||
```
|
||||
|
||||
To register a runner for a specific repo, in this case `username/test-repo`:
|
||||
|
||||
```
|
||||
gitea actions generate-runner-token -s username/test-repo
|
||||
```
|
||||
|
||||
@@ -5,8 +5,6 @@ slug: "config-cheat-sheet"
|
||||
sidebar_position: 30
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /en-us/config-cheat-sheet
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
@@ -42,27 +40,28 @@ reported as part of the default configuration when running `gitea --help` or on
|
||||
|
||||
- _`AppPath`_: This is the absolute path of the running gitea binary.
|
||||
- _`AppWorkPath`_: This refers to "working path" of the `gitea` binary. It is determined by using the first set thing in the following hierarchy:
|
||||
- The `WORK_PATH` option in `app.ini`
|
||||
- The `--work-path` flag passed to the binary
|
||||
- The environment variable `$GITEA_WORK_DIR`
|
||||
- A built-in value set at build time (see building from source)
|
||||
- Otherwise, it defaults to the directory of the _`AppPath`_
|
||||
- If any of the above are relative paths then they are made absolute against the directory of the _`AppPath`_
|
||||
- Otherwise it defaults to the directory of the _`AppPath`_
|
||||
- If any of the above are relative paths then they are made absolute against the
|
||||
the directory of the _`AppPath`_
|
||||
- _`CustomPath`_: This is the base directory for custom templates and other options.
|
||||
It is determined by using the first set thing in the following hierarchy:
|
||||
- The `--custom-path` flag passed to the binary
|
||||
- The environment variable `$GITEA_CUSTOM`
|
||||
- A built-in value set at build time (see building from source)
|
||||
- Otherwise, it defaults to _`AppWorkPath`_`/custom`
|
||||
- Otherwise it defaults to _`AppWorkPath`_`/custom`
|
||||
- If any of the above are relative paths then they are made absolute against the
|
||||
the directory of the _`AppWorkPath`_
|
||||
- _`CustomConf`_: This is the path to the `app.ini` file.
|
||||
- The `--config` flag passed to the binary
|
||||
- A built-in value set at build time (see building from source)
|
||||
- Otherwise, it defaults to _`CustomPath`_`/conf/app.ini`
|
||||
- If any of the above are relative paths then they are made absolute against the directory of the _`CustomPath`_
|
||||
- Otherwise it defaults to _`CustomPath`_`/conf/app.ini`
|
||||
- If any of the above are relative paths then they are made absolute against the
|
||||
the directory of the _`CustomPath`_
|
||||
|
||||
In addition, there is _`StaticRootPath`_ which can be set as a built-in at build time, but will otherwise default to _`AppWorkPath`_
|
||||
In addition there is _`StaticRootPath`_ which can be set as a built-in at build time, but will otherwise default to _`AppWorkPath`_
|
||||
|
||||
## Overall (`DEFAULT`)
|
||||
|
||||
@@ -70,8 +69,7 @@ In addition, there is _`StaticRootPath`_ which can be set as a built-in at build
|
||||
- `RUN_USER`: **_current OS username_/`$USER`/`$USERNAME` e.g. git**: The user Gitea will run as.
|
||||
This should be a dedicated system (non-user) account. Setting this incorrectly will cause Gitea
|
||||
to not start.
|
||||
- `RUN_MODE`: **prod**: Application run mode, affects performance and debugging: `dev` or `prod`, default is `prod`. Mode `dev` makes Gitea easier to develop and debug, values other than `dev` are treated as `prod` which is for production use.
|
||||
- `WORK_PATH`: **_the-work-path_**: The working directory, see the comment of AppWorkPath above.
|
||||
- `RUN_MODE`: **prod**: Application run mode, affects performance and debugging. Either "dev", "prod" or "test".
|
||||
|
||||
## Repository (`repository`)
|
||||
|
||||
@@ -87,14 +85,16 @@ In addition, there is _`StaticRootPath`_ which can be set as a built-in at build
|
||||
- `DEFAULT_PUSH_CREATE_PRIVATE`: **true**: Default private when creating a new repository with push-to-create.
|
||||
- `MAX_CREATION_LIMIT`: **-1**: Global maximum creation limit of repositories per user,
|
||||
`-1` means no limit.
|
||||
- `PULL_REQUEST_QUEUE_LENGTH`: **1000**: Length of pull request patch test queue, make it. **DEPRECATED** use `LENGTH` in `[queue.pr_patch_checker]`.
|
||||
as large as possible. Use caution when editing this value.
|
||||
- `MIRROR_QUEUE_LENGTH`: **1000**: Patch test queue length, increase if pull request patch
|
||||
testing starts hanging. **DEPRECATED** use `LENGTH` in `[queue.mirror]`.
|
||||
- `PREFERRED_LICENSES`: **Apache License 2.0,MIT License**: Preferred Licenses to place at
|
||||
the top of the list. Name must match file name in options/license or custom/options/license.
|
||||
- `DISABLE_HTTP_GIT`: **false**: Disable the ability to interact with repositories over the
|
||||
HTTP protocol.
|
||||
- `USE_COMPAT_SSH_URI`: **false**: Force ssh:// clone url instead of scp-style uri when
|
||||
default SSH port is used.
|
||||
- `GO_GET_CLONE_URL_PROTOCOL`: **https**: Value for the "go get" request returns the repository url as https or ssh
|
||||
default is https.
|
||||
- `ACCESS_CONTROL_ALLOW_ORIGIN`: **_empty_**: Value for Access-Control-Allow-Origin header,
|
||||
default is not to present. **WARNING**: This maybe harmful to you website if you do not
|
||||
give it a right value.
|
||||
@@ -115,7 +115,7 @@ In addition, there is _`StaticRootPath`_ which can be set as a built-in at build
|
||||
|
||||
### Repository - Editor (`repository.editor`)
|
||||
|
||||
- `LINE_WRAP_EXTENSIONS`: **.txt,.md,.markdown,.mdown,.mkd,.livemd,**: List of file extensions for which lines should be wrapped in the Monaco editor. Separate extensions with a comma. To line wrap files without an extension, just put a comma
|
||||
- `LINE_WRAP_EXTENSIONS`: **.txt,.md,.markdown,.mdown,.mkd,**: List of file extensions for which lines should be wrapped in the Monaco editor. Separate extensions with a comma. To line wrap files without an extension, just put a comma
|
||||
- `PREVIEWABLE_FILE_MODES`: **markdown**: Valid file modes that have a preview API associated with them, such as `api/v1/markdown`. Separate the values by commas. The preview tab in edit mode won't be displayed if the file extension doesn't match.
|
||||
|
||||
### Repository - Pull Request (`repository.pull-request`)
|
||||
@@ -139,7 +139,6 @@ In addition, there is _`StaticRootPath`_ which can be set as a built-in at build
|
||||
### Repository - Issue (`repository.issue`)
|
||||
|
||||
- `LOCK_REASONS`: **Too heated,Off-topic,Resolved,Spam**: A list of reasons why a Pull Request or Issue can be locked
|
||||
- `MAX_PINNED`: **3**: Maximum number of pinned Issues per Repo. Set to 0 to disable pinning Issues.
|
||||
|
||||
### Repository - Upload (`repository.upload`)
|
||||
|
||||
@@ -219,6 +218,7 @@ The following configuration set `Content-Type: application/vnd.android.package-a
|
||||
- `SHOW_USER_EMAIL`: **true**: Whether the email of the user should be shown in the Explore Users page.
|
||||
- `THEMES`: **auto,gitea,arc-green**: All available themes. Allow users select personalized themes.
|
||||
regardless of the value of `DEFAULT_THEME`.
|
||||
- `THEME_COLOR_META_TAG`: **_empty_**: Value of `theme-color` meta tag, used by some mobile browers for chrome and out-of-viewport areas. Default is unset which uses body color.
|
||||
- `MAX_DISPLAY_FILE_SIZE`: **8388608**: Max size of files to be displayed (default is 8MiB)
|
||||
- `REACTIONS`: All available reactions users can choose on issues/prs and comments
|
||||
Values can be emoji alias (:smile:) or a unicode emoji.
|
||||
@@ -228,6 +228,7 @@ The following configuration set `Content-Type: application/vnd.android.package-a
|
||||
add it to this config.
|
||||
- `DEFAULT_SHOW_FULL_NAME`: **false**: Whether the full name of the users should be shown where possible. If the full name isn't set, the username will be used.
|
||||
- `SEARCH_REPO_DESCRIPTION`: **true**: Whether to search within description at repository search on explore page.
|
||||
- `USE_SERVICE_WORKER`: **false**: Whether to enable a Service Worker to cache frontend assets.
|
||||
- `ONLY_SHOW_RELEVANT_REPOS`: **false** Whether to only show relevant repos on the explore page when no keyword is specified and default sorting is used.
|
||||
A repo is considered irrelevant if it's a fork or if it has no metadata (no description, no icon, no topic).
|
||||
|
||||
@@ -273,8 +274,7 @@ The following configuration set `Content-Type: application/vnd.android.package-a
|
||||
trailing whitespace to paragraphs is not necessary to force a line break.
|
||||
- `CUSTOM_URL_SCHEMES`: Use a comma separated list (ftp,git,svn) to indicate additional
|
||||
URL hyperlinks to be rendered in Markdown. URLs beginning in http and https are
|
||||
always displayed. If this entry is empty, all URL schemes are allowed
|
||||
- `FILE_EXTENSIONS`: **.md,.markdown,.mdown,.mkd,.livemd**: List of file extensions that should be rendered/edited as Markdown. Separate the extensions with a comma. To render files without any extension as markdown, just put a comma.
|
||||
always displayed
|
||||
- `ENABLE_MATH`: **true**: Enables detection of `\(...\)`, `\[...\]`, `$...$` and `$$...$$` blocks as math blocks.
|
||||
|
||||
## Server (`server`)
|
||||
@@ -337,13 +337,13 @@ The following configuration set `Content-Type: application/vnd.android.package-a
|
||||
- `SSH_AUTHORIZED_PRINCIPALS_ALLOW`: **off** or **username, email**: \[off, username, email, anything\]: Specify the principals values that users are allowed to use as principal. When set to `anything` no checks are done on the principal string. When set to `off` authorized principal are not allowed to be set.
|
||||
- `SSH_CREATE_AUTHORIZED_PRINCIPALS_FILE`: **false/true**: Gitea will create a authorized_principals file by default when it is not using the internal ssh server and `SSH_AUTHORIZED_PRINCIPALS_ALLOW` is not `off`.
|
||||
- `SSH_AUTHORIZED_PRINCIPALS_BACKUP`: **false/true**: Enable SSH Authorized Principals Backup when rewriting all keys, default is true if `SSH_AUTHORIZED_PRINCIPALS_ALLOW` is not `off`.
|
||||
- `SSH_AUTHORIZED_KEYS_COMMAND_TEMPLATE`: **{{.AppPath}} --config={{.CustomConf}} serv key-{{.Key.ID}}**: Set the template for the command to passed on authorized keys. Possible keys are: AppPath, AppWorkPath, CustomConf, CustomPath, Key - where Key is a `models/asymkey.PublicKey` and the others are strings which are shellquoted.
|
||||
- `SSH_AUTHORIZED_KEYS_COMMAND_TEMPLATE`: **`{{.AppPath}} --config={{.CustomConf}} serv key-{{.Key.ID}}`**: Set the template for the command to passed on authorized keys. Possible keys are: AppPath, AppWorkPath, CustomConf, CustomPath, Key - where Key is a `models/asymkey.PublicKey` and the others are strings which are shellquoted.
|
||||
- `SSH_SERVER_CIPHERS`: **chacha20-poly1305@openssh.com, aes128-ctr, aes192-ctr, aes256-ctr, aes128-gcm@openssh.com, aes256-gcm@openssh.com**: For the built-in SSH server, choose the ciphers to support for SSH connections, for system SSH this setting has no effect.
|
||||
- `SSH_SERVER_KEY_EXCHANGES`: **curve25519-sha256, ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521, diffie-hellman-group14-sha256, diffie-hellman-group14-sha1**: For the built-in SSH server, choose the key exchange algorithms to support for SSH connections, for system SSH this setting has no effect.
|
||||
- `SSH_SERVER_MACS`: **hmac-sha2-256-etm@openssh.com, hmac-sha2-256, hmac-sha1**: For the built-in SSH server, choose the MACs to support for SSH connections, for system SSH this setting has no effect
|
||||
- `SSH_SERVER_HOST_KEYS`: **ssh/gitea.rsa, ssh/gogs.rsa**: For the built-in SSH server, choose the keypairs to offer as the host key. The private key should be at `SSH_SERVER_HOST_KEY` and the public `SSH_SERVER_HOST_KEY.pub`. Relative paths are made absolute relative to the `APP_DATA_PATH`. If no key exists a 4096 bit RSA key will be created for you.
|
||||
- `SSH_KEY_TEST_PATH`: **/tmp**: Directory to create temporary files in when testing public keys using ssh-keygen, default is the system temporary directory.
|
||||
- `SSH_KEYGEN_PATH`: **_empty_**: Use `ssh-keygen` to parse public SSH keys. The value is passed to the shell. By default, Gitea does the parsing itself.
|
||||
- `SSH_KEYGEN_PATH`: **ssh-keygen**: Path to ssh-keygen, default is 'ssh-keygen' which means the shell is responsible for finding out which one to call.
|
||||
- `SSH_EXPOSE_ANONYMOUS`: **false**: Enable exposure of SSH clone URL to anonymous visitors, default is false.
|
||||
- `SSH_PER_WRITE_TIMEOUT`: **30s**: Timeout for any write to the SSH connections. (Set to
|
||||
-1 to disable all timeouts.)
|
||||
@@ -363,7 +363,7 @@ The following configuration set `Content-Type: application/vnd.android.package-a
|
||||
- `LFS_START_SERVER`: **false**: Enables Git LFS support.
|
||||
- `LFS_CONTENT_PATH`: **%(APP_DATA_PATH)s/lfs**: Default LFS content path. (if it is on local storage.) **DEPRECATED** use settings in `[lfs]`.
|
||||
- `LFS_JWT_SECRET`: **_empty_**: LFS authentication secret, change this a unique string.
|
||||
- `LFS_HTTP_AUTH_EXPIRY`: **24h**: LFS authentication validity period in time.Duration, pushes taking longer than this may fail.
|
||||
- `LFS_HTTP_AUTH_EXPIRY`: **20m**: LFS authentication validity period in time.Duration, pushes taking longer than this may fail.
|
||||
- `LFS_MAX_FILE_SIZE`: **0**: Maximum allowed LFS file size in bytes (Set to 0 for no limit).
|
||||
- `LFS_LOCKS_PAGING_NUM`: **50**: Maximum number of LFS Locks returned per page.
|
||||
|
||||
@@ -456,13 +456,17 @@ relation to port exhaustion.
|
||||
|
||||
## Indexer (`indexer`)
|
||||
|
||||
- `ISSUE_INDEXER_TYPE`: **bleve**: Issue indexer type, currently supported: `bleve`, `db`, `elasticsearch` or `meilisearch`.
|
||||
- `ISSUE_INDEXER_CONN_STR`: ****: Issue indexer connection string, available when ISSUE_INDEXER_TYPE is elasticsearch, or meilisearch. i.e. http://elastic:changeme@localhost:9200
|
||||
- `ISSUE_INDEXER_TYPE`: **bleve**: Issue indexer type, currently supported: `bleve`, `db` or `elasticsearch`.
|
||||
- `ISSUE_INDEXER_CONN_STR`: ****: Issue indexer connection string, available when ISSUE_INDEXER_TYPE is elasticsearch. i.e. http://elastic:changeme@localhost:9200
|
||||
- `ISSUE_INDEXER_NAME`: **gitea_issues**: Issue indexer name, available when ISSUE_INDEXER_TYPE is elasticsearch
|
||||
- `ISSUE_INDEXER_PATH`: **indexers/issues.bleve**: Index file used for issue search; available when ISSUE_INDEXER_TYPE is bleve and elasticsearch. Relative paths will be made absolute against _`AppWorkPath`_.
|
||||
- The next 4 configuration values are deprecated and should be set in `queue.issue_indexer` however are kept for backwards compatibility:
|
||||
- `ISSUE_INDEXER_QUEUE_TYPE`: **levelqueue**: Issue indexer queue, currently supports:`channel`, `levelqueue`, `redis`. **DEPRECATED** use settings in `[queue.issue_indexer]`.
|
||||
- `ISSUE_INDEXER_QUEUE_DIR`: **queues/common**: When `ISSUE_INDEXER_QUEUE_TYPE` is `levelqueue`, this will be the path where the queue will be saved. **DEPRECATED** use settings in `[queue.issue_indexer]`. Relative paths will be made absolute against `%(APP_DATA_PATH)s`.
|
||||
- `ISSUE_INDEXER_QUEUE_CONN_STR`: **addrs=127.0.0.1:6379 db=0**: When `ISSUE_INDEXER_QUEUE_TYPE` is `redis`, this will store the redis connection string. When `ISSUE_INDEXER_QUEUE_TYPE` is `levelqueue`, this is a directory or additional options of the form `leveldb://path/to/db?option=value&....`, and overrides `ISSUE_INDEXER_QUEUE_DIR`. **DEPRECATED** use settings in `[queue.issue_indexer]`.
|
||||
- `ISSUE_INDEXER_QUEUE_BATCH_NUMBER`: **20**: Batch queue number. **DEPRECATED** use settings in `[queue.issue_indexer]`.
|
||||
|
||||
- `REPO_INDEXER_ENABLED`: **false**: Enables code search (uses a lot of disk space, about 6 times more than the repository size).
|
||||
- `REPO_INDEXER_REPO_TYPES`: **sources,forks,mirrors,templates**: Repo indexer units. The items to index could be `sources`, `forks`, `mirrors`, `templates` or any combination of them separated by a comma. If empty then it defaults to `sources` only, as if you'd like to disable fully please see `REPO_INDEXER_ENABLED`.
|
||||
- `REPO_INDEXER_TYPE`: **bleve**: Code search engine type, could be `bleve` or `elasticsearch`.
|
||||
- `REPO_INDEXER_PATH`: **indexers/repos.bleve**: Index file used for code search.
|
||||
- `REPO_INDEXER_CONN_STR`: ****: Code indexer connection string, available when `REPO_INDEXER_TYPE` is elasticsearch. i.e. http://elastic:changeme@localhost:9200
|
||||
@@ -471,6 +475,7 @@ relation to port exhaustion.
|
||||
- `REPO_INDEXER_INCLUDE`: **empty**: A comma separated list of glob patterns (see https://github.com/gobwas/glob) to **include** in the index. Use `**.txt` to match any files with .txt extension. An empty list means include all files.
|
||||
- `REPO_INDEXER_EXCLUDE`: **empty**: A comma separated list of glob patterns (see https://github.com/gobwas/glob) to **exclude** from the index. Files that match this list will not be indexed, even if they match in `REPO_INDEXER_INCLUDE`.
|
||||
- `REPO_INDEXER_EXCLUDE_VENDORED`: **true**: Exclude vendored files from index.
|
||||
- `UPDATE_BUFFER_LEN`: **20**: Buffer length of index request. **DEPRECATED** use settings in `[queue.issue_indexer]`.
|
||||
- `MAX_FILE_SIZE`: **1048576**: Maximum size in bytes of files to be indexed.
|
||||
- `STARTUP_TIMEOUT`: **30s**: If the indexer takes longer than this timeout to start - fail. (This timeout will be added to the hammer time above for child processes - as bleve will not start until the previous parent is shutdown.) Set to -1 to never timeout.
|
||||
|
||||
@@ -478,14 +483,23 @@ relation to port exhaustion.
|
||||
|
||||
Configuration at `[queue]` will set defaults for queues with overrides for individual queues at `[queue.*]`. (However see below.)
|
||||
|
||||
- `TYPE`: **level**: General queue type, currently support: `level` (uses a LevelDB internally), `channel`, `redis`, `dummy`. Invalid types are treated as `level`.
|
||||
- `DATADIR`: **queues/common**: Base DataDir for storing level queues. `DATADIR` for individual queues can be set in `queue.name` sections. Relative paths will be made absolute against `%(APP_DATA_PATH)s`.
|
||||
- `LENGTH`: **100**: Maximal queue size before channel queues block
|
||||
- `TYPE`: **persistable-channel**: General queue type, currently support: `persistable-channel` (uses a LevelDB internally), `channel`, `level`, `redis`, `dummy`
|
||||
- `DATADIR`: **queues/**: Base DataDir for storing persistent and level queues. `DATADIR` for individual queues can be set in `queue.name` sections but will default to `DATADIR/`**`common`**. (Previously each queue would default to `DATADIR/`**`name`**.) Relative paths will be made absolute against `%(APP_DATA_PATH)s`.
|
||||
- `LENGTH`: **20**: Maximal queue size before channel queues block
|
||||
- `BATCH_LENGTH`: **20**: Batch data before passing to the handler
|
||||
- `CONN_STR`: **redis://127.0.0.1:6379/0**: Connection string for the redis queue type. For `redis-cluster` use `redis+cluster://127.0.0.1:6379/0`. Options can be set using query params. Similarly, LevelDB options can also be set using: **leveldb://relative/path?option=value** or **leveldb:///absolute/path?option=value**, and will override `DATADIR`
|
||||
- `CONN_STR`: **redis://127.0.0.1:6379/0**: Connection string for the redis queue type. Options can be set using query params. Similarly LevelDB options can also be set using: **leveldb://relative/path?option=value** or **leveldb:///absolute/path?option=value**, and will override `DATADIR`
|
||||
- `QUEUE_NAME`: **_queue**: The suffix for default redis and disk queue name. Individual queues will default to **`name`**`QUEUE_NAME` but can be overridden in the specific `queue.name` section.
|
||||
- `SET_NAME`: **_unique**: The suffix that will be added to the default redis and disk queue `set` name for unique queues. Individual queues will default to **`name`**`QUEUE_NAME`_`SET_NAME`_ but can be overridden in the specific `queue.name` section.
|
||||
- `MAX_WORKERS`: **(dynamic)**: Maximum number of worker go-routines for the queue. Default value is "CpuNum/2" clipped to between 1 and 10.
|
||||
- `SET_NAME`: **_unique**: The suffix that will be added to the default redis and disk queue `set` name for unique queues. Individual queues will default to
|
||||
**`name`**`QUEUE_NAME`_`SET_NAME`_ but can be overridden in the specific `queue.name` section.
|
||||
- `WRAP_IF_NECESSARY`: **true**: Will wrap queues with a timeoutable queue if the selected queue is not ready to be created - (Only relevant for the level queue.)
|
||||
- `MAX_ATTEMPTS`: **10**: Maximum number of attempts to create the wrapped queue
|
||||
- `TIMEOUT`: **GRACEFUL_HAMMER_TIME + 30s**: Timeout the creation of the wrapped queue if it takes longer than this to create.
|
||||
- Queues by default come with a dynamically scaling worker pool. The following settings configure this:
|
||||
- `WORKERS`: **0**: Number of initial workers for the queue.
|
||||
- `MAX_WORKERS`: **10**: Maximum number of worker go-routines for the queue.
|
||||
- `BLOCK_TIMEOUT`: **1s**: If the queue blocks for this time, boost the number of workers - the `BLOCK_TIMEOUT` will then be doubled before boosting again whilst the boost is ongoing.
|
||||
- `BOOST_TIMEOUT`: **5m**: Boost workers will timeout after this long.
|
||||
- `BOOST_WORKERS`: **1**: This many workers will be added to the worker pool if there is a boost.
|
||||
|
||||
Gitea creates the following non-unique queues:
|
||||
|
||||
@@ -503,6 +517,21 @@ And the following unique queues:
|
||||
- `mirror`
|
||||
- `pr_patch_checker`
|
||||
|
||||
Certain queues have defaults that override the defaults set in `[queue]` (this occurs mostly to support older configuration):
|
||||
|
||||
- `[queue.issue_indexer]`
|
||||
- `TYPE` this will default to `[queue]` `TYPE` if it is set but if not it will appropriately convert `[indexer]` `ISSUE_INDEXER_QUEUE_TYPE` if that is set.
|
||||
- `LENGTH` will default to `[indexer]` `UPDATE_BUFFER_LEN` if that is set.
|
||||
- `BATCH_LENGTH` will default to `[indexer]` `ISSUE_INDEXER_QUEUE_BATCH_NUMBER` if that is set.
|
||||
- `DATADIR` will default to `[indexer]` `ISSUE_INDEXER_QUEUE_DIR` if that is set.
|
||||
- `CONN_STR` will default to `[indexer]` `ISSUE_INDEXER_QUEUE_CONN_STR` if that is set.
|
||||
- `[queue.mailer]`
|
||||
- `LENGTH` will default to **100** or whatever `[mailer]` `SEND_BUFFER_LEN` is.
|
||||
- `[queue.pr_patch_checker]`
|
||||
- `LENGTH` will default to **1000** or whatever `[repository]` `PULL_REQUEST_QUEUE_LENGTH` is.
|
||||
- `[queue.mirror]`
|
||||
- `LENGTH` will default to **1000** or whatever `[repository]` `MIRROR_QUEUE_LENGTH` is.
|
||||
|
||||
## Admin (`admin`)
|
||||
|
||||
- `DEFAULT_EMAIL_NOTIFICATIONS`: **enabled**: Default configuration for email notifications for users (user configurable). Options: enabled, onmention, disabled
|
||||
@@ -649,8 +678,9 @@ And the following unique queues:
|
||||
- `ENABLE_TIMETRACKING`: **true**: Enable Timetracking feature.
|
||||
- `DEFAULT_ENABLE_TIMETRACKING`: **true**: Allow repositories to use timetracking by default.
|
||||
- `DEFAULT_ALLOW_ONLY_CONTRIBUTORS_TO_TRACK_TIME`: **true**: Only allow users with write permissions to track time.
|
||||
- `EMAIL_DOMAIN_ALLOWLIST`: **_empty_**: If non-empty, comma separated list of domain names that can only be used to register on this instance, wildcard is supported.
|
||||
- `EMAIL_DOMAIN_BLOCKLIST`: **_empty_**: If non-empty, comma separated list of domain names that cannot be used to register on this instance, wildcard is supported.
|
||||
- `EMAIL_DOMAIN_WHITELIST`: **_empty_**: If non-empty, list of domain names that can only be used to register
|
||||
on this instance.
|
||||
- `EMAIL_DOMAIN_BLOCKLIST`: **_empty_**: If non-empty, list of domain names that cannot be used to register on this instance
|
||||
- `SHOW_REGISTRATION_BUTTON`: **! DISABLE\_REGISTRATION**: Show Registration Button
|
||||
- `SHOW_MILESTONES_DASHBOARD_PAGE`: **true** Enable this to show the milestones dashboard page - a view of all the user's milestones
|
||||
- `AUTO_WATCH_NEW_REPOS`: **true**: Enable this to let all organisation users watch new repos when they are created
|
||||
@@ -753,11 +783,10 @@ and
|
||||
## Cache (`cache`)
|
||||
|
||||
- `ENABLED`: **true**: Enable the cache.
|
||||
- `ADAPTER`: **memory**: Cache engine adapter, either `memory`, `redis`, `redis-cluster`, `twoqueue` or `memcache`. (`twoqueue` represents a size limited LRU cache.)
|
||||
- `ADAPTER`: **memory**: Cache engine adapter, either `memory`, `redis`, `twoqueue` or `memcache`. (`twoqueue` represents a size limited LRU cache.)
|
||||
- `INTERVAL`: **60**: Garbage Collection interval (sec), for memory and twoqueue cache only.
|
||||
- `HOST`: **_empty_**: Connection string for `redis`, `redis-cluster` and `memcache`. For `twoqueue` sets configuration for the queue.
|
||||
- `HOST`: **_empty_**: Connection string for `redis` and `memcache`. For `twoqueue` sets configuration for the queue.
|
||||
- Redis: `redis://:macaron@127.0.0.1:6379/0?pool_size=100&idle_timeout=180s`
|
||||
- Redis-cluster `redis+cluster://:macaron@127.0.0.1:6379/0?pool_size=100&idle_timeout=180s`
|
||||
- Memcache: `127.0.0.1:9090;127.0.0.1:9091`
|
||||
- TwoQueue LRU cache: `{"size":50000,"recent_ratio":0.25,"ghost_ratio":0.5}` or `50000` representing the maximum number of objects stored in the cache.
|
||||
- `ITEM_TTL`: **16h**: Time to keep items in cache if not used, Setting it to -1 disables caching.
|
||||
@@ -770,7 +799,7 @@ and
|
||||
|
||||
## Session (`session`)
|
||||
|
||||
- `PROVIDER`: **memory**: Session engine provider \[memory, file, redis, redis-cluster, db, mysql, couchbase, memcache, postgres\]. Setting `db` will reuse the configuration in `[database]`
|
||||
- `PROVIDER`: **memory**: Session engine provider \[memory, file, redis, db, mysql, couchbase, memcache, postgres\]. Setting `db` will reuse the configuration in `[database]`
|
||||
- `PROVIDER_CONFIG`: **data/sessions**: For file, the root path; for db, empty (database config will be used); for others, the connection string. Relative paths will be made absolute against _`AppWorkPath`_.
|
||||
- `COOKIE_SECURE`: **false**: Enable this to force using HTTPS for all session access.
|
||||
- `COOKIE_NAME`: **i\_like\_gitea**: The name of the cookie used for the session ID.
|
||||
@@ -790,10 +819,9 @@ and
|
||||
- `AVATAR_STORAGE_TYPE`: **default**: Storage type defined in `[storage.xxx]`. Default is `default` which will read `[storage]` if no section `[storage]` will be a type `local`.
|
||||
- `AVATAR_UPLOAD_PATH`: **data/avatars**: Path to store user avatar image files.
|
||||
- `AVATAR_MAX_WIDTH`: **4096**: Maximum avatar image width in pixels.
|
||||
- `AVATAR_MAX_HEIGHT`: **4096**: Maximum avatar image height in pixels.
|
||||
- `AVATAR_MAX_FILE_SIZE`: **1048576** (1MiB): Maximum avatar image file size in bytes.
|
||||
- `AVATAR_MAX_ORIGIN_SIZE`: **262144** (256KiB): If the uploaded file is not larger than this byte size, the image will be used as is, without resizing/converting.
|
||||
- `AVATAR_RENDERED_SIZE_FACTOR`: **2**: The multiplication factor for rendered avatar images. Larger values result in finer rendering on HiDPI devices.
|
||||
- `AVATAR_MAX_HEIGHT`: **3072**: Maximum avatar image height in pixels.
|
||||
- `AVATAR_MAX_FILE_SIZE`: **1048576** (1Mb): Maximum avatar image file size in bytes.
|
||||
- `AVATAR_RENDERED_SIZE_FACTOR`: **3**: The multiplication factor for rendered avatar images. Larger values result in finer rendering on HiDPI devices.
|
||||
|
||||
- `REPOSITORY_AVATAR_STORAGE_TYPE`: **default**: Storage type defined in `[storage.xxx]`. Default is `default` which will read `[storage]` if no section `[storage]` will be a type `local`.
|
||||
- `REPOSITORY_AVATAR_UPLOAD_PATH`: **data/repo-avatars**: Path to store repository avatar image files.
|
||||
@@ -832,48 +860,48 @@ Default templates for project boards:
|
||||
## Log (`log`)
|
||||
|
||||
- `ROOT_PATH`: **_empty_**: Root path for log files.
|
||||
- `MODE`: **console**: Logging mode. For multiple modes, use a comma to separate values. You can configure each mode in per mode log subsections `\[log.writer-mode-name\]`.
|
||||
- `MODE`: **console**: Logging mode. For multiple modes, use a comma to separate values. You can configure each mode in per mode log subsections `\[log.modename\]`. By default the file mode will log to `$ROOT_PATH/gitea.log`.
|
||||
- `LEVEL`: **Info**: General log level. \[Trace, Debug, Info, Warn, Error, Critical, Fatal, None\]
|
||||
- `STACKTRACE_LEVEL`: **None**: Default log level at which to log create stack traces (rarely useful, do not set it). \[Trace, Debug, Info, Warn, Error, Critical, Fatal, None\]
|
||||
- `STACKTRACE_LEVEL`: **None**: Default log level at which to log create stack traces. \[Trace, Debug, Info, Warn, Error, Critical, Fatal, None\]
|
||||
- `ENABLE_SSH_LOG`: **false**: save ssh log to log file
|
||||
- `logger.access.MODE`: **_empty_**: The "access" logger
|
||||
- `logger.router.MODE`: **,**: The "router" logger, a single comma means it will use the default MODE above
|
||||
- `logger.xorm.MODE`: **,**: The "xorm" logger
|
||||
- `ENABLE_XORM_LOG`: **true**: Set whether to perform XORM logging. Please note SQL statement logging can be disabled by setting `LOG_SQL` to false in the `[database]` section.
|
||||
|
||||
### Router Log (`log`)
|
||||
|
||||
- `DISABLE_ROUTER_LOG`: **false**: Mute printing of the router log.
|
||||
- `ROUTER`: **console**: The mode or name of the log the router should log to. (If you set this to `,` it will log to default Gitea logger.)
|
||||
NB: You must have `DISABLE_ROUTER_LOG` set to `false` for this option to take effect. Configure each mode in per mode log subsections `\[log.modename.router\]`.
|
||||
|
||||
### Access Log (`log`)
|
||||
|
||||
- `ACCESS_LOG_TEMPLATE`: **`{{.Ctx.RemoteHost}} - {{.Identity}} {{.Start.Format "[02/Jan/2006:15:04:05 -0700]" }} "{{.Ctx.Req.Method}} {{.Ctx.Req.URL.RequestURI}} {{.Ctx.Req.Proto}}" {{.ResponseWriter.Status}} {{.ResponseWriter.Size}} "{{.Ctx.Req.Referer}}" "{{.Ctx.Req.UserAgent}}"`**: Sets the template used to create the access log.
|
||||
- `ENABLE_ACCESS_LOG`: **false**: Creates an access.log in NCSA common log format, or as per the following template
|
||||
- `ACCESS`: **file**: Logging mode for the access logger, use a comma to separate values. Configure each mode in per mode log subsections `\[log.modename.access\]`. By default the file mode will log to `$ROOT_PATH/access.log`. (If you set this to `,` it will log to the default Gitea logger.)
|
||||
- `ACCESS_LOG_TEMPLATE`: **`{{.Ctx.RemoteAddr}} - {{.Identity}} {{.Start.Format "[02/Jan/2006:15:04:05 -0700]" }} "{{.Ctx.Req.Method}} {{.Ctx.Req.URL.RequestURI}} {{.Ctx.Req.Proto}}" {{.ResponseWriter.Status}} {{.ResponseWriter.Size}} "{{.Ctx.Req.Referer}}\" \"{{.Ctx.Req.UserAgent}}"`**: Sets the template used to create the access log.
|
||||
- The following variables are available:
|
||||
- `Ctx`: the `context.Context` of the request.
|
||||
- `Identity`: the SignedUserName or `"-"` if not logged in.
|
||||
- `Start`: the start time of the request.
|
||||
- `ResponseWriter`: the responseWriter from the request.
|
||||
- `RequestID`: the value matching REQUEST_ID_HEADERS(default: `-`, if not matched).
|
||||
- You must be very careful to ensure that this template does not throw errors or panics as this template runs outside the panic/recovery script.
|
||||
- `REQUEST_ID_HEADERS`: **_empty_**: You can configure multiple values that are splited by comma here. It will match in the order of configuration, and the first match will be finally printed in the access log.
|
||||
- e.g.
|
||||
- In the Request Header: X-Request-ID: **test-id-123**
|
||||
- Configuration in app.ini: REQUEST_ID_HEADERS = X-Request-ID
|
||||
- Print in log: 127.0.0.1:58384 - - [14/Feb/2023:16:33:51 +0800] "**test-id-123**" ...
|
||||
- You must be very careful to ensure that this template does not throw errors or panics as this template runs outside of the panic/recovery script.
|
||||
|
||||
### Log subsections (`log.<writer-mode-name>`)
|
||||
### Log subsections (`log.name`, `log.name.*`)
|
||||
|
||||
- `MODE`: **name**: Sets the mode of this log writer - Defaults to the provided subsection name. This allows you to have two different file loggers at different levels.
|
||||
- `LEVEL`: **log.LEVEL**: Sets the log-level of this writer. Defaults to the `LEVEL` set in the global `[log]` section.
|
||||
- `LEVEL`: **log.LEVEL**: Sets the log-level of this sublogger. Defaults to the `LEVEL` set in the global `[log]` section.
|
||||
- `STACKTRACE_LEVEL`: **log.STACKTRACE_LEVEL**: Sets the log level at which to log stack traces.
|
||||
- `MODE`: **name**: Sets the mode of this sublogger - Defaults to the provided subsection name. This allows you to have two different file loggers at different levels.
|
||||
- `EXPRESSION`: **""**: A regular expression to match either the function name, file or message. Defaults to empty. Only log messages that match the expression will be saved in the logger.
|
||||
- `FLAGS`: **stdflags**: A comma separated string representing the log flags. Defaults to `stdflags` which represents the prefix: `2009/01/23 01:23:23 ...a/b/c/d.go:23:runtime.Caller() [I]: message`. `none` means don't prefix log lines. See `modules/log/flags.go` for more information.
|
||||
- `PREFIX`: **""**: An additional prefix for every log line in this logger. Defaults to empty.
|
||||
- `COLORIZE`: **false**: Whether to colorize the log lines
|
||||
|
||||
### Console log mode (`log.console`, or `MODE=console`)
|
||||
### Console log mode (`log.console`, `log.console.*`, or `MODE=console`)
|
||||
|
||||
- For the console logger `COLORIZE` will default to `true` if not on windows or the terminal is determined to be able to color.
|
||||
- `STDERR`: **false**: Use Stderr instead of Stdout.
|
||||
|
||||
### File log mode (`log.file`, or `MODE=file`)
|
||||
### File log mode (`log.file`, `log.file.*` or `MODE=file`)
|
||||
|
||||
- `FILE_NAME`: Set the file name for this logger. Defaults to `gitea.log` (exception: access log defaults to `access.log`). If relative will be relative to the `ROOT_PATH`
|
||||
- `FILE_NAME`: Set the file name for this logger. Defaults as described above. If relative will be relative to the `ROOT_PATH`
|
||||
- `LOG_ROTATE`: **true**: Rotate the log files.
|
||||
- `MAX_SIZE_SHIFT`: **28**: Maximum size shift of a single file, 28 represents 256Mb.
|
||||
- `DAILY_ROTATE`: **true**: Rotate logs daily.
|
||||
@@ -881,13 +909,21 @@ Default templates for project boards:
|
||||
- `COMPRESS`: **true**: Compress old log files by default with gzip
|
||||
- `COMPRESSION_LEVEL`: **-1**: Compression level
|
||||
|
||||
### Conn log mode (`log.conn`, or `MODE=conn`)
|
||||
### Conn log mode (`log.conn`, `log.conn.*` or `MODE=conn`)
|
||||
|
||||
- `RECONNECT_ON_MSG`: **false**: Reconnect host for every single message.
|
||||
- `RECONNECT`: **false**: Try to reconnect when connection is lost.
|
||||
- `PROTOCOL`: **tcp**: Set the protocol, either "tcp", "unix" or "udp".
|
||||
- `ADDR`: **:7020**: Sets the address to connect to.
|
||||
|
||||
### SMTP log mode (`log.smtp`, `log.smtp.*` or `MODE=smtp`)
|
||||
|
||||
- `USER`: User email address to send from.
|
||||
- `PASSWD`: Password for the smtp server.
|
||||
- `HOST`: **127.0.0.1:25**: The SMTP host to connect to.
|
||||
- `RECEIVERS`: Email addresses to send to.
|
||||
- `SUBJECT`: **Diagnostic message from Gitea**
|
||||
|
||||
## Cron (`cron`)
|
||||
|
||||
- `ENABLED`: **false**: Enable to run all cron tasks periodically with default settings.
|
||||
@@ -1011,7 +1047,7 @@ Default templates for project boards:
|
||||
- `RUN_AT_START`: **false**: Run tasks at start up time (if ENABLED).
|
||||
- `ENABLE_SUCCESS_NOTICE`: **true**: Set to false to switch off success notices.
|
||||
- `SCHEDULE`: **@every 168h**: Cron syntax for scheduling a work, e.g. `@every 168h`.
|
||||
- `HTTP_ENDPOINT`: **https://dl.gitea.com/gitea/version.json**: the endpoint that Gitea will check for newer versions
|
||||
- `HTTP_ENDPOINT`: **https://dl.gitea.io/gitea/version.json**: the endpoint that Gitea will check for newer versions
|
||||
|
||||
#### Cron - Delete all old system notices from database (`cron.delete_old_system_notices`)
|
||||
|
||||
@@ -1052,7 +1088,12 @@ Default templates for project boards:
|
||||
- `DISABLE_CORE_PROTECT_NTFS`: **false** Set to true to forcibly set `core.protectNTFS` to false.
|
||||
- `DISABLE_PARTIAL_CLONE`: **false** Disable the usage of using partial clones for git.
|
||||
|
||||
### Git - Timeout settings (`git.timeout`)
|
||||
## Git - Reflog settings (`git.reflog`)
|
||||
|
||||
- `ENABLED`: **true** Set to true to enable Git to write changes to reflogs in each repo.
|
||||
- `EXPIRATION`: **90** Reflog entry lifetime, in days. Entries are removed opportunistically by Git.
|
||||
|
||||
## Git - Timeout settings (`git.timeout`)
|
||||
|
||||
- `DEFAULT`: **360**: Git operations default timeout seconds.
|
||||
- `MIGRATE`: **600**: Migrate external repositories timeout seconds.
|
||||
@@ -1061,15 +1102,6 @@ Default templates for project boards:
|
||||
- `PULL`: **300**: Git pull from internal repositories timeout seconds.
|
||||
- `GC`: **60**: Git repository GC timeout seconds.
|
||||
|
||||
### Git - Config options (`git.config`)
|
||||
|
||||
The key/value pairs in this section will be used as git config.
|
||||
This section only does "set" config, a removed config key from this section won't be removed from git config automatically. The format is `some.configKey = value`.
|
||||
|
||||
- `diff.algorithm`: **histogram**
|
||||
- `core.logAllRefUpdates`: **true**
|
||||
- `gc.reflogExpire`: **90**
|
||||
|
||||
## Metrics (`metrics`)
|
||||
|
||||
- `ENABLED`: **false**: Enables /metrics endpoint for prometheus.
|
||||
@@ -1113,7 +1145,7 @@ Gitea can support Markup using external tools. The example below will add a mark
|
||||
ENABLED = true
|
||||
NEED_POSTPROCESS = true
|
||||
FILE_EXTENSIONS = .adoc,.asciidoc
|
||||
RENDER_COMMAND = "asciidoctor --embedded --safe-mode=secure --out-file=- -"
|
||||
RENDER_COMMAND = "asciidoc --out-file=- -"
|
||||
IS_INPUT_FILE = false
|
||||
```
|
||||
|
||||
@@ -1164,6 +1196,7 @@ in this mapping or the filetype using heuristics.
|
||||
|
||||
## Time (`time`)
|
||||
|
||||
- `FORMAT`: Time format to display on UI. i.e. RFC1123 or 2006-01-02 15:04:05
|
||||
- `DEFAULT_UI_LOCATION`: Default location of time on the UI, so that we can display correct user's time on UI. i.e. Asia/Shanghai
|
||||
|
||||
## Task (`task`)
|
||||
@@ -1172,7 +1205,7 @@ Task queue configuration has been moved to `queue.task`. However, the below conf
|
||||
|
||||
- `QUEUE_TYPE`: **channel**: Task queue type, could be `channel` or `redis`.
|
||||
- `QUEUE_LENGTH`: **1000**: Task queue length, available only when `QUEUE_TYPE` is `channel`.
|
||||
- `QUEUE_CONN_STR`: **redis://127.0.0.1:6379/0**: Task queue connection string, available only when `QUEUE_TYPE` is `redis`. If redis needs a password, use `redis://123@127.0.0.1:6379/0` or `redis+cluster://123@127.0.0.1:6379/0`.
|
||||
- `QUEUE_CONN_STR`: **redis://127.0.0.1:6379/0**: Task queue connection string, available only when `QUEUE_TYPE` is `redis`. If redis needs a password, use `redis://123@127.0.0.1:6379/0`.
|
||||
|
||||
## Migrations (`migrations`)
|
||||
|
||||
@@ -1202,26 +1235,20 @@ Task queue configuration has been moved to `queue.task`. However, the below conf
|
||||
- `CHUNKED_UPLOAD_PATH`: **tmp/package-upload**: Path for chunked uploads. Defaults to `APP_DATA_PATH` + `tmp/package-upload`
|
||||
- `LIMIT_TOTAL_OWNER_COUNT`: **-1**: Maximum count of package versions a single owner can have (`-1` means no limits)
|
||||
- `LIMIT_TOTAL_OWNER_SIZE`: **-1**: Maximum size of packages a single owner can use (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||
- `LIMIT_SIZE_ALPINE`: **-1**: Maximum size of an Alpine upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||
- `LIMIT_SIZE_CARGO`: **-1**: Maximum size of a Cargo upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||
- `LIMIT_SIZE_CHEF`: **-1**: Maximum size of a Chef upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||
- `LIMIT_SIZE_COMPOSER`: **-1**: Maximum size of a Composer upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||
- `LIMIT_SIZE_CONAN`: **-1**: Maximum size of a Conan upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||
- `LIMIT_SIZE_CONDA`: **-1**: Maximum size of a Conda upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||
- `LIMIT_SIZE_CONTAINER`: **-1**: Maximum size of a Container upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||
- `LIMIT_SIZE_CRAN`: **-1**: Maximum size of a CRAN upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||
- `LIMIT_SIZE_DEBIAN`: **-1**: Maximum size of a Debian upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||
- `LIMIT_SIZE_GENERIC`: **-1**: Maximum size of a Generic upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||
- `LIMIT_SIZE_GO`: **-1**: Maximum size of a Go upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||
- `LIMIT_SIZE_HELM`: **-1**: Maximum size of a Helm upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||
- `LIMIT_SIZE_MAVEN`: **-1**: Maximum size of a Maven upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||
- `LIMIT_SIZE_NPM`: **-1**: Maximum size of a npm upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||
- `LIMIT_SIZE_NUGET`: **-1**: Maximum size of a NuGet upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||
- `LIMIT_SIZE_PUB`: **-1**: Maximum size of a Pub upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||
- `LIMIT_SIZE_PYPI`: **-1**: Maximum size of a PyPI upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||
- `LIMIT_SIZE_RPM`: **-1**: Maximum size of a RPM upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||
- `LIMIT_SIZE_RUBYGEMS`: **-1**: Maximum size of a RubyGems upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||
- `LIMIT_SIZE_SWIFT`: **-1**: Maximum size of a Swift upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||
- `LIMIT_SIZE_VAGRANT`: **-1**: Maximum size of a Vagrant upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||
|
||||
## Mirror (`mirror`)
|
||||
@@ -1252,9 +1279,8 @@ is `data/lfs` and the default of `MINIO_BASE_PATH` is `lfs/`.
|
||||
|
||||
## Storage (`storage`)
|
||||
|
||||
Default storage configuration for attachments, lfs, avatars, repo-avatars, repo-archive, packages, actions_log, actions_artifact.
|
||||
Default storage configuration for attachments, lfs, avatars and etc.
|
||||
|
||||
- `STORAGE_TYPE`: **local**: Storage type, `local` for local disk or `minio` for s3 compatible object storage service.
|
||||
- `SERVE_DIRECT`: **false**: Allows the storage driver to redirect to authenticated URLs to serve files directly. Currently, only Minio/S3 is supported via signed URLs, local does nothing.
|
||||
- `MINIO_ENDPOINT`: **localhost:9000**: Minio endpoint to connect only available when `STORAGE_TYPE` is `minio`
|
||||
- `MINIO_ACCESS_KEY_ID`: Minio accessKeyID to connect only available when `STORAGE_TYPE` is `minio`
|
||||
@@ -1264,56 +1290,9 @@ Default storage configuration for attachments, lfs, avatars, repo-avatars, repo-
|
||||
- `MINIO_USE_SSL`: **false**: Minio enabled ssl only available when `STORAGE_TYPE` is `minio`
|
||||
- `MINIO_INSECURE_SKIP_VERIFY`: **false**: Minio skip SSL verification available when STORAGE_TYPE is `minio`
|
||||
|
||||
The recommanded storage configuration for minio like below:
|
||||
And you can also define a customize storage like below:
|
||||
|
||||
```ini
|
||||
[storage]
|
||||
STORAGE_TYPE = minio
|
||||
; Minio endpoint to connect only available when STORAGE_TYPE is `minio`
|
||||
MINIO_ENDPOINT = localhost:9000
|
||||
; Minio accessKeyID to connect only available when STORAGE_TYPE is `minio`
|
||||
MINIO_ACCESS_KEY_ID =
|
||||
; Minio secretAccessKey to connect only available when STORAGE_TYPE is `minio`
|
||||
MINIO_SECRET_ACCESS_KEY =
|
||||
; Minio bucket to store the attachments only available when STORAGE_TYPE is `minio`
|
||||
MINIO_BUCKET = gitea
|
||||
; Minio location to create bucket only available when STORAGE_TYPE is `minio`
|
||||
MINIO_LOCATION = us-east-1
|
||||
; Minio enabled ssl only available when STORAGE_TYPE is `minio`
|
||||
MINIO_USE_SSL = false
|
||||
; Minio skip SSL verification available when STORAGE_TYPE is `minio`
|
||||
MINIO_INSECURE_SKIP_VERIFY = false
|
||||
SERVE_DIRECT = true
|
||||
```
|
||||
|
||||
Defaultly every storage has their default base path like below
|
||||
|
||||
| storage | default base path |
|
||||
| ----------------- | ------------------ |
|
||||
| attachments | attachments/ |
|
||||
| lfs | lfs/ |
|
||||
| avatars | avatars/ |
|
||||
| repo-avatars | repo-avatars/ |
|
||||
| repo-archive | repo-archive/ |
|
||||
| packages | packages/ |
|
||||
| actions_log | actions_log/ |
|
||||
| actions_artifacts | actions_artifacts/ |
|
||||
|
||||
And bucket, basepath or `SERVE_DIRECT` could be special or overrided, if you want to use a different you can:
|
||||
|
||||
```ini
|
||||
[storage.actions_log]
|
||||
MINIO_BUCKET = gitea_actions_log
|
||||
SERVE_DIRECT = true
|
||||
MINIO_BASE_PATH = my_actions_log/ ; default is actions_log/ if blank
|
||||
```
|
||||
|
||||
If you want to customerize a different storage for `lfs` if above default storage defined
|
||||
|
||||
```ini
|
||||
[lfs]
|
||||
STORAGE_TYPE = my_minio
|
||||
|
||||
[storage.my_minio]
|
||||
STORAGE_TYPE = minio
|
||||
; Minio endpoint to connect only available when STORAGE_TYPE is `minio`
|
||||
@@ -1332,6 +1311,8 @@ MINIO_USE_SSL = false
|
||||
MINIO_INSECURE_SKIP_VERIFY = false
|
||||
```
|
||||
|
||||
And used by `[attachment]`, `[lfs]` and etc. as `STORAGE_TYPE`.
|
||||
|
||||
## Repository Archive Storage (`storage.repo-archive`)
|
||||
|
||||
Configuration for repository archive storage. It will inherit from default `[storage]` or
|
||||
@@ -1350,11 +1331,6 @@ is `data/repo-archive` and the default of `MINIO_BASE_PATH` is `repo-archive/`.
|
||||
- `MINIO_USE_SSL`: **false**: Minio enabled ssl only available when `STORAGE_TYPE` is `minio`
|
||||
- `MINIO_INSECURE_SKIP_VERIFY`: **false**: Minio skip SSL verification available when STORAGE_TYPE is `minio`
|
||||
|
||||
## Repository Archives (`repo-archive`)
|
||||
|
||||
- `STORAGE_TYPE`: **local**: Storage type for actions logs, `local` for local disk or `minio` for s3 compatible object storage service, default is `local` or other name defined with `[storage.xxx]`
|
||||
- `MINIO_BASE_PATH`: **repo-archive/**: Minio base path on the bucket only available when STORAGE_TYPE is `minio`
|
||||
|
||||
## Proxy (`proxy`)
|
||||
|
||||
- `PROXY_ENABLED`: **false**: Enable the proxy if true, all requests to external via HTTP will be affected, if false, no proxy will be used even environment http_proxy/https_proxy
|
||||
@@ -1372,25 +1348,41 @@ PROXY_HOSTS = *.github.com
|
||||
## Actions (`actions`)
|
||||
|
||||
- `ENABLED`: **false**: Enable/Disable actions capabilities
|
||||
- `DEFAULT_ACTIONS_URL`: **github**: Default platform to get action plugins, `github` for `https://github.com`, `self` for the current Gitea instance.
|
||||
- `STORAGE_TYPE`: **local**: Storage type for actions logs, `local` for local disk or `minio` for s3 compatible object storage service, default is `local` or other name defined with `[storage.xxx]`
|
||||
- `MINIO_BASE_PATH`: **actions_log/**: Minio base path on the bucket only available when STORAGE_TYPE is `minio`
|
||||
- `DEFAULT_ACTIONS_URL`: **https://gitea.com**: Default address to get action plugins, e.g. the default value means downloading from "https://gitea.com/actions/checkout" for "uses: actions/checkout@v3"
|
||||
|
||||
`DEFAULT_ACTIONS_URL` indicates where the Gitea Actions runners should find the actions with relative path.
|
||||
For example, `uses: actions/checkout@v3` means `https://github.com/actions/checkout@v3` since the value of `DEFAULT_ACTIONS_URL` is `github`.
|
||||
And it can be changed to `self` to make it `root_url_of_your_gitea/actions/checkout@v3`.
|
||||
`DEFAULT_ACTIONS_URL` indicates where should we find the relative path action plugin. i.e. when use an action in a workflow file like
|
||||
|
||||
Please note that using `self` is not recommended for most cases, as it could make names globally ambiguous.
|
||||
Additionally, it requires you to mirror all the actions you need to your Gitea instance, which may not be worth it.
|
||||
Therefore, please use `self` only if you understand what you are doing.
|
||||
```yaml
|
||||
name: versions
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- releases/*
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
```
|
||||
|
||||
In earlier versions (<= 1.19), `DEFAULT_ACTIONS_URL` cound be set to any custom URLs like `https://gitea.com` or `http://your-git-server,https://gitea.com`, and the default value was `https://gitea.com`.
|
||||
However, later updates removed those options, and now the only options are `github` and `self`, with the default value being `github`.
|
||||
However, if you want to use actions from other git server, you can use a complete URL in `uses` field, it's supported by Gitea (but not GitHub).
|
||||
Like `uses: https://gitea.com/actions/checkout@v3` or `uses: http://your-git-server/actions/checkout@v3`.
|
||||
Now we need to know how to get actions/checkout, this configuration is the default git server to get it. That means we will get the repository via git clone `${DEFAULT_ACTIONS_URL}/actions/checkout` and fetch tag v3.
|
||||
|
||||
To help people who don't want to mirror these actions in their git instances, the default value is https://gitea.com
|
||||
To help people run actions totally in their network, they can change the value and copy all necessary action repositories into their git server.
|
||||
|
||||
Of course we should support the form in future PRs like
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: gitea.com/actions/checkout@v3
|
||||
```
|
||||
|
||||
although Github don't support this form.
|
||||
|
||||
## Other (`other`)
|
||||
|
||||
- `SHOW_FOOTER_BRANDING`: **false**: Show Gitea branding in the footer.
|
||||
- `SHOW_FOOTER_VERSION`: **true**: Show Gitea and Go version information in the footer.
|
||||
- `SHOW_FOOTER_TEMPLATE_LOAD_TIME`: **true**: Show time of template execution in the footer.
|
||||
- `ENABLE_SITEMAP`: **true**: Generate sitemap.
|
||||
|
||||
@@ -5,8 +5,6 @@ slug: "config-cheat-sheet"
|
||||
sidebar_position: 30
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /zh-cn/config-cheat-sheet
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
@@ -41,6 +39,7 @@ menu:
|
||||
- `DEFAULT_PRIVATE`: 默认创建的git工程为私有。 可以是`last`, `private` 或 `public`。默认值是 `last`表示用户最后创建的Repo的选择。
|
||||
- `DEFAULT_PUSH_CREATE_PRIVATE`: **true**: 通过 ``push-to-create`` 方式创建的仓库是否默认为私有仓库.
|
||||
- `MAX_CREATION_LIMIT`: 全局最大每个用户创建的git工程数目, `-1` 表示没限制。
|
||||
- `PULL_REQUEST_QUEUE_LENGTH`: 小心:合并请求测试队列的长度,尽量放大。
|
||||
|
||||
### Repository - Release (`repository.release`)
|
||||
|
||||
@@ -108,6 +107,10 @@ menu:
|
||||
- `ISSUE_INDEXER_CONN_STR`: ****: 工单索引连接字符串,仅当 ISSUE_INDEXER_TYPE 为 `elasticsearch` 时有效。例如: http://elastic:changeme@localhost:9200
|
||||
- `ISSUE_INDEXER_NAME`: **gitea_issues**: 工单索引名称,仅当 ISSUE_INDEXER_TYPE 为 `elasticsearch` 时有效。
|
||||
- `ISSUE_INDEXER_PATH`: **indexers/issues.bleve**: 工单索引文件存放路径,当索引类型为 `bleve` 时有效。
|
||||
- `ISSUE_INDEXER_QUEUE_TYPE`: **levelqueue**: 工单索引队列类型,当前支持 `channel`, `levelqueue` 或 `redis`。
|
||||
- `ISSUE_INDEXER_QUEUE_DIR`: **indexers/issues.queue**: 当 `ISSUE_INDEXER_QUEUE_TYPE` 为 `levelqueue` 时,保存索引队列的磁盘路径。
|
||||
- `ISSUE_INDEXER_QUEUE_CONN_STR`: **addrs=127.0.0.1:6379 db=0**: 当 `ISSUE_INDEXER_QUEUE_TYPE` 为 `redis` 时,保存Redis队列的连接字符串。
|
||||
- `ISSUE_INDEXER_QUEUE_BATCH_NUMBER`: **20**: 队列处理中批量提交数量。
|
||||
|
||||
- `REPO_INDEXER_ENABLED`: **false**: 是否启用代码搜索(启用后会占用比较大的磁盘空间,如果是bleve可能需要占用约6倍存储空间)。
|
||||
- `REPO_INDEXER_TYPE`: **bleve**: 代码搜索引擎类型,可以为 `bleve` 或者 `elasticsearch`。
|
||||
@@ -115,6 +118,7 @@ menu:
|
||||
- `REPO_INDEXER_CONN_STR`: ****: 代码搜索引擎连接字符串,当 `REPO_INDEXER_TYPE` 为 `elasticsearch` 时有效。例如: http://elastic:changeme@localhost:9200
|
||||
- `REPO_INDEXER_NAME`: **gitea_codes**: 代码搜索引擎的名字,当 `REPO_INDEXER_TYPE` 为 `elasticsearch` 时有效。
|
||||
|
||||
- `UPDATE_BUFFER_LEN`: **20**: 代码索引请求的缓冲区长度。
|
||||
- `MAX_FILE_SIZE`: **1048576**: 进行解析的源代码文件的最大长度,小于该值时才会索引。
|
||||
|
||||
## Security (`security`)
|
||||
@@ -212,8 +216,8 @@ menu:
|
||||
- `AVATAR_STORAGE_TYPE`: **local**: 头像存储类型,可以为 `local` 或 `minio`,分别支持本地文件系统和 minio 兼容的API。
|
||||
- `AVATAR_UPLOAD_PATH`: **data/avatars**: 存储头像的文件系统路径。
|
||||
- `AVATAR_MAX_WIDTH`: **4096**: 头像最大宽度,单位像素。
|
||||
- `AVATAR_MAX_HEIGHT`: **4096**: 头像最大高度,单位像素。
|
||||
- `AVATAR_MAX_FILE_SIZE`: **1048576** (1MiB): 头像最大大小。
|
||||
- `AVATAR_MAX_HEIGHT`: **3072**: 头像最大高度,单位像素。
|
||||
- `AVATAR_MAX_FILE_SIZE`: **1048576** (1Mb): 头像最大大小。
|
||||
|
||||
- `REPOSITORY_AVATAR_STORAGE_TYPE`: **local**: 仓库头像存储类型,可以为 `local` 或 `minio`,分别支持本地文件系统和 minio 兼容的API。
|
||||
- `REPOSITORY_AVATAR_UPLOAD_PATH`: **data/repo-avatars**: 存储仓库头像的路径。
|
||||
@@ -256,22 +260,7 @@ test01.xls: application/vnd.ms-excel; charset=binary
|
||||
|
||||
- `ROOT_PATH`: 日志文件根目录。
|
||||
- `MODE`: 日志记录模式,默认是为 `console`。如果要写到多个通道,用逗号分隔
|
||||
- `LEVEL`: 日志级别,默认为 `Trace`。
|
||||
- `DISABLE_ROUTER_LOG`: 关闭日志中的路由日志。
|
||||
- `ENABLE_ACCESS_LOG`: 是否开启 Access Log, 默认为 false。
|
||||
- `ACCESS_LOG_TEMPLATE`: `access.log` 输出内容的模板,默认模板:**`{{.Ctx.RemoteHost}} - {{.Identity}} {{.Start.Format "[02/Jan/2006:15:04:05 -0700]" }} "{{.Ctx.Req.Method}} {{.Ctx.Req.URL.RequestURI}} {{.Ctx.Req.Proto}}" {{.ResponseWriter.Status}} {{.ResponseWriter.Size}} "{{.Ctx.Req.Referer}}" "{{.Ctx.Req.UserAgent}}"`**
|
||||
模板支持以下参数:
|
||||
- `Ctx`: 请求上下文。
|
||||
- `Identity`: 登录用户名,默认: “`-`”。
|
||||
- `Start`: 请求开始时间。
|
||||
- `ResponseWriter`:
|
||||
- `RequestID`: 从请求头中解析得到的与 `REQUEST_ID_HEADERS` 匹配的值,默认: “`-`”。
|
||||
- 一定要谨慎配置该模板,否则可能会引起panic.
|
||||
- `REQUEST_ID_HEADERS`: 从 Request Header 中匹配指定 Key,并将匹配到的值输出到 `access.log` 中(需要在 `ACCESS_LOG_TEMPLATE` 中指定输出位置)。如果在该参数中配置多个 Key, 请用逗号分割,程序将按照配置的顺序进行匹配。
|
||||
- 示例:
|
||||
- 请求头: X-Request-ID: **test-id-123**
|
||||
- 配置文件: REQUEST_ID_HEADERS = X-Request-ID
|
||||
- 日志输出: 127.0.0.1:58384 - - [14/Feb/2023:16:33:51 +0800] "**test-id-123**" ...
|
||||
- `LEVEL`: 日志级别,默认为`Trace`。
|
||||
|
||||
## Cron (`cron`)
|
||||
|
||||
@@ -335,7 +324,7 @@ test01.xls: application/vnd.ms-excel; charset=binary
|
||||
ENABLED = false
|
||||
NEED_POSTPROCESS = true
|
||||
FILE_EXTENSIONS = .adoc,.asciidoc
|
||||
RENDER_COMMAND = "asciidoctor --embedded --safe-mode=secure --out-file=- -"
|
||||
RENDER_COMMAND = "asciidoc --out-file=- -"
|
||||
IS_INPUT_FILE = false
|
||||
```
|
||||
|
||||
@@ -412,7 +401,7 @@ LFS 的存储配置。 如果 `STORAGE_TYPE` 为空,则此配置将从 `[stora
|
||||
|
||||
## Storage (`storage`)
|
||||
|
||||
Attachments, lfs, avatars, repo-avatars, repo-archive, packages, actions_log, actions_artifact 的默认存储配置。
|
||||
Attachments, lfs, avatars and etc 的默认存储配置。
|
||||
|
||||
- `STORAGE_TYPE`: **local**: 附件存储类型,`local` 将存储到本地文件夹, `minio` 将存储到 s3 兼容的对象存储服务中。
|
||||
- `SERVE_DIRECT`: **false**: 允许直接重定向到存储系统。当前,仅 Minio/S3 是支持的。
|
||||
@@ -423,59 +412,9 @@ Attachments, lfs, avatars, repo-avatars, repo-archive, packages, actions_log, ac
|
||||
- `MINIO_LOCATION`: **us-east-1**: Minio location to create bucket,仅当 `STORAGE_TYPE` 是 `minio` 时有效。
|
||||
- `MINIO_USE_SSL`: **false**: Minio enabled ssl,仅当 `STORAGE_TYPE` 是 `minio` 时有效。
|
||||
|
||||
以下为推荐的 recommanded storage configuration for minio like below:
|
||||
你也可以自定义一个存储的名字如下:
|
||||
|
||||
```ini
|
||||
[storage]
|
||||
STORAGE_TYPE = minio
|
||||
; uncomment when STORAGE_TYPE = local
|
||||
; PATH = storage root path
|
||||
; Minio endpoint to connect only available when STORAGE_TYPE is `minio`
|
||||
MINIO_ENDPOINT = localhost:9000
|
||||
; Minio accessKeyID to connect only available when STORAGE_TYPE is `minio`
|
||||
MINIO_ACCESS_KEY_ID =
|
||||
; Minio secretAccessKey to connect only available when STORAGE_TYPE is `minio`
|
||||
MINIO_SECRET_ACCESS_KEY =
|
||||
; Minio bucket to store the attachments only available when STORAGE_TYPE is `minio`
|
||||
MINIO_BUCKET = gitea
|
||||
; Minio location to create bucket only available when STORAGE_TYPE is `minio`
|
||||
MINIO_LOCATION = us-east-1
|
||||
; Minio enabled ssl only available when STORAGE_TYPE is `minio`
|
||||
MINIO_USE_SSL = false
|
||||
; Minio skip SSL verification available when STORAGE_TYPE is `minio`
|
||||
MINIO_INSECURE_SKIP_VERIFY = false
|
||||
SERVE_DIRECT = true
|
||||
```
|
||||
|
||||
默认的,每一个存储都会有各自默认的 BasePath 在同一个minio中,默认值如下:
|
||||
|
||||
| storage | default base path |
|
||||
| ----------------- | ------------------ |
|
||||
| attachments | attachments/ |
|
||||
| lfs | lfs/ |
|
||||
| avatars | avatars/ |
|
||||
| repo-avatars | repo-avatars/ |
|
||||
| repo-archive | repo-archive/ |
|
||||
| packages | packages/ |
|
||||
| actions_log | actions_log/ |
|
||||
| actions_artifacts | actions_artifacts/ |
|
||||
|
||||
同时 bucket, basepath or `SERVE_DIRECT` 是可以被覆写的,像如下所示:
|
||||
|
||||
```ini
|
||||
[storage.actions_log]
|
||||
MINIO_BUCKET = gitea_actions_log
|
||||
SERVE_DIRECT = true
|
||||
MINIO_BASE_PATH = my_actions_log/ ; default is actions_log/ if blank
|
||||
```
|
||||
|
||||
当然你也可以完全自定义,像如下
|
||||
|
||||
```ini
|
||||
[lfs]
|
||||
STORAGE_TYPE = my_minio
|
||||
MINIO_BASE_PATH = my_lfs_basepath
|
||||
|
||||
[storage.my_minio]
|
||||
STORAGE_TYPE = minio
|
||||
; Minio endpoint to connect only available when STORAGE_TYPE is `minio`
|
||||
@@ -492,9 +431,10 @@ MINIO_LOCATION = us-east-1
|
||||
MINIO_USE_SSL = false
|
||||
; Minio skip SSL verification available when STORAGE_TYPE is `minio`
|
||||
MINIO_INSECURE_SKIP_VERIFY = false
|
||||
SERVE_DIRECT = true
|
||||
```
|
||||
|
||||
然后你在 `[attachment]`, `[lfs]` 等中可以把这个名字用作 `STORAGE_TYPE` 的值。
|
||||
|
||||
## Repository Archive Storage (`storage.repo-archive`)
|
||||
|
||||
Repository archive 的存储配置。 如果 `STORAGE_TYPE` 为空,则此配置将从 `[storage]` 继承。如果不为 `local` 或者 `minio` 而为 `xxx`, 则从 `[storage.xxx]` 继承。当继承时, `PATH` 默认为 `data/repo-archive`,`MINIO_BASE_PATH` 默认为 `repo-archive/`。
|
||||
@@ -526,4 +466,5 @@ PROXY_HOSTS = *.github.com
|
||||
|
||||
## Other (`other`)
|
||||
|
||||
- `SHOW_FOOTER_BRANDING`: 为真则在页面底部显示Gitea的字样。
|
||||
- `SHOW_FOOTER_VERSION`: 为真则在页面底部显示Gitea的版本。
|
||||
|
||||
@@ -5,8 +5,6 @@ slug: "customizing-gitea"
|
||||
sidebar_position: 100
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /en-us/customizing-gitea
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
@@ -18,7 +16,7 @@ menu:
|
||||
# Customizing Gitea
|
||||
|
||||
Customizing Gitea is typically done using the `CustomPath` folder - by default this is
|
||||
the `custom` folder from the working directory (WorkPath), but may be different if your build has
|
||||
the `custom` folder from the running directory, but may be different if your build has
|
||||
set this differently. This is the central place to override configuration settings,
|
||||
templates, etc. You can check the `CustomPath` using `gitea help`. You can also find
|
||||
the path on the _Configuration_ tab in the _Site Administration_ page. You can override
|
||||
@@ -278,22 +276,6 @@ Place custom files in corresponding sub-folder under `custom/options`.
|
||||
|
||||
To add custom .gitignore, add a file with existing [.gitignore rules](https://git-scm.com/docs/gitignore) in it to `$GITEA_CUSTOM/options/gitignore`
|
||||
|
||||
## Customizing the git configuration
|
||||
|
||||
Starting with Gitea 1.20, you can customize the git configuration via the `git.config` section.
|
||||
|
||||
### Enabling signed git pushes
|
||||
|
||||
To enable signed git pushes, set these two options:
|
||||
|
||||
```ini
|
||||
[git.config]
|
||||
receive.advertisePushOptions = true
|
||||
receive.certNonceSeed = <randomstring>
|
||||
```
|
||||
|
||||
`certNonceSeed` should be set to a random string and be kept secret.
|
||||
|
||||
### Labels
|
||||
|
||||
Starting with Gitea 1.19, you can add a file that follows the [YAML label format](https://github.com/go-gitea/gitea/blob/main/options/label/Advanced.yaml) to `$GITEA_CUSTOM/options/label`:
|
||||
|
||||
@@ -5,8 +5,6 @@ slug: "customizing-gitea"
|
||||
sidebar_position: 100
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /zh-cn/customizing-gitea
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
|
||||
@@ -5,8 +5,6 @@ slug: "email-setup"
|
||||
sidebar_position: 12
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /en-us/email-setup
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
@@ -31,7 +29,7 @@ Note: For Internet-facing sites consult documentation of your MTA for instructio
|
||||
[mailer]
|
||||
ENABLED = true
|
||||
FROM = gitea@mydomain.com
|
||||
PROTOCOL = sendmail
|
||||
MAILER_TYPE = sendmail
|
||||
SENDMAIL_PATH = /usr/sbin/sendmail
|
||||
SENDMAIL_ARGS = "--" ; most "sendmail" programs take options, "--" will prevent an email address being interpreted as an option.
|
||||
```
|
||||
@@ -44,9 +42,10 @@ Directly use SMTP server as relay. This option is useful if you don't want to se
|
||||
[mailer]
|
||||
ENABLED = true
|
||||
FROM = gitea@mydomain.com
|
||||
PROTOCOL = smtps
|
||||
MAILER_TYPE = smtp
|
||||
SMTP_ADDR = mail.mydomain.com
|
||||
SMTP_PORT = 587
|
||||
IS_TLS_ENABLED = true
|
||||
USER = gitea@mydomain.com
|
||||
PASSWD = `password`
|
||||
```
|
||||
@@ -79,7 +78,7 @@ SMTP_PORT = 465
|
||||
FROM = example.user@gmail.com
|
||||
USER = example.user
|
||||
PASSWD = `***`
|
||||
PROTOCOL = smtp
|
||||
MAILER_TYPE = smtp
|
||||
IS_TLS_ENABLED = true
|
||||
```
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ Gitea 具有邮件功能,用于发送事务性邮件(例如注册确认邮
|
||||
[mailer]
|
||||
ENABLED = true
|
||||
FROM = gitea@mydomain.com
|
||||
PROTOCOL = sendmail
|
||||
MAILER_TYPE = sendmail
|
||||
SENDMAIL_PATH = /usr/sbin/sendmail
|
||||
SENDMAIL_ARGS = "--" ; 大多数 "sendmail" 程序都接受选项,使用 "--" 将防止电子邮件地址被解释为选项。
|
||||
```
|
||||
@@ -44,9 +44,10 @@ SENDMAIL_ARGS = "--" ; 大多数 "sendmail" 程序都接受选项,使用 "--"
|
||||
[mailer]
|
||||
ENABLED = true
|
||||
FROM = gitea@mydomain.com
|
||||
PROTOCOL = smtps
|
||||
MAILER_TYPE = smtp
|
||||
SMTP_ADDR = mail.mydomain.com
|
||||
SMTP_PORT = 587
|
||||
IS_TLS_ENABLED = true
|
||||
USER = gitea@mydomain.com
|
||||
PASSWD = `password`
|
||||
```
|
||||
@@ -55,7 +56,7 @@ PASSWD = `password`
|
||||
|
||||
要发送测试邮件以验证设置,请转到 Gitea > 站点管理 > 配置 > SMTP 邮件配置。
|
||||
|
||||
有关所有选项的完整列表,请查看[配置速查表](doc/administration/config-cheat-sheet.zh-cn.md)。
|
||||
有关所有选项的完整列表,请查看[配置速查表](administration/config-cheat-sheet.md)。
|
||||
|
||||
请注意:只有在使用 TLS 或 `HOST=localhost` 加密 SMTP 服务器通信时才支持身份验证。TLS 加密可以通过以下方式进行:
|
||||
|
||||
@@ -79,7 +80,8 @@ SMTP_PORT = 465
|
||||
FROM = example.user@gmail.com
|
||||
USER = example.user
|
||||
PASSWD = `***`
|
||||
PROTOCOL = smtps
|
||||
MAILER_TYPE = smtp
|
||||
IS_TLS_ENABLED = true
|
||||
```
|
||||
|
||||
请注意,您需要创建并使用一个 [应用密码](https://support.google.com/accounts/answer/185833?hl=en) 并在您的 Google 帐户上启用 2FA。您将无法直接使用您的 Google 帐户密码。
|
||||
|
||||
@@ -5,8 +5,6 @@ slug: "environment-variables"
|
||||
sidebar_position: 10
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /en-us/environment-variables
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
@@ -39,7 +37,10 @@ For documentation about each of the variables available, refer to the
|
||||
## Gitea files
|
||||
|
||||
- `GITEA_WORK_DIR`: Absolute path of working directory.
|
||||
- `GITEA_CUSTOM`: Gitea uses `WorkPath`/custom folder by default. Use this variable to change _custom_ directory.
|
||||
- `GITEA_CUSTOM`: Gitea uses `GITEA_WORK_DIR`/custom folder by default. Use this variable
|
||||
to change _custom_ directory.
|
||||
- `GOGS_WORK_DIR`: Deprecated, use `GITEA_WORK_DIR`
|
||||
- `GOGS_CUSTOM`: Deprecated, use `GITEA_CUSTOM`
|
||||
|
||||
## Operating system specifics
|
||||
|
||||
|
||||
@@ -5,8 +5,6 @@ slug: "environment-variables"
|
||||
sidebar_position: 10
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /zh-cn/environment-variables
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
|
||||
@@ -5,8 +5,6 @@ slug: "external-renderers"
|
||||
sidebar_position: 60
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /en-us/external-renderers
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
@@ -24,7 +22,7 @@ it is just a matter of:
|
||||
- add some configuration to your `app.ini` file
|
||||
- restart your Gitea instance
|
||||
|
||||
This supports rendering of whole files. If you want to render code blocks in markdown you would need to do something with javascript. See some examples on the [Customizing Gitea](../customizing-gitea) page.
|
||||
This supports rendering of whole files. If you want to render code blocks in markdown you would need to do something with javascript. See some examples on the [Customizing Gitea](administration/customizing-gitea.md) page.
|
||||
|
||||
## Installing external binaries
|
||||
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
---
|
||||
date: "2018-05-11T11:00:00+02:00"
|
||||
title: "Fail2ban Setup "
|
||||
title: "Setup fail2ban"
|
||||
slug: "fail2ban-setup"
|
||||
sidebar_position: 16
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /en-us/fail2ban-setup
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
---
|
||||
date: "2022-08-01T00:00:00+00:00"
|
||||
title: "设置 Fail2ban"
|
||||
title: "使用: 设置 Fail2ban"
|
||||
slug: "fail2ban-setup"
|
||||
sidebar_position: 16
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /zh-cn/fail2ban-setup
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
|
||||
@@ -5,8 +5,6 @@ slug: "git-lfs-setup"
|
||||
sidebar_position: 12
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /en-us/git-lfs-setup
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
|
||||
@@ -5,8 +5,6 @@ slug: "https-setup"
|
||||
sidebar_position: 12
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /en-us/https-setup
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
@@ -36,7 +34,7 @@ KEY_FILE = key.pem
|
||||
```
|
||||
|
||||
Note that if your certificate is signed by a third party certificate authority (i.e. not self-signed), then cert.pem should contain the certificate chain. The server certificate must be the first entry in cert.pem, followed by the intermediaries in order (if any). The root certificate does not have to be included because the connecting client must already have it in order to estalbish the trust relationship.
|
||||
To learn more about the config values, please checkout the [Config Cheat Sheet](../config-cheat-sheet#server-server).
|
||||
To learn more about the config values, please checkout the [Config Cheat Sheet](administration/config-cheat-sheet.md#server-server).
|
||||
|
||||
For the `CERT_FILE` or `KEY_FILE` field, the file path is relative to the `GITEA_CUSTOM` environment variable when it is a relative path. It can be an absolute path as well.
|
||||
|
||||
@@ -85,11 +83,11 @@ ACME_DIRECTORY=https
|
||||
ACME_EMAIL=email@example.com
|
||||
```
|
||||
|
||||
To learn more about the config values, please checkout the [Config Cheat Sheet](../config-cheat-sheet#server-server).
|
||||
To learn more about the config values, please checkout the [Config Cheat Sheet](administration/config-cheat-sheet.md#server-server).
|
||||
|
||||
## Using a reverse proxy
|
||||
|
||||
Setup up your reverse proxy as shown in the [reverse proxy guide](../reverse-proxies).
|
||||
Setup up your reverse proxy as shown in the [reverse proxy guide](administration/reverse-proxies.md).
|
||||
|
||||
After that, enable HTTPS by following one of these guides:
|
||||
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
---
|
||||
date: "2023-04-09T11:00:00+02:00"
|
||||
title: "HTTPS配置"
|
||||
slug: "https-setup"
|
||||
sidebar_position: 12
|
||||
toc: false
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
name: "HTTPS setup"
|
||||
sidebar_position: 12
|
||||
identifier: "https-setup"
|
||||
---
|
||||
|
||||
# HTTPS setup to encrypt connections to Gitea
|
||||
|
||||
## 使用内置服务器
|
||||
|
||||
在启用HTTPS之前,确保您拥有有效的SSL/TLS证书。
|
||||
建议在测试和评估情况下使用自签名证书,请运行 `gitea cert --host [HOST]` 以生成自签名证书
|
||||
|
||||
如果您在服务器上使用阿帕奇(Apache)或Nginx,建议参考 [反向代理指南](administration/reverse-proxies.md)。
|
||||
|
||||
要使用Gitea内置HTTPS支持,您必须编辑`app.ini`文件。
|
||||
|
||||
```ini
|
||||
[server]
|
||||
PROTOCOL = https
|
||||
ROOT_URL = https://git.example.com:3000/
|
||||
HTTP_PORT = 3000
|
||||
CERT_FILE = cert.pem
|
||||
KEY_FILE = key.pem
|
||||
```
|
||||
|
||||
请注意,如果您的证书由第三方证书颁发机构签名(即不是自签名的),则 cert.pem 应包含证书链。服务器证书必须是 cert.pem 中的第一个条目,后跟中介(如果有)。不必包含根证书,因为连接客户端必须已经拥有根证书才能建立信任关系。要了解有关配置值的更多信息,请查看 [配置备忘单](../config-cheat-sheet#server-server)。
|
||||
|
||||
对于“CERT_FILE”或“KEY_FILE”字段,当文件路径是相对路径时,文件路径相对于“GITEA_CUSTOM”环境变量。它也可以是绝对路径。
|
||||
|
||||
### 设置HTTP重定向
|
||||
|
||||
Gitea服务器仅支持监听一个端口;要重定向HTTP请求致HTTPS端口,您需要启用HTTP重定向服务:
|
||||
|
||||
```ini
|
||||
[server]
|
||||
REDIRECT_OTHER_PORT = true
|
||||
; Port the redirection service should listen on
|
||||
PORT_TO_REDIRECT = 3080
|
||||
```
|
||||
|
||||
如果您使用Docker,确保端口已配置在 `docker-compose.yml` 文件
|
||||
|
||||
## 使用 ACME (默认: Let's Encrypt)
|
||||
|
||||
[ACME](https://tools.ietf.org/html/rfc8555) 是一种证书颁发机构标准协议,允许您自动请求和续订 SSL/TLS 证书。[Let`s Encrypt](https://letsencrypt.org/) 是使用此标准的免费公开信任的证书颁发机构服务器。仅实施“HTTP-01”和“TLS-ALPN-01”挑战。为了使 ACME 质询通过并验证您的域所有权,“80”端口(“HTTP-01”)或“443”端口(“TLS-ALPN-01”)上 gitea 域的外部流量必须由 gitea 实例提供服务。可能需要设置 [HTTP 重定向](#设置http重定向) 和端口转发才能正确路由外部流量。否则,到端口“80”的正常流量将自动重定向到 HTTPS。**您必须同意**ACME提供商的服务条款(默认为Let's Encrypt的 [服务条款](https://letsencrypt.org/documents/LE-SA-v1.2-2017年11月15日.pdf)。
|
||||
|
||||
使用默认 Let's Encrypt 的最小配置如下:
|
||||
|
||||
```ini
|
||||
[server]
|
||||
PROTOCOL=https
|
||||
DOMAIN=git.example.com
|
||||
ENABLE_ACME=true
|
||||
ACME_ACCEPTTOS=true
|
||||
ACME_DIRECTORY=https
|
||||
;; Email can be omitted here and provided manually at first run, after which it is cached
|
||||
ACME_EMAIL=email@example.com
|
||||
```
|
||||
|
||||
小型配置请使用 [smallstep CA](https://github.com/smallstep/certificates), 点击 [教程](https://smallstep.com/docs/tutorials/acme-challenge) 了解更多信息。
|
||||
|
||||
```ini
|
||||
[server]
|
||||
PROTOCOL=https
|
||||
DOMAIN=git.example.com
|
||||
ENABLE_ACME=true
|
||||
ACME_ACCEPTTOS=true
|
||||
ACME_URL=https://ca.example.com/acme/acme/directory
|
||||
;; Can be omitted if using the system's trust is preferred
|
||||
;ACME_CA_ROOT=/path/to/root_ca.crt
|
||||
ACME_DIRECTORY=https
|
||||
ACME_EMAIL=email@example.com
|
||||
```
|
||||
|
||||
要了解关于配置, 请访问 [配置备忘单](../config-cheat-sheet#server-server)获取更多信息
|
||||
|
||||
## 使用反向代理服务器
|
||||
|
||||
按照 [reverse proxy guide](../reverse-proxies) 的规则设置你的反向代理服务器
|
||||
|
||||
然后,按照下面的向导启用 HTTPS:
|
||||
|
||||
- [nginx](https://nginx.org/en/docs/http/configuring_https_servers.html)
|
||||
- [apache2/httpd](https://httpd.apache.org/docs/2.4/ssl/ssl_howto.html)
|
||||
- [caddy](https://caddyserver.com/docs/tls)
|
||||
|
||||
注意:仅在代理层启用 HTTPS 被称为 [TLS 终止代理](https://en.wikipedia.org/wiki/TLS_termination_proxy)。代理服务器接受传入的 TLS 连接,解密内容,然后将现在未加密的内容传递给 Gitea。只要代理和 Gitea 实例在同一台计算机上或在私有网络中的不同计算机上(代理暴露给外部网络),这通常是可以接受的。如果您的 Gitea 实例与代理隔离在公共网络上,或者如果您想要全端到端的加密,您还可以直接在 Gitea 中 [启用内置服务器的 HTTPS 支持](#使用内置服务器),并将连接转发到 HTTPS 上。
|
||||
@@ -1,291 +0,0 @@
|
||||
---
|
||||
date: "2019-04-02T17:06:00+01:00"
|
||||
title: "Logging Configuration"
|
||||
slug: "logging-config"
|
||||
sidebar_position: 40
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /en-us/logging-configuration
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
name: "Logging Configuration"
|
||||
sidebar_position: 40
|
||||
identifier: "logging-config"
|
||||
---
|
||||
|
||||
# Logging Configuration
|
||||
|
||||
The logging configuration of Gitea mainly consists of 3 types of components:
|
||||
|
||||
- The `[log]` section for general configuration
|
||||
- `[log.<mode-name>]` sections for the configuration of different log writers to output logs, aka: "writer mode", the mode name is also used as "writer name".
|
||||
- The `[log]` section can also contain sub-logger configurations following the key schema `logger.<logger-name>.<CONFIG-KEY>`
|
||||
|
||||
There is a fully functional log output by default, so it is not necessary to define one.
|
||||
|
||||
## Collecting Logs for Help
|
||||
|
||||
To collect logs for help and issue report, see [Support Options](help/support.md).
|
||||
|
||||
## The `[log]` section
|
||||
|
||||
Configuration of logging facilities in Gitea happen in the `[log]` section and its subsections.
|
||||
|
||||
In the top level `[log]` section the following configurations can be placed:
|
||||
|
||||
- `ROOT_PATH`: (Default: **%(GITEA_WORK_DIR)/log**): Base path for log files
|
||||
- `MODE`: (Default: **console**) List of log outputs to use for the Default logger.
|
||||
- `LEVEL`: (Default: **Info**) Least severe log events to persist, case-insensitive. Possible values are: `Trace`, `Debug`, `Info`, `Warn`, `Error`, `Fatal`.
|
||||
- `STACKTRACE_LEVEL`: (Default: **None**) For this and more severe events the stacktrace will be printed upon getting logged.
|
||||
|
||||
And it can contain the following sub-loggers:
|
||||
|
||||
- `logger.router.MODE`: (Default: **,**): List of log outputs to use for the Router logger.
|
||||
- `logger.access.MODE`: (Default: **_empty_**) List of log outputs to use for the Access logger. By default, the access logger is disabled.
|
||||
- `logger.xorm.MODE`: (Default: **,**) List of log outputs to use for the XORM logger.
|
||||
|
||||
Setting a comma (`,`) to sub-logger's mode means making it use the default global `MODE`.
|
||||
|
||||
## Quick samples
|
||||
|
||||
### Default (empty) Configuration
|
||||
|
||||
The empty configuration is equivalent to default:
|
||||
|
||||
```ini
|
||||
[log]
|
||||
ROOT_PATH = %(GITEA_WORK_DIR)/log
|
||||
MODE = console
|
||||
LEVEL = Info
|
||||
STACKTRACE_LEVEL = None
|
||||
logger.router.MODE = ,
|
||||
logger.xorm.MODE = ,
|
||||
logger.access.MODE =
|
||||
|
||||
; this is the config options of "console" mode (used by MODE=console above)
|
||||
[log.console]
|
||||
MODE = console
|
||||
FLAGS = stdflags
|
||||
PREFIX =
|
||||
COLORIZE = true
|
||||
```
|
||||
|
||||
This is equivalent to sending all logs to the console, with default Golang log being sent to the console log too.
|
||||
|
||||
This is only a sample, and it is the default, do not need to write it into your configuration file.
|
||||
|
||||
### Disable Router logs and record some access logs to file
|
||||
|
||||
The Router logger is disabled, the access logs (>=Warn) goes into `access.log`:
|
||||
|
||||
```ini
|
||||
[log]
|
||||
logger.router.MODE =
|
||||
logger.access.MODE = access-file
|
||||
|
||||
[log.access-file]
|
||||
MODE = file
|
||||
LEVEL = Warn
|
||||
FILE_NAME = access.log
|
||||
```
|
||||
|
||||
### Set different log levels for different modes
|
||||
|
||||
Default logs (>=Warn) goes into `gitea.log`, while Error logs goes into `file-error.log`:
|
||||
|
||||
```ini
|
||||
[log]
|
||||
LEVEL = Warn
|
||||
MODE = file, file-error
|
||||
|
||||
; by default, the "file" mode will record logs to %(log.ROOT_PATH)/gitea.log, so we don't need to set it
|
||||
; [log.file]
|
||||
|
||||
[log.file-error]
|
||||
LEVEL = Error
|
||||
FILE_NAME = file-error.log
|
||||
```
|
||||
|
||||
## Log outputs (mode and writer)
|
||||
|
||||
Gitea provides the following log output writers:
|
||||
|
||||
- `console` - Log to `stdout` (or `stderr` if it is set in the config)
|
||||
- `file` - Log to a file
|
||||
- `conn` - Log to a socket (network or unix)
|
||||
|
||||
### Common configuration
|
||||
|
||||
Certain configuration is common to all modes of log output:
|
||||
|
||||
- `MODE` is the mode of the log output writer. It will default to the mode name in the ini section. Thus `[log.console]` will default to `MODE = console`.
|
||||
- `LEVEL` is the lowest level that this output will log.
|
||||
- `STACKTRACE_LEVEL` is the lowest level that this output will print a stacktrace.
|
||||
- `COLORIZE` will default to `true` for `console` as described, otherwise it will default to `false`.
|
||||
|
||||
#### `EXPRESSION`
|
||||
|
||||
`EXPRESSION` represents a regular expression that log events must match to be logged by the output writer.
|
||||
Either the log message, (with colors removed), must match or the `longfilename:linenumber:functionname` must match.
|
||||
NB: the whole message or string doesn't need to completely match.
|
||||
|
||||
Please note this expression will be run in the writer's goroutine but not the logging event goroutine.
|
||||
|
||||
#### `FLAGS`
|
||||
|
||||
`FLAGS` represents the preceding logging context information that is
|
||||
printed before each message. It is a comma-separated string set. The order of values does not matter.
|
||||
|
||||
It defaults to `stdflags` (= `date,time,medfile,shortfuncname,levelinitial`)
|
||||
|
||||
Possible values are:
|
||||
|
||||
- `none` or `,` - No flags.
|
||||
- `date` - the date in the local time zone: `2009/01/23`.
|
||||
- `time` - the time in the local time zone: `01:23:23`.
|
||||
- `microseconds` - microsecond resolution: `01:23:23.123123`. Assumes time.
|
||||
- `longfile` - full file name and line number: `/a/b/c/d.go:23`.
|
||||
- `shortfile` - final file name element and line number: `d.go:23`.
|
||||
- `funcname` - function name of the caller: `runtime.Caller()`.
|
||||
- `shortfuncname` - last part of the function name. Overrides `funcname`.
|
||||
- `utc` - if date or time is set, use UTC rather than the local time zone.
|
||||
- `levelinitial` - initial character of the provided level in brackets eg. `[I]` for info.
|
||||
- `level` - level in brackets `[INFO]`.
|
||||
- `gopid` - the Goroutine-PID of the context.
|
||||
- `medfile` - last 20 characters of the filename - equivalent to `shortfile,longfile`.
|
||||
- `stdflags` - equivalent to `date,time,medfile,shortfuncname,levelinitial`.
|
||||
|
||||
### Console mode
|
||||
|
||||
In this mode the logger will forward log messages to the stdout and
|
||||
stderr streams attached to the Gitea process.
|
||||
|
||||
For loggers in console mode, `COLORIZE` will default to `true` if not
|
||||
on windows, or the Windows terminal can be set into ANSI mode or is a
|
||||
cygwin or Msys pipe.
|
||||
|
||||
Settings:
|
||||
|
||||
- `STDERR`: **false**: Whether the logger should print to `stderr` instead of `stdout`.
|
||||
|
||||
### File mode
|
||||
|
||||
In this mode the logger will save log messages to a file.
|
||||
|
||||
Settings:
|
||||
|
||||
- `FILE_NAME`: The file to write the log events to, relative to `ROOT_PATH`, Default to `%(ROOT_PATH)/gitea.log`. Exception: access log will default to `%(ROOT_PATH)/access.log`.
|
||||
- `MAX_SIZE_SHIFT`: **28**: Maximum size shift of a single file. 28 represents 256Mb. For details see below.
|
||||
- `LOG_ROTATE` **true**: Whether to rotate the log files. TODO: if false, will it delete instead on daily rotate, or do nothing?.
|
||||
- `DAILY_ROTATE`: **true**: Whether to rotate logs daily.
|
||||
- `MAX_DAYS`: **7**: Delete rotated log files after this number of days.
|
||||
- `COMPRESS`: **true**: Whether to compress old log files by default with gzip.
|
||||
- `COMPRESSION_LEVEL`: **-1**: Compression level. For details see below.
|
||||
|
||||
`MAX_SIZE_SHIFT` defines the maximum size of a file by left shifting 1 the given number of times (`1 << x`).
|
||||
The exact behavior at the time of v1.17.3 can be seen [here](https://github.com/go-gitea/gitea/blob/v1.17.3/modules/setting/log.go#L185).
|
||||
|
||||
The useful values of `COMPRESSION_LEVEL` are from 1 to (and including) 9, where higher numbers mean better compression.
|
||||
Beware that better compression might come with higher resource usage.
|
||||
Must be preceded with a `-` sign.
|
||||
|
||||
### Conn mode
|
||||
|
||||
In this mode the logger will send log messages over a network socket.
|
||||
|
||||
Settings:
|
||||
|
||||
- `ADDR`: **:7020**: Sets the address to connect to.
|
||||
- `PROTOCOL`: **tcp**: Set the protocol, either "tcp", "unix" or "udp".
|
||||
- `RECONNECT`: **false**: Try to reconnect when connection is lost.
|
||||
- `RECONNECT_ON_MSG`: **false**: Reconnect host for every single message.
|
||||
|
||||
### The "Router" logger
|
||||
|
||||
The Router logger logs the following message types when Gitea's route handlers work:
|
||||
|
||||
- `started` messages will be logged at TRACE level
|
||||
- `polling`/`completed` routers will be logged at INFO. Exception: "/assets" static resource requests are also logged at TRACE.
|
||||
- `slow` routers will be logged at WARN
|
||||
- `failed` routers will be logged at WARN
|
||||
|
||||
### The "XORM" logger
|
||||
|
||||
To make XORM outputs SQL logs, the `LOG_SQL` in `[database]` section should also be set to `true`.
|
||||
|
||||
### The "Access" logger
|
||||
|
||||
The Access logger is a new logger since Gitea 1.9. It provides a NCSA
|
||||
Common Log compliant log format. It's highly configurable but caution
|
||||
should be taken when changing its template. The main benefit of this
|
||||
logger is that Gitea can now log accesses in a standard log format so
|
||||
standard tools may be used.
|
||||
|
||||
You can enable this logger using `logger.access.MODE = ...`.
|
||||
|
||||
If desired the format of the Access logger can be changed by changing
|
||||
the value of the `ACCESS_LOG_TEMPLATE`.
|
||||
|
||||
Please note, the access logger will log at `INFO` level, setting the
|
||||
`LEVEL` of this logger to `WARN` or above will result in no access logs.
|
||||
|
||||
#### The ACCESS_LOG_TEMPLATE
|
||||
|
||||
This value represents a go template. Its default value is
|
||||
|
||||
```tmpl
|
||||
{{.Ctx.RemoteHost}} - {{.Identity}} {{.Start.Format "[02/Jan/2006:15:04:05 -0700]" }} "{{.Ctx.Req.Method}} {{.Ctx.Req.URL.RequestURI}} {{.Ctx.Req.Proto}}" {{.ResponseWriter.Status}} {{.ResponseWriter.Size}} "{{.Ctx.Req.Referer}}" "{{.Ctx.Req.UserAgent}}"`
|
||||
```
|
||||
|
||||
The template is passed following options:
|
||||
|
||||
- `Ctx` is the `context.Context`
|
||||
- `Identity` is the `SignedUserName` or `"-"` if the user is not logged in
|
||||
- `Start` is the start time of the request
|
||||
- `ResponseWriter` is the `http.ResponseWriter`
|
||||
|
||||
Caution must be taken when changing this template as it runs outside of
|
||||
the standard panic recovery trap. The template should also be as simple
|
||||
as it runs for every request.
|
||||
|
||||
## Releasing-and-Reopening, Pausing and Resuming logging
|
||||
|
||||
If you are running on Unix you may wish to release-and-reopen logs in order to use `logrotate` or other tools.
|
||||
It is possible force Gitea to release and reopen it's logging files and connections by sending `SIGUSR1` to the
|
||||
running process, or running `gitea manager logging release-and-reopen`.
|
||||
|
||||
Alternatively, you may wish to pause and resume logging - this can be accomplished through the use of the
|
||||
`gitea manager logging pause` and `gitea manager logging resume` commands. Please note that whilst logging
|
||||
is paused log events below INFO level will not be stored and only a limited number of events will be stored.
|
||||
Logging may block, albeit temporarily, slowing Gitea considerably whilst paused - therefore it is
|
||||
recommended that pausing only done for a very short period of time.
|
||||
|
||||
## Adding and removing logging whilst Gitea is running
|
||||
|
||||
It is possible to add and remove logging whilst Gitea is running using the `gitea manager logging add` and `remove` subcommands.
|
||||
This functionality can only adjust running log systems and cannot be used to start the access or router loggers if they
|
||||
were not already initialized. If you wish to start these systems you are advised to adjust the app.ini and (gracefully) restart
|
||||
the Gitea service.
|
||||
|
||||
The main intention of these commands is to easily add a temporary logger to investigate problems on running systems where a restart
|
||||
may cause the issue to disappear.
|
||||
|
||||
## Using `logrotate` instead of built-in log rotation
|
||||
|
||||
Gitea includes built-in log rotation, which should be enough for most deployments. However, if you instead want to use the `logrotate` utility:
|
||||
|
||||
- Disable built-in log rotation by setting `LOG_ROTATE` to `false` in your `app.ini`.
|
||||
- Install `logrotate`.
|
||||
- Configure `logrotate` to match your deployment requirements, see `man 8 logrotate` for configuration syntax details.
|
||||
In the `postrotate/endscript` block send Gitea a `USR1` signal via `kill -USR1` or `kill -10` to the `gitea` process itself,
|
||||
or run `gitea manager logging release-and-reopen` (with the appropriate environment).
|
||||
Ensure that your configurations apply to all files emitted by Gitea loggers as described in the above sections.
|
||||
- Always do `logrotate /etc/logrotate.conf --debug` to test your configurations.
|
||||
- If you are using docker and are running from outside the container you can use
|
||||
`docker exec -u $OS_USER $CONTAINER_NAME sh -c 'gitea manager logging release-and-reopen'`
|
||||
or `docker exec $CONTAINER_NAME sh -c '/bin/s6-svc -1 /etc/s6/gitea/'` or send `USR1` directly to the Gitea process itself.
|
||||
|
||||
The next `logrotate` jobs will include your configurations, so no restart is needed.
|
||||
You can also immediately reload `logrotate` with `logrotate /etc/logrotate.conf --force`.
|
||||
@@ -0,0 +1,518 @@
|
||||
---
|
||||
date: "2019-04-02T17:06:00+01:00"
|
||||
title: "Logging Configuration"
|
||||
slug: "logging-configuration"
|
||||
sidebar_position: 40
|
||||
toc: false
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
name: "Logging Configuration"
|
||||
sidebar_position: 40
|
||||
identifier: "logging-configuration"
|
||||
---
|
||||
|
||||
# Logging Configuration
|
||||
|
||||
The logging configuration of Gitea mainly consists of 3 types of components:
|
||||
|
||||
- The `[log]` section for general configuration
|
||||
- `[log.<sublogger>]` sections for the configuration of different log outputs
|
||||
- `[log.<sublogger>.<group>]` sections for output specific configuration of a log group
|
||||
|
||||
As mentioned below, there is a fully functional log output by default, so it is not necessary to define one.
|
||||
|
||||
## Collecting Logs for Help
|
||||
|
||||
To collect logs for help and issue report, see [Support Options](help/seek-help.md).
|
||||
|
||||
## The `[log]` section
|
||||
|
||||
Configuration of logging facilities in Gitea happen in the `[log]` section and it's subsections.
|
||||
|
||||
In the top level `[log]` section the following configurations can be placed:
|
||||
|
||||
- `ROOT_PATH`: (Default: **%(GITEA_WORK_DIR)/log**): Base path for log files
|
||||
- `MODE`: (Default: **console**) List of log outputs to use for the Default logger.
|
||||
- `ROUTER`: (Default: **console**): List of log outputs to use for the Router logger.
|
||||
- `ACCESS`: List of log outputs to use for the Access logger.
|
||||
- `XORM`: (Default: **,**) List of log outputs to use for the XORM logger.
|
||||
- `ENABLE_ACCESS_LOG`: (Default: **false**): whether the Access logger is allowed to emit logs
|
||||
- `ENABLE_XORM_LOG`: (Default: **true**): whether the XORM logger is allowed to emit logs
|
||||
|
||||
For details on the loggers check the "Log Groups" section.
|
||||
Important: log outputs won't be used if you don't enable them for the desired loggers in the corresponding list value.
|
||||
|
||||
Lists are specified as comma separated values. This format also works in subsection.
|
||||
|
||||
This section may be used for defining default values for subsections.
|
||||
Examples:
|
||||
|
||||
- `LEVEL`: (Default: **Info**) Least severe log events to persist. Case insensitive. The full list of levels as of v1.17.3 can be read [here](https://github.com/go-gitea/gitea/blob/v1.17.3/custom/conf/app.example.ini#L507).
|
||||
- `STACKTRACE_LEVEL`: (Default: **None**) For this and more severe events the stacktrace will be printed upon getting logged.
|
||||
|
||||
Some values are not inherited by subsections. For details see the "Non-inherited default values" section.
|
||||
|
||||
## Log outputs
|
||||
|
||||
Log outputs are the targets to which log messages will be sent.
|
||||
The content and the format of the log messages to be saved can be configured in these.
|
||||
|
||||
Log outputs are also called subloggers.
|
||||
|
||||
Gitea provides 4 possible log outputs:
|
||||
|
||||
- `console` - Log to `os.Stdout` or `os.Stderr`
|
||||
- `file` - Log to a file
|
||||
- `conn` - Log to a socket (network or unix)
|
||||
- `smtp` - Log via email
|
||||
|
||||
By default, Gitea has a `console` output configured, which is used by the loggers as seen in the section "The log section" above.
|
||||
|
||||
### Common configuration
|
||||
|
||||
Certain configuration is common to all modes of log output:
|
||||
|
||||
- `MODE` is the mode of the log output. It will default to the sublogger
|
||||
name, thus `[log.console.router]` will default to `MODE = console`.
|
||||
For mode specific confgurations read further.
|
||||
- `LEVEL` is the lowest level that this output will log. This value
|
||||
is inherited from `[log]` and in the case of the non-default loggers
|
||||
from `[log.sublogger]`.
|
||||
- `STACKTRACE_LEVEL` is the lowest level that this output will print
|
||||
a stacktrace. This value is inherited.
|
||||
- `COLORIZE` will default to `true` for `console` as
|
||||
described, otherwise it will default to `false`.
|
||||
|
||||
### Non-inherited default values
|
||||
|
||||
There are several values which are not inherited as described above but
|
||||
rather default to those specific to type of logger, these are:
|
||||
`EXPRESSION`, `FLAGS`, `PREFIX` and `FILE_NAME`.
|
||||
|
||||
#### `EXPRESSION`
|
||||
|
||||
`EXPRESSION` represents a regular expression that log events must match to be logged by the sublogger. Either the log message, (with colors removed), must match or the `longfilename:linenumber:functionname` must match. NB: the whole message or string doesn't need to completely match.
|
||||
|
||||
Please note this expression will be run in the sublogger's goroutine
|
||||
not the logging event subroutine. Therefore it can be complicated.
|
||||
|
||||
#### `FLAGS`
|
||||
|
||||
`FLAGS` represents the preceding logging context information that is
|
||||
printed before each message. It is a comma-separated string set. The order of values does not matter.
|
||||
|
||||
Possible values are:
|
||||
|
||||
- `none` or `,` - No flags.
|
||||
- `date` - the date in the local time zone: `2009/01/23`.
|
||||
- `time` - the time in the local time zone: `01:23:23`.
|
||||
- `microseconds` - microsecond resolution: `01:23:23.123123`. Assumes
|
||||
time.
|
||||
- `longfile` - full file name and line number: `/a/b/c/d.go:23`.
|
||||
- `shortfile` - final file name element and line number: `d.go:23`.
|
||||
- `funcname` - function name of the caller: `runtime.Caller()`.
|
||||
- `shortfuncname` - last part of the function name. Overrides
|
||||
`funcname`.
|
||||
- `utc` - if date or time is set, use UTC rather than the local time
|
||||
zone.
|
||||
- `levelinitial` - Initial character of the provided level in brackets eg. `[I]` for info.
|
||||
- `level` - Provided level in brackets `[INFO]`
|
||||
- `medfile` - Last 20 characters of the filename - equivalent to
|
||||
`shortfile,longfile`.
|
||||
- `stdflags` - Equivalent to `date,time,medfile,shortfuncname,levelinitial`
|
||||
|
||||
### Console mode
|
||||
|
||||
In this mode the logger will forward log messages to the stdout and
|
||||
stderr streams attached to the Gitea process.
|
||||
|
||||
For loggers in console mode, `COLORIZE` will default to `true` if not
|
||||
on windows, or the windows terminal can be set into ANSI mode or is a
|
||||
cygwin or Msys pipe.
|
||||
|
||||
Settings:
|
||||
|
||||
- `STDERR`: **false**: Whether the logger should print to `stderr` instead of `stdout`.
|
||||
|
||||
### File mode
|
||||
|
||||
In this mode the logger will save log messages to a file.
|
||||
|
||||
Settings:
|
||||
|
||||
- `FILE_NAME`: The file to write the log events to. For details see below.
|
||||
- `MAX_SIZE_SHIFT`: **28**: Maximum size shift of a single file. 28 represents 256Mb. For details see below.
|
||||
- `LOG_ROTATE` **true**: Whether to rotate the log files. TODO: if false, will it delete instead on daily rotate, or do nothing?.
|
||||
- `DAILY_ROTATE`: **true**: Whether to rotate logs daily.
|
||||
- `MAX_DAYS`: **7**: Delete rotated log files after this number of days.
|
||||
- `COMPRESS`: **true**: Whether to compress old log files by default with gzip.
|
||||
- `COMPRESSION_LEVEL`: **-1**: Compression level. For details see below.
|
||||
|
||||
The default value of `FILE_NAME` depends on the respective logger facility.
|
||||
If unset, their own default will be used.
|
||||
If set it will be relative to the provided `ROOT_PATH` in the master `[log]` section.
|
||||
|
||||
`MAX_SIZE_SHIFT` defines the maximum size of a file by left shifting 1 the given number of times (`1 << x`).
|
||||
The exact behavior at the time of v1.17.3 can be seen [here](https://github.com/go-gitea/gitea/blob/v1.17.3/modules/setting/log.go#L185).
|
||||
|
||||
The useful values of `COMPRESSION_LEVEL` are from 1 to (and including) 9, where higher numbers mean better compression.
|
||||
Beware that better compression might come with higher resource usage.
|
||||
Must be preceded with a `-` sign.
|
||||
|
||||
### Conn mode
|
||||
|
||||
In this mode the logger will send log messages over a network socket.
|
||||
|
||||
Settings:
|
||||
|
||||
- `ADDR`: **:7020**: Sets the address to connect to.
|
||||
- `PROTOCOL`: **tcp**: Set the protocol, either "tcp", "unix" or "udp".
|
||||
- `RECONNECT`: **false**: Try to reconnect when connection is lost.
|
||||
- `RECONNECT_ON_MSG`: **false**: Reconnect host for every single message.
|
||||
|
||||
### SMTP mode
|
||||
|
||||
In this mode the logger will send log messages in email.
|
||||
|
||||
It is not recommended to use this logger to send general logging
|
||||
messages. However, you could perhaps set this logger to work on `FATAL` messages only.
|
||||
|
||||
Settings:
|
||||
|
||||
- `HOST`: **127.0.0.1:25**: The SMTP host to connect to.
|
||||
- `USER`: User email address to send from.
|
||||
- `PASSWD`: Password for the smtp server.
|
||||
- `RECEIVERS`: Email addresses to send to.
|
||||
- `SUBJECT`: **Diagnostic message from Gitea**. The content of the email's subject field.
|
||||
|
||||
## Log Groups
|
||||
|
||||
The fundamental thing to be aware of in Gitea is that there are several
|
||||
log groups:
|
||||
|
||||
- The "Default" logger
|
||||
- The Router logger
|
||||
- The Access logger
|
||||
- The XORM logger
|
||||
|
||||
There is also the go log logger.
|
||||
|
||||
### The go log logger
|
||||
|
||||
Go provides its own extremely basic logger in the `log` package,
|
||||
however, this is not sufficient for our purposes as it does not provide
|
||||
a way of logging at multiple levels, nor does it provide a good way of
|
||||
controlling where these logs are logged except through setting of a
|
||||
writer.
|
||||
|
||||
We have therefore redirected this logger to our Default logger, and we
|
||||
will log anything that is logged using the go logger at the INFO level.
|
||||
|
||||
### The "Default" logger
|
||||
|
||||
Calls to `log.Info`, `log.Debug`, `log.Error` etc. from the `code.gitea.io/gitea/modules/log` package will log to this logger.
|
||||
|
||||
You can configure the outputs of this logger by setting the `MODE`
|
||||
value in the `[log]` section of the configuration.
|
||||
|
||||
Each output sublogger is configured in a separate `[log.sublogger.default]`
|
||||
which inherits from the sublogger `[log.sublogger]` section and from the
|
||||
generic `[log]` section, but there are certain default values. These will
|
||||
not be inherited from the `[log]` section:
|
||||
|
||||
- `FLAGS` is `stdflags` (Equal to
|
||||
`date,time,medfile,shortfuncname,levelinitial`)
|
||||
- `FILE_NAME` will default to `%(ROOT_PATH)/gitea.log`
|
||||
- `EXPRESSION` will default to `""`
|
||||
- `PREFIX` will default to `""`
|
||||
|
||||
The provider type of the sublogger can be set using the `MODE` value in
|
||||
its subsection, but will default to the name. This allows you to have
|
||||
multiple subloggers that will log to files.
|
||||
|
||||
### The "Router" logger
|
||||
|
||||
The Router logger has been substantially changed in v1.17. If you are using the router logger for fail2ban or other monitoring
|
||||
you will need to update this configuration.
|
||||
|
||||
You can disable Router log by setting `DISABLE_ROUTER_LOG` or by setting all of its sublogger configurations to `none`.
|
||||
|
||||
You can configure the outputs of this
|
||||
router log by setting the `ROUTER` value in the `[log]` section of the
|
||||
configuration. `ROUTER` will default to `console` if unset and will default to same level as main logger.
|
||||
|
||||
The Router logger logs the following:
|
||||
|
||||
- `started` messages will be logged at TRACE level
|
||||
- `polling`/`completed` routers will be logged at INFO
|
||||
- `slow` routers will be logged at WARN
|
||||
- `failed` routers will be logged at WARN
|
||||
|
||||
The logging level for the router will default to that of the main configuration. Set `[log.<mode>.router]` `LEVEL` to change this.
|
||||
|
||||
Each output sublogger for this logger is configured in
|
||||
`[log.sublogger.router]` sections. There are certain default values
|
||||
which will not be inherited from the `[log]` or relevant
|
||||
`[log.sublogger]` sections:
|
||||
|
||||
- `FILE_NAME` will default to `%(ROOT_PATH)/router.log`
|
||||
- `FLAGS` defaults to `date,time`
|
||||
- `EXPRESSION` will default to `""`
|
||||
- `PREFIX` will default to `""`
|
||||
|
||||
NB: You can redirect the router logger to send its events to the Gitea
|
||||
log using the value: `ROUTER = ,`
|
||||
|
||||
### The "Access" logger
|
||||
|
||||
The Access logger is a new logger for version 1.9. It provides a NCSA
|
||||
Common Log compliant log format. It's highly configurable but caution
|
||||
should be taken when changing its template. The main benefit of this
|
||||
logger is that Gitea can now log accesses in a standard log format so
|
||||
standard tools may be used.
|
||||
|
||||
You can enable this logger using `ENABLE_ACCESS_LOG`. Its outputs are
|
||||
configured by setting the `ACCESS` value in the `[log]` section of the
|
||||
configuration. `ACCESS` defaults to `file` if unset.
|
||||
|
||||
Each output sublogger for this logger is configured in
|
||||
`[log.sublogger.access]` sections. There are certain default values
|
||||
which will not be inherited from the `[log]` or relevant
|
||||
`[log.sublogger]` sections:
|
||||
|
||||
- `FILE_NAME` will default to `%(ROOT_PATH)/access.log`
|
||||
- `FLAGS` defaults to `` or None
|
||||
- `EXPRESSION` will default to `""`
|
||||
- `PREFIX` will default to `""`
|
||||
|
||||
If desired the format of the Access logger can be changed by changing
|
||||
the value of the `ACCESS_LOG_TEMPLATE`.
|
||||
|
||||
Please note, the access logger will log at `INFO` level, setting the
|
||||
`LEVEL` of this logger to `WARN` or above will result in no access logs.
|
||||
|
||||
NB: You can redirect the access logger to send its events to the Gitea
|
||||
log using the value: `ACCESS = ,`
|
||||
|
||||
#### The ACCESS_LOG_TEMPLATE
|
||||
|
||||
This value represent a go template. It's default value is:
|
||||
|
||||
`{{.Ctx.RemoteAddr}} - {{.Identity}} {{.Start.Format "[02/Jan/2006:15:04:05 -0700]" }} "{{.Ctx.Req.Method}} {{.Ctx.Req.URL.RequestURI}} {{.Ctx.Req.Proto}}" {{.ResponseWriter.Status}} {{.ResponseWriter.Size}} "{{.Ctx.Req.Referer}}\" \"{{.Ctx.Req.UserAgent}}"`
|
||||
|
||||
The template is passed following options:
|
||||
|
||||
- `Ctx` is the `context.Context`
|
||||
- `Identity` is the `SignedUserName` or `"-"` if the user is not logged
|
||||
in
|
||||
- `Start` is the start time of the request
|
||||
- `ResponseWriter` is the `http.ResponseWriter`
|
||||
|
||||
Caution must be taken when changing this template as it runs outside of
|
||||
the standard panic recovery trap. The template should also be as simple
|
||||
as it runs for every request.
|
||||
|
||||
### The "XORM" logger
|
||||
|
||||
The XORM logger is a long-standing logger that exists to collect XORM
|
||||
log events. It is enabled by default but can be switched off by setting
|
||||
`ENABLE_XORM_LOG` to `false` in the `[log]` section. Its outputs are
|
||||
configured by setting the `XORM` value in the `[log]` section of the
|
||||
configuration. `XORM` defaults to `,` if unset, meaning it is redirected
|
||||
to the main Gitea log.
|
||||
|
||||
XORM will log SQL events by default. This can be changed by setting
|
||||
the `LOG_SQL` value to `false` in the `[database]` section.
|
||||
|
||||
Each output sublogger for this logger is configured in
|
||||
`[log.sublogger.xorm]` sections. There are certain default values
|
||||
which will not be inherited from the `[log]` or relevant
|
||||
`[log.sublogger]` sections:
|
||||
|
||||
- `FILE_NAME` will default to `%(ROOT_PATH)/xorm.log`
|
||||
- `FLAGS` defaults to `date,time`
|
||||
- `EXPRESSION` will default to `""`
|
||||
- `PREFIX` will default to `""`
|
||||
|
||||
## Debugging problems
|
||||
|
||||
When submitting logs in Gitea issues it is often helpful to submit
|
||||
merged logs obtained by either by redirecting the console log to a file or
|
||||
copying and pasting it. To that end it is recommended to set your logging to:
|
||||
|
||||
```ini
|
||||
[database]
|
||||
LOG_SQL = false ; SQL logs are rarely helpful unless we specifically ask for them
|
||||
|
||||
...
|
||||
|
||||
[log]
|
||||
MODE = console
|
||||
LEVEL = debug ; please set the level to debug when we are debugging a problem
|
||||
ROUTER = console
|
||||
COLORIZE = false ; this can be true if you can strip out the ansi coloring
|
||||
ENABLE_SSH_LOG = true ; shows logs related to git over SSH.
|
||||
```
|
||||
|
||||
Sometimes it will be helpful get some specific `TRACE` level logging restricted
|
||||
to messages that match a specific `EXPRESSION`. Adjusting the `MODE` in the
|
||||
`[log]` section to `MODE = console,traceconsole` to add a new logger output
|
||||
`traceconsole` and then adding its corresponding section would be helpful:
|
||||
|
||||
```ini
|
||||
[log.traceconsole] ; traceconsole here is just a name
|
||||
MODE = console ; this is the output that the traceconsole writes to
|
||||
LEVEL = trace
|
||||
EXPRESSION = ; putting a string here will restrict this logger to logging only those messages that match this expression
|
||||
```
|
||||
|
||||
(It's worth noting that log messages that match the expression at or above debug
|
||||
level will get logged twice so don't worry about that.)
|
||||
|
||||
`STACKTRACE_LEVEL` should generally be left unconfigured (and hence kept at
|
||||
`none`). There are only very specific occasions when it useful.
|
||||
|
||||
## Empty Configuration
|
||||
|
||||
The empty configuration is equivalent to:
|
||||
|
||||
```ini
|
||||
[log]
|
||||
ROOT_PATH = %(GITEA_WORK_DIR)/log
|
||||
MODE = console
|
||||
LEVEL = Info
|
||||
STACKTRACE_LEVEL = None
|
||||
ENABLE_ACCESS_LOG = false
|
||||
ENABLE_XORM_LOG = true
|
||||
XORM = ,
|
||||
|
||||
[log.console]
|
||||
MODE = console
|
||||
LEVEL = %(LEVEL)
|
||||
STACKTRACE_LEVEL = %(STACKTRACE_LEVEL)
|
||||
FLAGS = stdflags
|
||||
PREFIX =
|
||||
COLORIZE = true # Or false if your windows terminal cannot color
|
||||
```
|
||||
|
||||
This is equivalent to sending all logs to the console, with default go log being sent to the console log too.
|
||||
|
||||
## Releasing-and-Reopening, Pausing and Resuming logging
|
||||
|
||||
If you are running on Unix you may wish to release-and-reopen logs in order to use `logrotate` or other tools.
|
||||
It is possible force Gitea to release and reopen it's logging files and connections by sending `SIGUSR1` to the
|
||||
running process, or running `gitea manager logging release-and-reopen`.
|
||||
|
||||
Alternatively, you may wish to pause and resume logging - this can be accomplished through the use of the
|
||||
`gitea manager logging pause` and `gitea manager logging resume` commands. Please note that whilst logging
|
||||
is paused log events below INFO level will not be stored and only a limited number of events will be stored.
|
||||
Logging may block, albeit temporarily, slowing Gitea considerably whilst paused - therefore it is
|
||||
recommended that pausing only done for a very short period of time.
|
||||
|
||||
## Adding and removing logging whilst Gitea is running
|
||||
|
||||
It is possible to add and remove logging whilst Gitea is running using the `gitea manager logging add` and `remove` subcommands.
|
||||
This functionality can only adjust running log systems and cannot be used to start the access or router loggers if they
|
||||
were not already initialized. If you wish to start these systems you are advised to adjust the app.ini and (gracefully) restart
|
||||
the Gitea service.
|
||||
|
||||
The main intention of these commands is to easily add a temporary logger to investigate problems on running systems where a restart
|
||||
may cause the issue to disappear.
|
||||
|
||||
## Log colorization
|
||||
|
||||
Logs to the console will be colorized by default when not running on
|
||||
Windows. Terminal sniffing will occur on Windows and if it is
|
||||
determined that we are running on a terminal capable of color we will
|
||||
colorize.
|
||||
|
||||
Further, on \*nix it is becoming common to have file logs that are
|
||||
colored by default. Therefore file logs will be colorised by default
|
||||
when not running on Windows.
|
||||
|
||||
You can switch on or off colorization by using the `COLORIZE` value.
|
||||
|
||||
From a development point of view. If you write
|
||||
`log.Info("A %s string", "formatted")` the `formatted` part of the log
|
||||
message will be Bolded on colorized logs.
|
||||
|
||||
You can change this by either rendering the formatted string yourself.
|
||||
Or you can wrap the value in a `log.ColoredValue` struct.
|
||||
|
||||
The `log.ColoredValue` struct contains a pointer to value, a pointer to
|
||||
string of bytes which should represent a color and second set of reset
|
||||
bytes. Pointers were chosen to prevent copying of large numbers of
|
||||
values. There are several helper methods:
|
||||
|
||||
- `log.NewColoredValue` takes a value and 0 or more color attributes
|
||||
that represent the color. If 0 are provided it will default to a cached
|
||||
bold. Note, it is recommended that color bytes constructed from
|
||||
attributes should be cached if this is a commonly used log message.
|
||||
- `log.NewColoredValuePointer` takes a pointer to a value, and
|
||||
0 or more color attributes that represent the color.
|
||||
- `log.NewColoredValueBytes` takes a value and a pointer to an array
|
||||
of bytes representing the color.
|
||||
|
||||
These functions will not double wrap a `log.ColoredValue`. They will
|
||||
also set the `resetBytes` to the cached `resetBytes`.
|
||||
|
||||
The `colorBytes` and `resetBytes` are not exported to prevent
|
||||
accidental overwriting of internal values.
|
||||
|
||||
## ColorFormat & ColorFormatted
|
||||
|
||||
Structs may implement the `log.ColorFormatted` interface by implementing the `ColorFormat(fmt.State)` function.
|
||||
|
||||
If a `log.ColorFormatted` struct is logged with `%-v` format, its `ColorFormat` will be used instead of the usual `%v`. The full `fmt.State` will be passed to allow implementers to look at additional flags.
|
||||
|
||||
In order to help implementers provide `ColorFormat` methods. There is a
|
||||
`log.ColorFprintf(...)` function in the log module that will wrap values in `log.ColoredValue` and recognise `%-v`.
|
||||
|
||||
In general it is recommended not to make the results of this function too verbose to help increase its versatility. Usually this should simply be an `ID`:`Name`. If you wish to make a more verbose result, it is recommended to use `%-+v` as your marker.
|
||||
|
||||
## Log Spoofing protection
|
||||
|
||||
In order to protect the logs from being spoofed with cleverly
|
||||
constructed messages. Newlines are now prefixed with a tab and control
|
||||
characters except those used in an ANSI CSI are escaped with a
|
||||
preceding `\` and their octal value.
|
||||
|
||||
## Creating a new named logger group
|
||||
|
||||
Should a developer wish to create a new named logger, `NEWONE`. It is
|
||||
recommended to add an `ENABLE_NEWONE_LOG` value to the `[log]`
|
||||
section, and to add a new `NEWONE` value for the modes.
|
||||
|
||||
A function like `func newNewOneLogService()` is recommended to manage
|
||||
construction of the named logger. e.g.
|
||||
|
||||
```go
|
||||
func newNewoneLogService() {
|
||||
EnableNewoneLog = Cfg.Section("log").Key("ENABLE_NEWONE_LOG").MustBool(false)
|
||||
Cfg.Section("log").Key("NEWONE").MustString("file") // or console? or "," if you want to send this to default logger by default
|
||||
if EnableNewoneLog {
|
||||
options := newDefaultLogOptions()
|
||||
options.filename = filepath.Join(LogRootPath, "newone.log")
|
||||
options.flags = "stdflags"
|
||||
options.bufferLength = Cfg.Section("log").Key("BUFFER_LEN").MustInt64(10000)
|
||||
generateNamedLogger("newone", options)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You should then add `newOneLogService` to `NewServices()` in
|
||||
`modules/setting/setting.go`
|
||||
|
||||
## Using `logrotate` instead of built-in log rotation
|
||||
|
||||
Gitea includes built-in log rotation, which should be enough for most deployments. However, if you instead want to use the `logrotate` utility:
|
||||
|
||||
- Disable built-in log rotation by setting `LOG_ROTATE` to `false` in your `app.ini`.
|
||||
- Install `logrotate`.
|
||||
- Configure `logrotate` to match your deployment requirements, see `man 8 logrotate` for configuration syntax details. In the `postrotate/endscript` block send Gitea a `USR1` signal via `kill -USR1` or `kill -10` to the `gitea` process itself, or run `gitea manager logging release-and-reopen` (with the appropriate environment). Ensure that your configurations apply to all files emitted by Gitea loggers as described in the above sections.
|
||||
- Always do `logrotate /etc/logrotate.conf --debug` to test your configurations.
|
||||
- If you are using docker and are running from outside of the container you can use `docker exec -u $OS_USER $CONTAINER_NAME sh -c 'gitea manager logging release-and-reopen'` or `docker exec $CONTAINER_NAME sh -c '/bin/s6-svc -1 /etc/s6/gitea/'` or send `USR1` directly to the Gitea process itself.
|
||||
|
||||
The next `logrotate` jobs will include your configurations, so no restart is needed. You can also immediately reload `logrotate` with `logrotate /etc/logrotate.conf --force`.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user