mirror of
https://github.com/go-gitea/gitea.git
synced 2025-08-14 14:30:29 +02:00
Compare commits
262 Commits
v1.21.0-de
...
v1.19.3
Author | SHA1 | Date | |
---|---|---|---|
|
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
|
||||
|
922
.drone.yml
922
.drone.yml
File diff suppressed because it is too large
Load Diff
246
.eslintrc.yaml
246
.eslintrc.yaml
@@ -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
|
||||
@@ -47,26 +40,11 @@ overrides:
|
||||
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]
|
||||
|
3
.gitattributes
vendored
3
.gitattributes
vendored
@@ -1,8 +1,7 @@
|
||||
* 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/js/vendor/** -text -eol linguist-vendored
|
||||
|
23
.github/lock.yml
vendored
Normal file
23
.github/lock.yml
vendored
Normal file
@@ -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
|
27
.github/workflows/cron-licenses.yml
vendored
27
.github/workflows/cron-licenses.yml
vendored
@@ -1,27 +0,0 @@
|
||||
name: cron-licenses
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "7 0 * * 1" # every Monday at 00:07 UTC
|
||||
|
||||
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 }}
|
22
.github/workflows/cron-lock.yml
vendored
22
.github/workflows/cron-lock.yml
vendored
@@ -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
|
48
.github/workflows/cron-translations.yml
vendored
48
.github/workflows/cron-translations.yml
vendored
@@ -1,48 +0,0 @@
|
||||
name: cron-translations
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "7 0 * * *" # every day at 00:07 UTC
|
||||
|
||||
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
|
53
.github/workflows/files-changed.yml
vendored
53
.github/workflows/files-changed.yml
vendored
@@ -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/*"
|
142
.github/workflows/pull-compliance.yml
vendored
142
.github/workflows/pull-compliance.yml
vendored
@@ -1,142 +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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
|
||||
backend:
|
||||
if: needs.files-changed.outputs.backend == '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-backend deps-tools
|
||||
- run: make deps-frontend
|
||||
- run: make frontend
|
||||
- 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
|
||||
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
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v4
|
||||
- run: make lint-actions
|
247
.github/workflows/pull-db-tests.yml
vendored
247
.github/workflows/pull-db-tests.yml
vendored
@@ -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.frontend == '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.frontend == '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
|
||||
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.frontend == '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.frontend == '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.frontend == '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
|
23
.github/workflows/pull-docker-dryrun.yml
vendored
23
.github/workflows/pull-docker-dryrun.yml
vendored
@@ -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
|
||||
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
|
32
.github/workflows/pull-e2e-tests.yml
vendored
32
.github/workflows/pull-e2e-tests.yml
vendored
@@ -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
|
||||
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
|
3
.gitignore
vendored
3
.gitignore
vendored
@@ -47,7 +47,6 @@ cpu.out
|
||||
|
||||
*.db
|
||||
*.log
|
||||
*.log.*.gz
|
||||
|
||||
/gitea
|
||||
/gitea-vet
|
||||
@@ -72,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
|
||||
|
17
.gitpod.yml
17
.gitpod.yml
@@ -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
|
||||
|
@@ -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"
|
||||
|
2
.ignore
2
.ignore
@@ -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
|
||||
|
3
.lgtm
Normal file
3
.lgtm
Normal file
@@ -0,0 +1,3 @@
|
||||
pattern = "(?)LGTM"
|
||||
self_approval_off = true
|
||||
ignore_maintainers_file = true
|
1
.npmrc
1
.npmrc
@@ -3,4 +3,3 @@ fund=false
|
||||
update-notifier=false
|
||||
package-lock=true
|
||||
save-exact=true
|
||||
lockfile-version=3
|
||||
|
@@ -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
|
||||
@@ -90,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
|
||||
@@ -98,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
|
||||
|
33
BSDmakefile
33
BSDmakefile
@@ -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
|
||||
|
@@ -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.
|
654
CONTRIBUTING.md
654
CONTRIBUTING.md
@@ -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 compatability](#github-api-compatability)
|
||||
- [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/master/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/master/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 compatability
|
||||
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
|
||||
@@ -561,3 +427,17 @@ be reviewed by two maintainers and must pass the automatic tests.
|
||||
- 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.
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
12
MAINTAINERS
12
MAINTAINERS
@@ -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)
|
182
Makefile
182
Makefile
@@ -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)
|
||||
|
||||
@@ -114,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))
|
||||
@@ -136,11 +136,11 @@ 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)
|
||||
GO_SOURCES += $(shell find $(GO_DIRS) -type f -name "*.go" ! -path modules/options/bindata.go ! -path modules/public/bindata.go ! -path modules/templates/bindata.go)
|
||||
GO_SOURCES += $(shell find $(GO_DIRS) -type f -name "*.go" -not -path modules/options/bindata.go -not -path modules/public/bindata.go -not -path modules/templates/bindata.go)
|
||||
GO_SOURCES += $(GENERATED_GO_DEST)
|
||||
GO_SOURCES_NO_BINDATA := $(GO_SOURCES)
|
||||
|
||||
@@ -194,26 +194,11 @@ help:
|
||||
@echo " - clean delete backend and integration files"
|
||||
@echo " - clean-all delete backend, frontend and integration files"
|
||||
@echo " - deps install dependencies"
|
||||
@echo " - deps-docs install docs 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"
|
||||
@@ -231,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:
|
||||
@@ -285,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}"; \
|
||||
@@ -305,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)
|
||||
@@ -324,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}"; \
|
||||
@@ -337,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
|
||||
|
||||
@@ -349,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 docs/assets/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 docs/assets/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
|
||||
@@ -482,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}"; \
|
||||
@@ -814,7 +751,7 @@ generate-go: $(TAGS_PREREQ)
|
||||
|
||||
.PHONY: security-check
|
||||
security-check:
|
||||
go run $(GOVULNCHECK_PACKAGE) ./...
|
||||
go run $(GOVULNCHECK_PACKAGE) -v ./...
|
||||
|
||||
$(EXECUTABLE): $(GO_SOURCES) $(TAGS_PREREQ)
|
||||
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) build $(GOFLAGS) $(EXTRA_GOFLAGS) -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)' -o $@
|
||||
@@ -883,17 +820,14 @@ release-docs: | $(DIST_DIRS) docs
|
||||
tar -czf $(DIST)/release/gitea-docs-$(VERSION).tar.gz -C ./docs/public .
|
||||
|
||||
.PHONY: docs
|
||||
docs: deps-docs
|
||||
docs:
|
||||
@hash hugo > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
||||
curl -sL https://github.com/gohugoio/hugo/releases/download/v$(HUGO_VERSION)/hugo_$(HUGO_VERSION)_Linux-64bit.tar.gz | tar zxf - -C /tmp && mv /tmp/hugo /usr/bin/hugo && chmod +x /usr/bin/hugo; \
|
||||
fi
|
||||
cd docs; make trans-copy clean build-offline;
|
||||
|
||||
.PHONY: deps-docs
|
||||
deps-docs:
|
||||
@hash hugo > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
||||
curl -sL https://github.com/gohugoio/hugo/releases/download/v$(HUGO_VERSION)/hugo_$(HUGO_VERSION)_Linux-64bit.tar.gz | tar zxf - -C /tmp && mkdir -p ~/go/bin && mv /tmp/hugo ~/go/bin/hugo && chmod +x ~/go/bin/hugo; \
|
||||
fi
|
||||
|
||||
.PHONY: deps
|
||||
deps: deps-frontend deps-backend deps-tools deps-docs
|
||||
deps: deps-frontend deps-backend
|
||||
|
||||
.PHONY: deps-frontend
|
||||
deps-frontend: node_modules
|
||||
@@ -901,11 +835,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)
|
||||
@@ -914,7 +846,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
|
||||
@@ -956,7 +887,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}"; \
|
||||
@@ -966,7 +897,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:"; \
|
||||
@@ -1005,6 +936,25 @@ 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) .
|
||||
|
@@ -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)
|
||||
|
||||
|
102
assets/go-licenses.json
generated
102
assets/go-licenses.json
generated
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("----")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -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)
|
||||
|
@@ -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)
|
||||
}
|
||||
}
|
@@ -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.Init(&setting.Options{})
|
||||
|
||||
scope := c.String("scope")
|
||||
|
||||
respText, extra := private.GenerateActionsRunnerToken(ctx, scope)
|
||||
if extra.HasError() {
|
||||
return handleCliResponseExtra(extra)
|
||||
}
|
||||
_, _ = fmt.Printf("%s\n", respText)
|
||||
return nil
|
||||
}
|
20
cmd/cmd.go
20
cmd/cmd.go
@@ -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.Init(&setting.Options{})
|
||||
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,17 +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).RemoveAllWriters().AddWriters(writer)
|
||||
}
|
||||
|
@@ -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.Init(&setting.Options{})
|
||||
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).RemoveAllWriters().AddWriters(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)
|
||||
}
|
||||
|
32
cmd/dump.go
32
cmd/dump.go
@@ -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(),
|
||||
@@ -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.Init(&setting.Options{})
|
||||
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,6 +223,7 @@ func runDump(ctx *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
verbose := ctx.Bool("verbose")
|
||||
var iface interface{}
|
||||
if fileName == "-" {
|
||||
iface, err = archiver.ByExtension(fmt.Sprintf(".%s", outType))
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
127
cmd/embedded.go
127
cmd/embedded.go
@@ -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"
|
||||
@@ -87,31 +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)
|
||||
|
||||
// Read configuration file
|
||||
setting.Init(&setting.Options{
|
||||
AllowEmpty: true,
|
||||
})
|
||||
setting.InitProviderAllowEmpty()
|
||||
setting.LoadCommonSettings()
|
||||
|
||||
patterns, err := compileCollectPatterns(c.Args())
|
||||
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
|
||||
}
|
||||
@@ -145,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
|
||||
@@ -157,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
|
||||
@@ -181,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 := "."
|
||||
@@ -206,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)
|
||||
@@ -214,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 {
|
||||
@@ -251,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()
|
||||
@@ -272,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{"**"}
|
||||
}
|
||||
@@ -303,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
|
||||
}
|
||||
}
|
||||
|
29
cmd/embedded_stub.go
Normal file
29
cmd/embedded_stub.go
Normal file
@@ -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
|
||||
}
|
161
cmd/hook.go
161
cmd/hook.go
@@ -6,9 +6,9 @@ package cmd
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"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"
|
||||
)
|
||||
@@ -140,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
|
||||
}
|
||||
@@ -166,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.`, "")
|
||||
}
|
||||
@@ -201,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
|
||||
@@ -236,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
|
||||
@@ -256,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
|
||||
@@ -279,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")
|
||||
@@ -300,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 {
|
||||
@@ -314,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.`, "")
|
||||
}
|
||||
@@ -351,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
|
||||
@@ -373,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
|
||||
}
|
||||
@@ -385,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...)
|
||||
@@ -400,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)
|
||||
@@ -418,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...)
|
||||
@@ -431,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()
|
||||
@@ -476,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)
|
||||
@@ -506,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
|
||||
}
|
||||
@@ -521,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:]), " ")
|
||||
|
||||
@@ -546,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
|
||||
}
|
||||
@@ -575,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
|
||||
}
|
||||
@@ -593,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
|
||||
}
|
||||
@@ -617,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
|
||||
@@ -640,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
|
||||
}
|
||||
@@ -648,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
|
||||
}
|
||||
@@ -709,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
|
||||
@@ -720,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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -755,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]
|
||||
@@ -777,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
|
||||
|
@@ -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())
|
||||
}
|
||||
|
@@ -64,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
|
||||
|
@@ -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.Init(&setting.Options{})
|
||||
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: "..",
|
||||
|
@@ -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
|
||||
}
|
||||
|
@@ -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,25 +191,58 @@ 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"))
|
||||
setup("manager", c.Bool("debug"))
|
||||
vals := map[string]interface{}{}
|
||||
mode := "conn"
|
||||
vals["net"] = "tcp"
|
||||
@@ -204,10 +269,7 @@ func runAddConnLogger(c *cli.Context) error {
|
||||
}
|
||||
|
||||
func runAddFileLogger(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
setup(ctx, c.Bool("debug"))
|
||||
setup("manager", c.Bool("debug"))
|
||||
vals := map[string]interface{}{}
|
||||
mode := "file"
|
||||
if c.IsSet("filename") {
|
||||
@@ -236,12 +298,22 @@ func runAddFileLogger(c *cli.Context) error {
|
||||
return commonAddLogger(c, mode, vals)
|
||||
}
|
||||
|
||||
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]interface{}) e
|
||||
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
|
||||
}
|
||||
|
@@ -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()
|
||||
@@ -218,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"))
|
||||
|
@@ -25,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()
|
||||
|
||||
@@ -67,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())
|
||||
}
|
||||
|
@@ -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.Init(&setting.Options{})
|
||||
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)
|
||||
}
|
||||
|
107
cmd/serv.go
107
cmd/serv.go
@@ -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"
|
||||
@@ -55,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.Init(&setting.Options{})
|
||||
setting.InitProviderFromExistingFile()
|
||||
setting.LoadCommonSettings()
|
||||
if debug {
|
||||
setting.RunMode = "dev"
|
||||
}
|
||||
@@ -70,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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,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 ...interface{}) 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")
|
||||
@@ -155,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:
|
||||
@@ -184,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 {
|
||||
@@ -195,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]
|
||||
@@ -207,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 {
|
||||
@@ -220,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 {
|
||||
@@ -259,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
|
||||
@@ -287,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{
|
||||
@@ -299,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
|
||||
}
|
||||
@@ -345,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)
|
||||
}
|
||||
}
|
||||
|
||||
|
51
cmd/web.go
51
cmd/web.go
@@ -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,11 +22,9 @@ 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",
|
||||
@@ -49,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{
|
||||
@@ -85,27 +81,13 @@ 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 runWeb(ctx *cli.Context) error {
|
||||
if ctx.Bool("verbose") {
|
||||
setupConsoleLogger(log.TRACE, log.CanColorStdout, os.Stdout)
|
||||
_ = log.DelLogger("console")
|
||||
log.NewLogger(0, "console", "console", fmt.Sprintf(`{"level": "trace", "colorize": %t, "stacktraceLevel": "none"}`, log.CanColorStdout))
|
||||
} else if ctx.Bool("quiet") {
|
||||
setupConsoleLogger(log.FATAL, log.CanColorStdout, os.Stdout)
|
||||
_ = 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 {
|
||||
@@ -125,7 +107,8 @@ 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
|
||||
}
|
||||
|
||||
// Perform pre-initialization
|
||||
@@ -142,8 +125,10 @@ func runWeb(ctx *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
c := install.Routes()
|
||||
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()
|
||||
@@ -152,7 +137,7 @@ func runWeb(ctx *cli.Context) error {
|
||||
case <-graceful.GetManager().IsShutdown():
|
||||
<-graceful.GetManager().Done()
|
||||
log.Info("PID: %d Gitea Web Finished", os.Getpid())
|
||||
log.GetManager().Close()
|
||||
log.Close()
|
||||
return err
|
||||
default:
|
||||
}
|
||||
@@ -173,7 +158,8 @@ func runWeb(ctx *cli.Context) error {
|
||||
|
||||
log.Info("Global init")
|
||||
// Perform global initialization
|
||||
setting.Init(&setting.Options{})
|
||||
setting.InitProviderFromExistingFile()
|
||||
setting.LoadCommonSettings()
|
||||
routers.GlobalInitInstalled(graceful.GetManager().HammerContext())
|
||||
|
||||
// We check that AppDataPath exists here (it should have been created during installation)
|
||||
@@ -195,7 +181,7 @@ func runWeb(ctx *cli.Context) error {
|
||||
err := listen(c, true)
|
||||
<-graceful.GetManager().Done()
|
||||
log.Info("PID: %d Gitea Web Finished", os.Getpid())
|
||||
log.GetManager().Close()
|
||||
log.Close()
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -217,10 +203,9 @@ func setPort(port string) error {
|
||||
defaultLocalURL += ":" + setting.HTTPPort + "/"
|
||||
|
||||
// Save LOCAL_ROOT_URL if port changed
|
||||
setting.CfgProvider.Section("server").Key("LOCAL_ROOT_URL").SetValue(defaultLocalURL)
|
||||
if err := setting.CfgProvider.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
|
||||
}
|
||||
|
2
contrib/autoboot.sh
Executable file
2
contrib/autoboot.sh
Executable file
@@ -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,12 +5,16 @@ 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
|
||||
@@ -28,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:
|
||||
@@ -95,16 +95,61 @@ func runEnvironmentToIni(c *cli.Context) error {
|
||||
providedWorkPath := c.String("work-path")
|
||||
setting.SetCustomPathAndConf(providedCustom, providedConf, providedWorkPath)
|
||||
|
||||
cfg, err := setting.NewConfigProviderFromFile(&setting.Options{CustomConf: setting.CustomConf, AllowEmpty: true})
|
||||
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
|
||||
|
||||
prefixGitea := c.String("prefix") + "__"
|
||||
suffixFile := "__FILE"
|
||||
changed := setting.EnvironmentToConfig(cfg, prefixGitea, suffixFile, os.Environ())
|
||||
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
|
||||
@@ -116,8 +161,6 @@ func runEnvironmentToIni(c *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// clear Gitea's specific environment variables if requested
|
||||
if c.Bool("clear") {
|
||||
for _, kv := range os.Environ() {
|
||||
idx := strings.IndexByte(kv, '=')
|
||||
@@ -125,11 +168,69 @@ func runEnvironmentToIni(c *cli.Context) error {
|
||||
continue
|
||||
}
|
||||
eKey := kv[:idx]
|
||||
if strings.HasPrefix(eKey, prefixGitea) {
|
||||
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
|
2
contrib/mysql.sql
Normal file
2
contrib/mysql.sql
Normal file
@@ -0,0 +1,2 @@
|
||||
DROP DATABASE IF EXISTS gitea;
|
||||
CREATE DATABASE IF NOT EXISTS gitea CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
|
267
contrib/pr/checkout.go
Normal file
267
contrib/pr/checkout.go
Normal file
@@ -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
|
||||
|
@@ -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}"
|
||||
|
||||
|
@@ -20,7 +20,7 @@
|
||||
;; - 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
|
||||
;; - 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:
|
||||
@@ -49,9 +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
|
||||
;; 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"
|
||||
;;
|
||||
;; 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 =
|
||||
@@ -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"
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
@@ -2399,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`)
|
||||
@@ -2413,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`)
|
||||
@@ -2433,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
|
||||
|
||||
|
@@ -53,7 +53,7 @@ function doSearch() {
|
||||
} else {
|
||||
const para = document.createElement('P');
|
||||
para.textContent = 'Please enter a word or phrase above';
|
||||
document.getElementById('search-results').append(para);
|
||||
document.getElementById('search-results').appendChild(para);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ function executeSearch(searchQuery) {
|
||||
} else {
|
||||
const para = document.createElement('P');
|
||||
para.textContent = 'No matches found';
|
||||
document.getElementById('search-results').append(para);
|
||||
document.getElementById('search-results').appendChild(para);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -128,7 +128,7 @@ function populateResults(result) {
|
||||
categories: value.item.categories,
|
||||
snippet
|
||||
});
|
||||
document.getElementById('search-results').append(htmlToElement(output));
|
||||
document.getElementById('search-results').appendChild(htmlToElement(output));
|
||||
|
||||
for (const snipvalue of snippetHighlights) {
|
||||
new Mark(document.getElementById(`summary-${key}`)).mark(snipvalue);
|
||||
@@ -138,8 +138,8 @@ function populateResults(result) {
|
||||
|
||||
function render(templateString, data) {
|
||||
let conditionalMatches, copy;
|
||||
const conditionalPattern = /\$\{\s*isset ([a-zA-Z]*) \s*\}(.*)\$\{\s*end\s*\}/g;
|
||||
// since loop below depends on re.lastIndex, we use a copy to capture any manipulations whilst inside the loop
|
||||
const conditionalPattern = /\$\{\s*isset ([a-zA-Z]*) \s*\}(.*)\$\{\s*end\s*}/g;
|
||||
// since loop below depends on re.lastInxdex, we use a copy to capture any manipulations whilst inside the loop
|
||||
copy = templateString;
|
||||
while ((conditionalMatches = conditionalPattern.exec(templateString)) !== null) {
|
||||
if (data[conditionalMatches[1]]) {
|
||||
|
@@ -10,7 +10,7 @@ enableEmoji: true
|
||||
|
||||
permalinks:
|
||||
post: /:year/:month/:title/
|
||||
doc: /:sections[1:]/:slug/
|
||||
doc: /:slug/
|
||||
page: /:slug/
|
||||
default: /:slug/
|
||||
|
||||
@@ -18,8 +18,8 @@ params:
|
||||
description: Git with a cup of tea
|
||||
author: The Gitea Authors
|
||||
website: https://docs.gitea.io
|
||||
version: 1.19.0 # FIXME: this version was used as "latest stable release", but it always gets outdated and doesn't make sense
|
||||
minGoVersion: 1.20
|
||||
version: 1.18.5
|
||||
minGoVersion: 1.19
|
||||
goVersion: 1.20
|
||||
minNodeVersion: 16
|
||||
search: nav
|
||||
|
@@ -1,13 +0,0 @@
|
||||
---
|
||||
date: "2023-04-27T14:00:00+08:00"
|
||||
title: "Actions"
|
||||
slug: "actions"
|
||||
weight: 36
|
||||
toc: false
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
name: "Usage - Actions"
|
||||
weight: 31
|
||||
identifier: "actions"
|
||||
---
|
@@ -5,8 +5,6 @@ slug: adding-legal-pages
|
||||
weight: 110
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /en-us/adding-legal-pages
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
|
@@ -1,40 +0,0 @@
|
||||
---
|
||||
date: "2023-05-23T09:00:00+08:00"
|
||||
title: "添加法律页面"
|
||||
slug: adding-legal-pages
|
||||
weight: 110
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /zh-cn/adding-legal-pages
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
name: "添加法律页面"
|
||||
identifier: "adding-legal-pages"
|
||||
weight: 110
|
||||
---
|
||||
|
||||
一些法域(例如欧盟)要求在网站上添加特定的法律页面(例如隐私政策)。按照以下步骤将它们添加到你的 Gitea 实例中。
|
||||
|
||||
## 获取页面
|
||||
|
||||
Gitea 源代码附带了示例页面,位于 `contrib/legal` 目录中。将它们复制到 `custom/public/` 目录下。例如,如果要添加隐私政策:
|
||||
|
||||
```
|
||||
wget -O /path/to/custom/public/privacy.html https://raw.githubusercontent.com/go-gitea/gitea/main/contrib/legal/privacy.html.sample
|
||||
```
|
||||
|
||||
现在,你需要编辑该页面以满足你的需求。特别是,你必须更改电子邮件地址、网址以及与 "Your Gitea Instance" 相关的引用,以匹配你的情况。
|
||||
|
||||
请务必不要放置会暗示 Gitea 项目对你的服务器负责的一般服务条款或隐私声明。
|
||||
|
||||
## 使其可见
|
||||
|
||||
创建或追加到 `/path/to/custom/templates/custom/extra_links_footer.tmpl` 文件中:
|
||||
|
||||
```go
|
||||
<a class="item" href="{{AppSubUrl}}/assets/privacy.html">隐私政策</a>
|
||||
```
|
||||
|
||||
重启 Gitea 以查看更改。
|
@@ -1,12 +1,10 @@
|
||||
---
|
||||
date: "2017-01-01T16:00:00+02:00"
|
||||
title: "Backup and Restore"
|
||||
title: "Usage: Backup and Restore"
|
||||
slug: "backup-and-restore"
|
||||
weight: 11
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /en-us/backup-and-restore
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
|
@@ -1,12 +1,10 @@
|
||||
---
|
||||
date: "2018-06-06T09:33:00+08:00"
|
||||
title: "备份与恢复"
|
||||
title: "使用:备份与恢复"
|
||||
slug: "backup-and-restore"
|
||||
weight: 11
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /zh-cn/backup-and-restore
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
|
@@ -5,8 +5,6 @@ slug: "backup-and-restore"
|
||||
weight: 11
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /zh-tw/backup-and-restore
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
|
@@ -5,8 +5,6 @@ slug: "cmd-embedded"
|
||||
weight: 20
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /en-us/cmd-embedded
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
@@ -40,7 +38,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,105 +0,0 @@
|
||||
---
|
||||
date: "2023-05-23T09:00:00+08:00"
|
||||
title: "嵌入资源提取工具"
|
||||
slug: "cmd-embedded"
|
||||
weight: 20
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /zh-cn/cmd-embedded
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
name: "嵌入资源提取工具"
|
||||
weight: 20
|
||||
identifier: "cmd-embedded"
|
||||
---
|
||||
|
||||
# 嵌入资源提取工具
|
||||
|
||||
**目录**
|
||||
|
||||
{{< toc >}}
|
||||
|
||||
Gitea 的可执行文件包含了运行所需的所有资源:模板、图片、样式表和翻译文件。你可以通过在 `custom` 目录下的相应路径中放置替换文件来覆盖其中的任何资源(详见 [自定义 Gitea 配置]({{< relref "doc/administration/customizing-gitea.zh-cn.md" >}}))。
|
||||
|
||||
要获取嵌入资源的副本以进行编辑,可以使用 CLI 中的 `embedded` 命令,通过操作系统的 shell 执行。
|
||||
|
||||
**注意:** 嵌入资源提取工具包含在 Gitea 1.12 及以上版本中。
|
||||
|
||||
## 资源列表
|
||||
|
||||
要列出嵌入在 Gitea 可执行文件中的资源,请使用以下语法:
|
||||
|
||||
```sh
|
||||
gitea embedded list [--include-vendored] [patterns...]
|
||||
```
|
||||
|
||||
`--include-vendored` 标志使命令包括被供应的文件,这些文件通常被排除在外;即来自外部库的文件,这些文件是 Gitea 所需的(例如 [octicons](https://octicons.github.com/) 等)。
|
||||
|
||||
可以提供一系列文件搜索模式。Gitea 使用 [gobwas/glob](https://github.com/gobwas/glob) 作为其 glob 语法。以下是一些示例:
|
||||
|
||||
- 列出所有模板文件,无论在哪个虚拟目录下:`**.tmpl`
|
||||
- 列出所有邮件模板文件:`templates/mail/**.tmpl`
|
||||
- 列出 `public/img` 目录下的所有文件:`public/img/**`
|
||||
|
||||
不要忘记为模式使用引号,因为空格、`*` 和其他字符可能对命令行解释器有特殊含义。
|
||||
|
||||
如果未提供模式,则列出所有文件。
|
||||
|
||||
### 示例
|
||||
|
||||
列出所有路径中包含 `openid` 的嵌入文件:
|
||||
|
||||
```sh
|
||||
$ gitea embedded list '**openid**'
|
||||
public/img/auth/openid_connect.svg
|
||||
public/img/openid-16x16.png
|
||||
templates/user/auth/finalize_openid.tmpl
|
||||
templates/user/auth/signin_openid.tmpl
|
||||
templates/user/auth/signup_openid_connect.tmpl
|
||||
templates/user/auth/signup_openid_navbar.tmpl
|
||||
templates/user/auth/signup_openid_register.tmpl
|
||||
templates/user/settings/security_openid.tmpl
|
||||
```
|
||||
|
||||
## 提取资源
|
||||
|
||||
要提取嵌入在 Gitea 可执行文件中的资源,请使用以下语法:
|
||||
|
||||
```sh
|
||||
gitea [--config {file}] embedded extract [--destination {dir}|--custom] [--overwrite|--rename] [--include-vendored] {patterns...}
|
||||
```
|
||||
|
||||
`--config` 选项用于告知 Gitea `app.ini` 配置文件的位置(如果不在默认位置)。此选项仅在使用 `--custom` 标志时使用。
|
||||
|
||||
`--destination` 选项用于指定提取文件的目标目录。默认为当前目录。
|
||||
|
||||
`--custom` 标志告知 Gitea 直接将文件提取到 `custom` 目录中。为使其正常工作,该命令需要知道 `app.ini` 配置文件的位置(通过 `--config` 指定),并且根据配置的不同,需要从 Gitea 通常启动的目录运行。有关详细信息,请参阅 [自定义 Gitea 配置]({{< relref "doc/administration/customizing-gitea.zh-cn.md" >}})。
|
||||
|
||||
`--overwrite` 标志允许覆盖目标目录中的任何现有文件。
|
||||
|
||||
`--rename` 标志告知 Gitea 将目标目录中的任何现有文件重命名为 `filename.bak`。之前的 `.bak` 文件将被覆盖。
|
||||
|
||||
至少需要提供一个文件搜索模式;有关模式的语法和示例,请参阅上述 `list` 子命令。
|
||||
|
||||
### 重要提示
|
||||
|
||||
请确保**只提取需要自定义的文件**。位于 `custom` 目录中的文件不会受到 Gitea 的升级过程的影响。当 Gitea 升级到新版本(通过替换可执行文件)时,许多嵌入文件将发生变化。Gitea 将尊重并使用在 `custom` 目录中找到的任何文件,即使这些文件是旧的和不兼容的。
|
||||
|
||||
### 示例
|
||||
|
||||
将邮件模板提取到临时目录:
|
||||
|
||||
```sh
|
||||
$ mkdir tempdir
|
||||
$ gitea embedded extract --destination tempdir 'templates/mail/**.tmpl'
|
||||
Extracting to tempdir:
|
||||
tempdir/templates/mail/auth/activate.tmpl
|
||||
tempdir/templates/mail/auth/activate_email.tmpl
|
||||
tempdir/templates/mail/auth/register_notify.tmpl
|
||||
tempdir/templates/mail/auth/reset_passwd.tmpl
|
||||
tempdir/templates/mail/issue/assigned.tmpl
|
||||
tempdir/templates/mail/issue/default.tmpl
|
||||
tempdir/templates/mail/notify/collaborator.tmpl
|
||||
```
|
@@ -1,12 +1,10 @@
|
||||
---
|
||||
date: "2017-01-01T16:00:00+02:00"
|
||||
title: "Gitea Command Line"
|
||||
title: "Usage: Command Line"
|
||||
slug: "command-line"
|
||||
weight: 1
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /en-us/command-line
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
@@ -225,7 +223,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.
|
||||
@@ -553,28 +551,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
|
||||
```
|
||||
|
@@ -1,556 +0,0 @@
|
||||
---
|
||||
date: "2023-05-23T09:00:00+08:00"
|
||||
title: "Gitea 命令行"
|
||||
slug: "command-line"
|
||||
weight: 1
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /zh-cn/command-line
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
name: "Gitea 命令行"
|
||||
weight: 1
|
||||
identifier: "command-line"
|
||||
---
|
||||
|
||||
# 命令行
|
||||
|
||||
**目录**
|
||||
|
||||
{{< toc >}}
|
||||
|
||||
## 用法
|
||||
|
||||
`gitea [全局选项] 命令 [命令或全局选项] [参数...]`
|
||||
|
||||
## 全局选项
|
||||
|
||||
所有全局选项均可被放置在命令级别。
|
||||
|
||||
- `--help`,`-h`:显示帮助文本并退出。可选。
|
||||
- `--version`,`-v`:显示版本信息并退出。可选。 (示例:`Gitea version 1.1.0+218-g7b907ed built with: bindata, sqlite`)。
|
||||
- `--custom-path path`,`-C path`:Gitea 自定义文件夹的路径。可选。 (默认值:`AppWorkPath`/custom 或 `$GITEA_CUSTOM`)。
|
||||
- `--config path`,`-c path`:Gitea 配置文件的路径。可选。 (默认值:`custom`/conf/app.ini)。
|
||||
- `--work-path path`,`-w path`:Gitea 的 `AppWorkPath`。可选。 (默认值:LOCATION_OF_GITEA_BINARY 或 `$GITEA_WORK_DIR`)
|
||||
|
||||
注意:默认的 custom-path、config 和 work-path 也可以在构建时更改(如果需要)。
|
||||
|
||||
## 命令
|
||||
|
||||
### web
|
||||
|
||||
启动服务器:
|
||||
|
||||
- 选项:
|
||||
- `--port number`,`-p number`:端口号。可选。 (默认值:3000)。覆盖配置文件中的设置。
|
||||
- `--install-port number`:运行安装页面的端口号。可选。 (默认值:3000)。覆盖配置文件中的设置。
|
||||
- `--pid path`,`-P path`:Pid 文件的路径。可选。
|
||||
- `--quiet`,`-q`:只在控制台上输出 Fatal 日志,用于在设置日志之前发出的日志。
|
||||
- `--verbose`:在控制台上输出跟踪日志,用于在设置日志之前发出的日志。
|
||||
- 示例:
|
||||
- `gitea web`
|
||||
- `gitea web --port 80`
|
||||
- `gitea web --config /etc/gitea.ini --pid /some/custom/gitea.pid`
|
||||
- 注意:
|
||||
- Gitea 不应以 root 用户身份运行。要绑定到低于 1024 的端口,您可以在 Linux 上使用 setcap 命令:`sudo setcap 'cap_net_bind_service=+ep' /path/to/gitea`。每次更新 Gitea 都需要重新执行此操作。
|
||||
|
||||
### admin
|
||||
|
||||
管理员操作:
|
||||
|
||||
- 命令:
|
||||
- `user`:
|
||||
- `list`:
|
||||
- 选项:
|
||||
- `--admin`:仅列出管理员用户。可选。
|
||||
- 描述:列出所有现有用户。
|
||||
- 示例:
|
||||
- `gitea admin user list`
|
||||
- `delete`:
|
||||
- 选项:
|
||||
- `--email`:要删除的用户的电子邮件。
|
||||
- `--username`:要删除的用户的用户名。
|
||||
- `--id`:要删除的用户的ID。
|
||||
- 必须提供 `--id`、`--username` 或 `--email` 中的一个。如果提供多个,则所有条件必须匹配。
|
||||
- 示例:
|
||||
- `gitea admin user delete --id 1`
|
||||
- `create`:
|
||||
- 选项:
|
||||
- `--name value`:用户名。必填。自 Gitea 1.9.0 版本起,请改用 `--username` 标志。
|
||||
- `--username value`:用户名。必填。Gitea 1.9.0 新增。
|
||||
- `--password value`:密码。必填。
|
||||
- `--email value`:邮箱。必填。
|
||||
- `--admin`:如果提供此选项,将创建一个管理员用户。可选。
|
||||
- `--access-token`:如果提供,将为用户创建访问令牌。可选。(默认值:false)。
|
||||
- `--must-change-password`:如果提供,创建的用户将在初始登录后需要选择一个新密码。可选。(默认值:true)。
|
||||
- `--random-password`:如果提供,将使用随机生成的密码作为创建用户的密码。`--password` 的值将被忽略。可选。
|
||||
- `--random-password-length`:如果提供,将用于配置随机生成密码的长度。可选。(默认值:12)
|
||||
- 示例:
|
||||
- `gitea admin user create --username myname --password asecurepassword --email me@example.com`
|
||||
- `change-password`:
|
||||
- 选项:
|
||||
- `--username value`,`-u value`:用户名。必填。
|
||||
- `--password value`,`-p value`:新密码。必填。
|
||||
- 示例:
|
||||
- `gitea admin user change-password --username myname --password asecurepassword`
|
||||
- `must-change-password`:
|
||||
- 参数:
|
||||
- `[username...]`:需要更改密码的用户
|
||||
- 选项:
|
||||
- `--all`,`-A`:强制所有用户更改密码
|
||||
- `--exclude username`,`-e username`:排除给定的用户。可以多次设置。
|
||||
- `--unset`:撤销对给定用户的强制密码更改
|
||||
- `regenerate`:
|
||||
- 选项:
|
||||
- `hooks`:重新生成所有仓库的 Git Hooks。
|
||||
- `keys`:重新生成 authorized_keys 文件。
|
||||
- 示例:
|
||||
- `gitea admin regenerate hooks`
|
||||
- `gitea admin regenerate keys`
|
||||
- `auth`:
|
||||
- `list`:
|
||||
- 描述:列出所有存在的外部认证源。
|
||||
- 示例:
|
||||
- `gitea admin auth list`
|
||||
- `delete`:
|
||||
- 选项:
|
||||
- `--id`:要删除的源的 ID。必填。
|
||||
- 示例:
|
||||
- `gitea admin auth delete --id 1`
|
||||
- `add-oauth`:
|
||||
- 选项:
|
||||
- `--name`:应用程序名称。
|
||||
- `--provider`:OAuth2 提供者。
|
||||
- `--key`:客户端 ID(Key)。
|
||||
- `--secret`:客户端密钥。
|
||||
- `--auto-discover-url`:OpenID Connect 自动发现 URL(仅在使用 OpenID Connect 作为提供程序时需要)。
|
||||
- `--use-custom-urls`:在 GitLab/GitHub OAuth 端点上使用自定义 URL。
|
||||
- `--custom-tenant-id`:在 OAuth 端点上使用自定义租户 ID。
|
||||
- `--custom-auth-url`:使用自定义授权 URL(GitLab/GitHub 的选项)。
|
||||
- `--custom-token-url`:使用自定义令牌 URL(GitLab/GitHub 的选项)。
|
||||
- `--custom-profile-url`:使用自定义配置文件 URL(GitLab/GitHub 的选项)。
|
||||
- `--custom-email-url`:使用自定义电子邮件 URL(GitHub 的选项)。
|
||||
- `--icon-url`:OAuth2 登录源的自定义图标 URL。
|
||||
- `--skip-local-2fa`:允许源覆盖本地 2FA。(可选)
|
||||
- `--scopes`:请求此 OAuth2 源的附加范围。(可选)
|
||||
- `--required-claim-name`:必须设置的声明名称,以允许用户使用此源登录。(可选)
|
||||
- `--required-claim-value`:必须设置的声明值,以允许用户使用此源登录。(可选)
|
||||
- `--group-claim-name`:提供此源的组名的声明名称。(可选)
|
||||
- `--admin-group`:管理员用户的组声明值。(可选)
|
||||
- `--restricted-group`:受限用户的组声明值。(可选)
|
||||
- `--group-team-map`:组与组织团队之间的 JSON 映射。(可选)
|
||||
- `--group-team-map-removal`:根据组自动激活团队成员资格的删除。(可选)
|
||||
- 示例:
|
||||
- `gitea admin auth add-oauth --name external-github --provider github --key OBTAIN_FROM_SOURCE --secret OBTAIN_FROM_SOURCE`
|
||||
- `update-oauth`:
|
||||
- 选项:
|
||||
- `--id`:要更新的源的 ID。必填。
|
||||
- `--name`:应用程序名称。
|
||||
- `--provider`:OAuth2 提供者。
|
||||
- `--key`:客户端 ID(Key)。
|
||||
- `--secret`:客户端密钥。
|
||||
- `--auto-discover-url`:OpenID Connect 自动发现 URL(仅在使用 OpenID Connect 作为提供程序时需要)。
|
||||
- `--use-custom-urls`:在 GitLab/GitHub OAuth 端点上使用自定义 URL。
|
||||
- `--custom-tenant-id`:在 OAuth 端点上使用自定义租户 ID。
|
||||
- `--custom-auth-url`:使用自定义授权 URL(GitLab/GitHub 的选项)。
|
||||
- `--custom-token-url`:使用自定义令牌 URL(GitLab/GitHub 的选项)。
|
||||
- `--custom-profile-url`:使用自定义配置文件 URL(GitLab/GitHub 的选项)。
|
||||
- `--custom-email-url`:使用自定义电子邮件 URL(GitHub 的选项)。
|
||||
- `--icon-url`:OAuth2 登录源的自定义图标 URL。
|
||||
- `--skip-local-2fa`:允许源覆盖本地 2FA。(可选)
|
||||
- `--scopes`:请求此 OAuth2 源的附加范围。
|
||||
- `--required-claim-name`:必须设置的声明名称,以允许用户使用此源登录。(可选)
|
||||
- `--required-claim-value`:必须设置的声明值,以允许用户使用此源登录。(可选)
|
||||
- `--group-claim-name`:提供此源的组名的声明名称。(可选)
|
||||
- `--admin-group`:管理员用户的组声明值。(可选)
|
||||
- `--restricted-group`:受限用户的组声明值。(可选)
|
||||
- 示例:
|
||||
- `gitea admin auth update-oauth --id 1 --name external-github-updated`
|
||||
- `add-smtp`:
|
||||
- 选项:
|
||||
- `--name`:应用程序名称。必填。
|
||||
- `--auth-type`:SMTP 认证类型(PLAIN/LOGIN/CRAM-MD5)。默认为 PLAIN。
|
||||
- `--host`:SMTP 主机。必填。
|
||||
- `--port`:SMTP 端口。必填。
|
||||
- `--force-smtps`:SMTPS 始终在端口 465 上使用。设置此选项以强制在其他端口上使用 SMTPS。
|
||||
- `--skip-verify`:跳过 TLS 验证。
|
||||
- `--helo-hostname`:发送 HELO 时使用的主机名。留空以发送当前主机名。
|
||||
- `--disable-helo`:禁用 SMTP helo。
|
||||
- `--allowed-domains`:留空以允许所有域。使用逗号(',')分隔多个域。
|
||||
- `--skip-local-2fa`:跳过 2FA 登录。
|
||||
- `--active`:启用此认证源。
|
||||
备注:
|
||||
`--force-smtps`、`--skip-verify`、`--disable-helo`、`--skip-local-2fs` 和 `--active` 选项可以采用以下形式使用:
|
||||
- `--option`、`--option=true` 以启用选项
|
||||
- `--option=false` 以禁用选项
|
||||
如果未指定这些选项,则在 `update-smtp` 中不会更改值,或者在 `add-smtp` 中将使用默认的 `false` 值。
|
||||
- 示例:
|
||||
- `gitea admin auth add-smtp --name ldap --host smtp.mydomain.org --port 587 --skip-verify --active`
|
||||
- `update-smtp`:
|
||||
- 选项:
|
||||
- `--id`:要更新的源的 ID。必填。
|
||||
- 其他选项与 `add-smtp` 共享
|
||||
- 示例:
|
||||
- `gitea admin auth update-smtp --id 1 --host smtp.mydomain.org --port 587 --skip-verify=false`
|
||||
- `gitea admin auth update-smtp --id 1 --active=false`
|
||||
- `add-ldap`:添加新的 LDAP(通过 Bind DN)认证源
|
||||
- 选项:
|
||||
- `--name value`:认证名称。必填。
|
||||
- `--not-active`:停用认证源。
|
||||
- `--security-protocol value`:安全协议名称。必填。
|
||||
- `--skip-tls-verify`:禁用 TLS 验证。
|
||||
- `--host value`:LDAP 服务器的地址。必填。
|
||||
- `--port value`:连接到 LDAP 服务器时使用的端口。必填。
|
||||
- `--user-search-base value`:用户帐户将在其中搜索的 LDAP 基础路径。必填。
|
||||
- `--user-filter value`:声明如何查找试图进行身份验证的用户记录的 LDAP 过滤器。必填。
|
||||
- `--admin-filter value`:指定是否应授予用户管理员特权的 LDAP 过滤器。
|
||||
- `--restricted-filter value`:指定是否应将用户设置为受限状态的 LDAP 过滤器。
|
||||
- `--username-attribute value`:用户 LDAP 记录中包含用户名的属性。
|
||||
- `--firstname-attribute value`:用户 LDAP 记录中包含用户名字的属性。
|
||||
- `--surname-attribute value`:用户 LDAP 记录中包含用户姓氏的属性。
|
||||
- `--email-attribute value`:用户 LDAP 记录中包含用户电子邮件地址的属性。必填。
|
||||
- `--public-ssh-key-attribute value`:用户 LDAP 记录中包含用户公共 SSH 密钥的属性。
|
||||
- `--avatar-attribute value`:用户 LDAP 记录中包含用户头像的属性。
|
||||
- `--bind-dn value`:在搜索用户时绑定到 LDAP 服务器的 DN。
|
||||
- `--bind-password value`:绑定 DN 的密码(如果有)。
|
||||
- `--attributes-in-bind`:在绑定 DN 上下文中获取属性。
|
||||
- `--synchronize-users`:启用用户同步。
|
||||
- `--page-size value`:搜索页面大小。
|
||||
- 示例:
|
||||
- `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`
|
||||
- `update-ldap`:更新现有的 LDAP(通过 Bind DN)认证源
|
||||
- 选项:
|
||||
- `--id value`:认证源的 ID。必填。
|
||||
- `--name value`:认证名称。
|
||||
- `--not-active`:停用认证源。
|
||||
- `--security-protocol value`:安全协议名称。
|
||||
- `--skip-tls-verify`:禁用 TLS 验证。
|
||||
- `--host value`:LDAP 服务器的地址。
|
||||
- `--port value`:连接到 LDAP 服务器时使用的端口。
|
||||
- `--user-search-base value`:用户帐户将在其中搜索的 LDAP 基础路径。
|
||||
- `--user-filter value`:声明如何查找试图进行身份验证的用户记录的 LDAP 过滤器。
|
||||
- `--admin-filter value`:指定是否应授予用户管理员特权的 LDAP 过滤器。
|
||||
- `--restricted-filter value`:指定是否应将用户设置为受限状态的 LDAP 过滤器。
|
||||
- `--username-attribute value`:用户 LDAP 记录中包含用户名的属性。
|
||||
- `--firstname-attribute value`:用户 LDAP 记录中包含用户名字的属性。
|
||||
- `--surname-attribute value`:用户 LDAP 记录中包含用户姓氏的属性。
|
||||
- `--email-attribute value`:用户 LDAP 记录中包含用户电子邮件地址的属性。
|
||||
- `--public-ssh-key-attribute value`:用户 LDAP 记录中包含用户公共 SSH 密钥的属性。
|
||||
- `--avatar-attribute value`:用户 LDAP 记录中包含用户头像的属性。
|
||||
- `--bind-dn value`:在搜索用户时绑定到 LDAP 服务器的 DN。
|
||||
- `--bind-password value`:绑定 DN 的密码(如果有)。
|
||||
- `--attributes-in-bind`:在绑定 DN 上下文中获取属性。
|
||||
- `--synchronize-users`:启用用户同步。
|
||||
- `--page-size value`:搜索页面大小。
|
||||
- 示例:
|
||||
- `gitea admin auth update-ldap --id 1 --name "my ldap auth source"`
|
||||
- `gitea admin auth update-ldap --id 1 --username-attribute uid --firstname-attribute givenName --surname-attribute sn`
|
||||
- `add-ldap-simple`:添加新的 LDAP(简单身份验证)认证源
|
||||
- 选项:
|
||||
- `--name value`:认证名称。必填。
|
||||
- `--not-active`:停用认证源。
|
||||
- `--security-protocol value`:安全协议名称。必填。
|
||||
- `--skip-tls-verify`:禁用 TLS 验证。
|
||||
- `--host value`:LDAP 服务器的地址。必填。
|
||||
- `--port value`:连接到 LDAP 服务器时使用的端口。必填。
|
||||
- `--user-search-base value`:用户帐户将在其中搜索的 LDAP 基础路径。
|
||||
- `--user-filter value`:声明如何查找试图进行身份验证的用户记录的 LDAP 过滤器。必填。
|
||||
- `--admin-filter value`:指定是否应授予用户管理员特权的 LDAP 过滤器。
|
||||
- `--restricted-filter value`:指定是否应将用户设置为受限状态的 LDAP 过滤器。
|
||||
- `--username-attribute value`:用户 LDAP 记录中包含用户名的属性。
|
||||
- `--firstname-attribute value`:用户 LDAP 记录中包含用户名字的属性。
|
||||
- `--surname-attribute value`:用户 LDAP 记录中包含用户姓氏的属性。
|
||||
- `--email-attribute value`:用户 LDAP 记录中包含用户电子邮件地址的属性。必填。
|
||||
- `--public-ssh-key-attribute value`:用户 LDAP 记录中包含用户公共 SSH 密钥的属性。
|
||||
- `--avatar-attribute value`:用户 LDAP 记录中包含用户头像的属性。
|
||||
- `--user-dn value`:用户的 DN。必填。
|
||||
- 示例:
|
||||
- `gitea admin auth add-ldap-simple --name ldap --security-protocol unencrypted --host mydomain.org --port 389 --user-dn "cn=%s,ou=Users,dc=mydomain,dc=org" --user-filter "(&(objectClass=posixAccount)(cn=%s))" --email-attribute mail`
|
||||
- `update-ldap-simple`:更新现有的 LDAP(简单身份验证)认证源
|
||||
- 选项:
|
||||
- `--id value`:认证源的 ID。必填。
|
||||
- `--name value`:认证名称。
|
||||
- `--not-active`:停用认证源。
|
||||
- `--security-protocol value`:安全协议名称。
|
||||
- `--skip-tls-verify`:禁用 TLS 验证。
|
||||
- `--host value`:LDAP 服务器的地址。
|
||||
- `--port value`:连接到 LDAP 服务器时使用的端口。
|
||||
- `--user-search-base value`:用户帐户将在其中搜索的 LDAP 基础路径。
|
||||
- `--user-filter value`:声明如何查找试图进行身份验证的用户记录的 LDAP 过滤器。
|
||||
- `--admin-filter value`:指定是否应授予用户管理员特权的 LDAP 过滤器。
|
||||
- `--restricted-filter value`:指定是否应将用户设置为受限状态的 LDAP 过滤器。
|
||||
- `--username-attribute value`:用户 LDAP 记录中包含用户名的属性。
|
||||
- `--firstname-attribute value`:用户 LDAP 记录中包含用户名字的属性。
|
||||
- `--surname-attribute value`:用户 LDAP 记录中包含用户姓氏的属性。
|
||||
- `--email-attribute value`:用户 LDAP 记录中包含用户电子邮件地址的属性。
|
||||
- `--public-ssh-key-attribute value`:用户 LDAP 记录中包含用户公共 SSH 密钥的属性。
|
||||
- `--avatar-attribute value`:用户 LDAP 记录中包含用户头像的属性。
|
||||
- `--user-dn value`:用户的 DN。
|
||||
- 示例:
|
||||
- `gitea admin auth update-ldap-simple --id 1 --name "my ldap auth source"`
|
||||
- `gitea admin auth update-ldap-simple --id 1 --username-attribute uid --firstname-attribute givenName --surname-attribute sn`
|
||||
|
||||
### cert
|
||||
|
||||
生成自签名的SSL证书。将输出到当前目录下的`cert.pem`和`key.pem`文件中,并且会覆盖任何现有文件。
|
||||
|
||||
- 选项:
|
||||
- `--host value`:逗号分隔的主机名和IP地址列表,此证书适用于这些主机。支持使用通配符。必填。
|
||||
- `--ecdsa-curve value`:用于生成密钥的ECDSA曲线。可选。有效选项为P224、P256、P384、P521。
|
||||
- `--rsa-bits value`:要生成的RSA密钥的大小。可选。如果设置了--ecdsa-curve,则忽略此选项。(默认值:2048)。
|
||||
- `--start-date value`:证书的创建日期。可选。(格式:`Jan 1 15:04:05 2011`)。
|
||||
- `--duration value`:证书有效期。可选。(默认值:8760h0m0s)
|
||||
- `--ca`:如果提供此选项,则证书将生成自己的证书颁发机构。可选。
|
||||
- 示例:
|
||||
- `gitea cert --host git.example.com,example.com,www.example.com --ca`
|
||||
|
||||
### dump
|
||||
|
||||
将所有文件和数据库导出到一个zip文件中。输出文件将保存在当前目录下,类似于`gitea-dump-1482906742.zip`。
|
||||
|
||||
- 选项:
|
||||
- `--file name`,`-f name`:指定要创建的导出文件的名称。可选。(默认值:gitea-dump-[timestamp].zip)。
|
||||
- `--tempdir path`,`-t path`:指定临时目录的路径。可选。(默认值:/tmp)。
|
||||
- `--skip-repository`,`-R`:跳过仓库的导出。可选。
|
||||
- `--skip-custom-dir`:跳过自定义目录的导出。可选。
|
||||
- `--skip-lfs-data`:跳过LFS数据的导出。可选。
|
||||
- `--skip-attachment-data`:跳过附件数据的导出。可选。
|
||||
- `--skip-package-data`:跳过包数据的导出。可选。
|
||||
- `--skip-log`:跳过日志数据的导出。可选。
|
||||
- `--database`,`-d`:指定数据库的SQL语法。可选。
|
||||
- `--verbose`,`-V`:如果提供此选项,显示附加详细信息。可选。
|
||||
- `--type`:设置导出的格式。可选。(默认值:zip)
|
||||
- 示例:
|
||||
- `gitea dump`
|
||||
- `gitea dump --verbose`
|
||||
|
||||
### generate
|
||||
|
||||
用于在配置文件中生成随机值和令牌。对于自动部署时生成值非常有用。
|
||||
|
||||
- 命令:
|
||||
- `secret`:
|
||||
- 选项:
|
||||
- `INTERNAL_TOKEN`: 用于内部 API 调用身份验证的令牌。
|
||||
- `JWT_SECRET`: 用于 LFS 和 OAUTH2 JWT 身份验证的密钥(LFS_JWT_SECRET 是此选项的别名,用于向后兼容)。
|
||||
- `SECRET_KEY`: 全局密钥。
|
||||
- 示例:
|
||||
- `gitea generate secret INTERNAL_TOKEN`
|
||||
- `gitea generate secret JWT_SECRET`
|
||||
- `gitea generate secret SECRET_KEY`
|
||||
|
||||
### keys
|
||||
|
||||
提供一个 SSHD AuthorizedKeysCommand。需要在 sshd 配置文件中进行配置:
|
||||
|
||||
```ini
|
||||
...
|
||||
# -e 的值和 AuthorizedKeysCommandUser 应与运行 Gitea 的用户名匹配
|
||||
AuthorizedKeysCommandUser git
|
||||
AuthorizedKeysCommand /path/to/gitea keys -e git -u %u -t %t -k %k
|
||||
```
|
||||
|
||||
该命令将返回适用于提供的密钥的合适 authorized_keys 行。您还应在 `app.ini` 的 `[server]` 部分设置值 `SSH_CREATE_AUTHORIZED_KEYS_FILE=false`。
|
||||
|
||||
注意: opensshd 要求 Gitea 程序由 root 拥有,并且不可由组或其他人写入。程序必须使用绝对路径指定。
|
||||
注意: Gitea 必须在运行此命令时处于运行状态才能成功。
|
||||
|
||||
### migrate
|
||||
|
||||
迁移数据库。该命令可用于在首次启动服务器之前运行其他命令。此命令是幂等的。
|
||||
|
||||
### convert
|
||||
|
||||
将现有的 MySQL 数据库从 utf8 转换为 utf8mb4。
|
||||
|
||||
### doctor
|
||||
|
||||
根据给定的配置诊断当前 Gitea 实例的问题。目前有以下检查清单:
|
||||
|
||||
- 检查 OpenSSH 的 authorized_keys 文件是否正确
|
||||
当您的 Gitea 实例支持 OpenSSH 时,当您的 Gitea 实例添加或更改任何公钥时,Gitea 实例的二进制路径将被写入 `authorized_keys` 文件。
|
||||
有时,如果您在升级时移动或重命名了 Gitea 二进制文件,并且您没有在管理面板上运行“使用 Gitea 的 SSH 密钥更新「.ssh/authorized_keys」文件”操作。那么通过 SSH 的所有拉取/推送操作将无法正常工作。
|
||||
此检查将帮助您检查它是否正常工作。
|
||||
|
||||
对于贡献者,如果您想添加更多的检查项,您可以编写一个新的函数,如 `func(ctx *cli.Context) ([]string, error)`,并将其追加到 `doctor.go` 文件中。
|
||||
|
||||
```go
|
||||
var checklist = []check{
|
||||
{
|
||||
title: "Check if OpenSSH authorized_keys file id correct",
|
||||
f: runDoctorLocationMoved,
|
||||
},
|
||||
// more checks please append here
|
||||
}
|
||||
```
|
||||
|
||||
此函数将接收一个命令行上下文,并返回有关问题或错误的详细信息列表。
|
||||
|
||||
#### doctor recreate-table
|
||||
|
||||
有时,在迁移时,旧的列和默认值可能会在数据库模式中保持不变。这可能会导致警告,如下所示:
|
||||
|
||||
```
|
||||
2020/08/02 11:32:29 ...rm/session_schema.go:360:Sync2() [W] Table user Column keep_activity_private db default is , struct default is 0
|
||||
```
|
||||
|
||||
您可以通过以下方式让 Gitea 重新创建这些表,并将旧数据复制到新表中,并适当设置默认值:
|
||||
|
||||
```
|
||||
gitea doctor recreate-table user
|
||||
```
|
||||
|
||||
您可以使用以下方式让 Gitea 重新创建多个表:
|
||||
|
||||
```
|
||||
gitea doctor recreate-table table1 table2 ...
|
||||
```
|
||||
|
||||
如果您希望 Gitea 重新创建所有表,请直接调用:
|
||||
|
||||
```
|
||||
gitea doctor recreate-table
|
||||
```
|
||||
|
||||
强烈建议在运行这些命令之前备份您的数据库。
|
||||
|
||||
### manager
|
||||
|
||||
管理运行中的服务器操作:
|
||||
|
||||
- 命令:
|
||||
- `shutdown`: 优雅地关闭运行中的进程
|
||||
- `restart`: 优雅地重新启动运行中的进程(对于Windows服务器尚未实现)
|
||||
- `flush-queues`: 刷新运行中的进程中的队列
|
||||
- 选项:
|
||||
- `--timeout value`: 刷新过程的超时时间(默认值: 1m0s)
|
||||
- `--non-blocking`: 设置为true,以在返回之前不等待刷新完成
|
||||
- `logging`: 调整日志命令
|
||||
- 命令:
|
||||
- `pause`: 暂停日志记录
|
||||
- 注意:
|
||||
- 如果日志级别低于此级别,日志级别将被临时提升为INFO。
|
||||
- Gitea将在一定程度上缓冲日志,并在超过该点后丢弃日志。
|
||||
- `resume`: 恢复日志记录
|
||||
- `release-and-reopen`: 使Gitea释放和重新打开用于日志记录的文件和连接(相当于向Gitea发送SIGUSR1信号)。
|
||||
- `remove name`: 删除指定的日志记录器
|
||||
- 选项:
|
||||
- `--group group`, `-g group`: 从中删除子记录器的组(默认为`default`)
|
||||
- `add`: 添加日志记录器
|
||||
- 命令:
|
||||
- `console`: 添加控制台日志记录器
|
||||
- 选项:
|
||||
- `--group value`, `-g value`: 要添加日志记录器的组 - 默认为"default"
|
||||
- `--name value`, `-n value`: 新日志记录器的名称 - 默认为模式
|
||||
- `--level value`, `-l value`: 新日志记录器的日志级别
|
||||
- `--stacktrace-level value`, `-L value`: 堆栈跟踪日志级别
|
||||
- `--flags value`, `-F value`: 日志记录器的标志
|
||||
- `--expression value`, `-e value`: 日志记录器的匹配表达式
|
||||
- `--prefix value`, `-p value`: 日志记录器的前缀
|
||||
- `--color`: 在日志中使用颜色
|
||||
- `--stderr`: 将控制台日志输出到stderr - 仅适用于控制台
|
||||
- `file`: 添加文件日志记录器
|
||||
- 选项:
|
||||
- `--group value`, `-g value`: 要添加日志记录器的组 - 默认为"default"
|
||||
- `--name value`, `-n value`: 新日志记录器的名称 - 默认为模式
|
||||
- `--level value`, `-l value`: 新日志记录器的日志级别
|
||||
- `--stacktrace-level value`, `-L value`: 堆栈跟踪日志级别
|
||||
- `--flags value`, `-F value`: 日志记录器的标志
|
||||
- `--expression value`, `-e value`: 日志记录器的匹配表达式
|
||||
- `--prefix value`, `-p value`: 日志记录器的前缀
|
||||
- `--color`: 在日志中使用颜色
|
||||
- `--filename value`, `-f value`: 日志记录器的文件名
|
||||
- `--rotate`, `-r`: 轮转日志
|
||||
- `--max-size value`, `-s value`: 在轮转之前的最大大小(以字节为单位)
|
||||
- `--daily`, `-d`: 每天轮转日志
|
||||
- `--max-days value`, `-D value`: 保留的每日日志的最大数量
|
||||
- `--compress`, `-z`: 压缩轮转的日志
|
||||
- `--compression-level value`, `-Z value`: 使用的压缩级别
|
||||
- `conn`: 添加网络连接日志记录器
|
||||
- 选项:
|
||||
- `--group value`, `-g value`: 要添加日志记录器的组 - 默认为"default"
|
||||
- `--name value`, `-n value`: 新日志记录器的名称 - 默认为模式
|
||||
- `--level value`, `-l value`: 新日志记录器的日志级别
|
||||
- `--stacktrace-level value`, `-L value`: 堆栈跟踪日志级别
|
||||
- `--flags value`, `-F value`: 日志记录器的标志
|
||||
- `--expression value`, `-e value`: 日志记录器的匹配表达式
|
||||
- `--prefix value`, `-p value`: 日志记录器的前缀
|
||||
- `--color`: 在日志中使用颜色
|
||||
- `--reconnect-on-message`, `-R`: 对于每个消息重新连接主机
|
||||
- `--reconnect`, `-r`: 连接中断时重新连接主机
|
||||
- `--protocol value`, `-P value`: 设置要使用的协议:tcp、unix或udp(默认为tcp)
|
||||
- `--address value`, `-a value`: 要连接到的主机地址和端口(默认为:7020)
|
||||
- `smtp`: 添加SMTP日志记录器
|
||||
- 选项:
|
||||
- `--group value`, `-g value`: 要添加日志记录器的组 - 默认为"default"
|
||||
- `--name value`, `-n value`: 新日志记录器的名称 - 默认为模式
|
||||
- `--level value`, `-l value`: 新日志记录器的日志级别
|
||||
- `--stacktrace-level value`, `-L value`: 堆栈跟踪日志级别
|
||||
- `--flags value`, `-F value`: 日志记录器的标志
|
||||
- `--expression value`, `-e value`: 日志记录器的匹配表达式
|
||||
- `--prefix value`, `-p value`: 日志记录器的前缀
|
||||
- `--color`: 在日志中使用颜色
|
||||
- `--username value`, `-u value`: 邮件服务器用户名
|
||||
- `--password value`, `-P value`: 邮件服务器密码
|
||||
- `--host value`, `-H value`: 邮件服务器主机(默认为: 127.0.0.1:25)
|
||||
- `--send-to value`, `-s value`: 要发送到的电子邮件地址
|
||||
- `--subject value`, `-S value`: 发送电子邮件的主题标题
|
||||
- `processes`: 显示 Gitea 进程和 Goroutine 信息
|
||||
- 选项:
|
||||
- `--flat`: 以平面表格形式显示进程,而不是树形结构
|
||||
- `--no-system`: 不显示系统进程
|
||||
- `--stacktraces`: 显示与进程关联的 Goroutine 的堆栈跟踪
|
||||
- `--json`: 输出为 JSON 格式
|
||||
- `--cancel PID`: 向具有 PID 的进程发送取消命令(仅适用于非系统进程)
|
||||
|
||||
### dump-repo
|
||||
|
||||
`dump-repo` 从 Git/GitHub/Gitea/GitLab 中转储存储库数据:
|
||||
|
||||
- 选项:
|
||||
- `--git_service service`:Git 服务,可以是 `git`、`github`、`gitea`、`gitlab`。如果 `clone_addr` 可以被识别,则可以忽略此选项。
|
||||
- `--repo_dir dir`,`-r dir`:存储数据的存储库目录路径。
|
||||
- `--clone_addr addr`:将被克隆的 URL,目前可以是 git/github/gitea/gitlab 的 http/https URL。例如:https://github.com/lunny/tango.git
|
||||
- `--auth_username lunny`:访问 `clone_addr` 的用户名。
|
||||
- `--auth_password <password>`:访问 `clone_addr` 的密码。
|
||||
- `--auth_token <token>`:访问 `clone_addr` 的个人令牌。
|
||||
- `--owner_name lunny`:如果非空,数据将存储在具有所有者名称的目录中。
|
||||
- `--repo_name tango`:如果非空,数据将存储在具有存储库名称的目录中。
|
||||
- `--units <units>`:要迁移的项目,一个或多个项目应以逗号分隔。允许的项目有 wiki, issues, labels, releases, release_assets, milestones, pull_requests, comments。如果为空,则表示所有项目。
|
||||
|
||||
### restore-repo
|
||||
|
||||
`restore-repo` 从磁盘目录中还原存储库数据:
|
||||
|
||||
- 选项:
|
||||
- `--repo_dir dir`,`-r dir`:还原数据的存储库目录路径。
|
||||
- `--owner_name lunny`:还原目标所有者名称。
|
||||
- `--repo_name tango`:还原目标存储库名称。
|
||||
- `--units <units>`:要还原的项目,一个或多个项目应以逗号分隔。允许的项目有 wiki, issues, labels, releases, release_assets, milestones, pull_requests, comments。如果为空,则表示所有项目。
|
||||
|
||||
### actions generate-runner-token
|
||||
|
||||
生成一个供 Runner 使用的新令牌,用于向服务器注册。
|
||||
|
||||
- 选项:
|
||||
- `--scope {owner}[/{repo}]`,`-s {owner}[/{repo}]`:限制 Runner 的范围,没有范围表示该 Runner 可用于所有仓库,但你也可以将其限制为特定的仓库或所有者。
|
||||
|
||||
要注册全局 Runner:
|
||||
|
||||
```
|
||||
gitea actions generate-runner-token
|
||||
```
|
||||
|
||||
要注册特定组织的 Runner,例如 `org`:
|
||||
|
||||
```
|
||||
gitea actions generate-runner-token -s org
|
||||
```
|
||||
|
||||
要注册特定仓库的 Runner,例如 `username/test-repo`:
|
||||
|
||||
```
|
||||
gitea actions generate-runner-token -s username/test-repo
|
||||
```
|
@@ -5,8 +5,6 @@ slug: "config-cheat-sheet"
|
||||
weight: 30
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /en-us/config-cheat-sheet
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
@@ -48,7 +46,7 @@ reported as part of the default configuration when running `gitea --help` or on
|
||||
- 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
|
||||
- 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:
|
||||
@@ -73,7 +71,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.
|
||||
- `RUN_MODE`: **prod**: Application run mode, affects performance and debugging. Either "dev", "prod" or "test".
|
||||
|
||||
## Repository (`repository`)
|
||||
|
||||
@@ -89,14 +87,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.
|
||||
@@ -117,7 +117,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`)
|
||||
@@ -141,7 +141,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`)
|
||||
|
||||
@@ -221,6 +220,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.
|
||||
@@ -230,6 +230,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).
|
||||
|
||||
@@ -275,8 +276,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`)
|
||||
@@ -345,7 +345,7 @@ The following configuration set `Content-Type: application/vnd.android.package-a
|
||||
- `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.)
|
||||
@@ -365,7 +365,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.
|
||||
|
||||
@@ -458,13 +458,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
|
||||
@@ -473,6 +477,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.
|
||||
|
||||
@@ -480,14 +485,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.
|
||||
- `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:
|
||||
|
||||
@@ -505,6 +519,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
|
||||
@@ -514,7 +543,7 @@ And the following unique queues:
|
||||
|
||||
- `INSTALL_LOCK`: **false**: Controls access to the installation page. When set to "true", the installation page is not accessible.
|
||||
- `SECRET_KEY`: **\<random at every install\>**: Global secret key. This key is VERY IMPORTANT, if you lost it, the data encrypted by it (like 2FA secret) can't be decrypted anymore.
|
||||
- `SECRET_KEY_URI`: **\<empty\>**: Instead of defining SECRET_KEY, this option can be used to use the key stored in a file (example value: `file:/etc/gitea/secret_key`). It shouldn't be lost like SECRET_KEY.
|
||||
- `SECRET_KEY_URI`: **<empty>**: Instead of defining SECRET_KEY, this option can be used to use the key stored in a file (example value: `file:/etc/gitea/secret_key`). It shouldn't be lost like SECRET_KEY.
|
||||
- `LOGIN_REMEMBER_DAYS`: **7**: Cookie lifetime, in days.
|
||||
- `COOKIE_USERNAME`: **gitea\_awesome**: Name of the cookie used to store the current username.
|
||||
- `COOKIE_REMEMBER_NAME`: **gitea\_incredible**: Name of cookie used to store authentication
|
||||
@@ -540,7 +569,7 @@ And the following unique queues:
|
||||
- `ONLY_ALLOW_PUSH_IF_GITEA_ENVIRONMENT_SET`: **true**: Set to `false` to allow local users to push to gitea-repositories without setting up the Gitea environment. This is not recommended and if you want local users to push to Gitea repositories you should set the environment appropriately.
|
||||
- `IMPORT_LOCAL_PATHS`: **false**: Set to `false` to prevent all users (including admin) from importing local path on server.
|
||||
- `INTERNAL_TOKEN`: **\<random at every install if no uri set\>**: Secret used to validate communication within Gitea binary.
|
||||
- `INTERNAL_TOKEN_URI`: **\<empty\>**: Instead of defining INTERNAL_TOKEN in the configuration, this configuration option can be used to give Gitea a path to a file that contains the internal token (example value: `file:/etc/gitea/internal_token`)
|
||||
- `INTERNAL_TOKEN_URI`: **<empty>**: Instead of defining INTERNAL_TOKEN in the configuration, this configuration option can be used to give Gitea a path to a file that contains the internal token (example value: `file:/etc/gitea/internal_token`)
|
||||
- `PASSWORD_HASH_ALGO`: **pbkdf2**: The hash algorithm to use \[argon2, pbkdf2, pbkdf2_v1, pbkdf2_hi, scrypt, bcrypt\], argon2 and scrypt will spend significant amounts of memory.
|
||||
- Note: The default parameters for `pbkdf2` hashing have changed - the previous settings are available as `pbkdf2_v1` but are not recommended.
|
||||
- The hash functions may be tuned by using `$` after the algorithm:
|
||||
@@ -571,8 +600,8 @@ And the following unique queues:
|
||||
## Camo (`camo`)
|
||||
|
||||
- `ENABLED`: **false**: Enable media proxy, we support images only at the moment.
|
||||
- `SERVER_URL`: **\<empty\>**: URL of camo server, it **is required** if camo is enabled.
|
||||
- `HMAC_KEY`: **\<empty\>**: Provide the HMAC key for encoding URLs, it **is required** if camo is enabled.
|
||||
- `SERVER_URL`: **<empty>**: URL of camo server, it **is required** if camo is enabled.
|
||||
- `HMAC_KEY`: **<empty>**: Provide the HMAC key for encoding URLs, it **is required** if camo is enabled.
|
||||
- `ALLWAYS`: **false**: Set to true to use camo for both HTTP and HTTPS content, otherwise only non-HTTPS URLs are proxied
|
||||
|
||||
## OpenID (`openid`)
|
||||
@@ -651,8 +680,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
|
||||
@@ -755,11 +785,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.
|
||||
@@ -772,7 +801,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.
|
||||
@@ -792,10 +821,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.
|
||||
@@ -834,48 +862,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.
|
||||
@@ -883,13 +911,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.
|
||||
@@ -1005,7 +1041,7 @@ Default templates for project boards:
|
||||
- `RUN_AT_START`: **false**: Run tasks at start up time (if ENABLED).
|
||||
- `NOTICE_ON_SUCCESS`: **false**: Set to true to switch on success notices.
|
||||
- `SCHEDULE`: **@every 168h**: Cron syntax to set how often to check.
|
||||
- `OLDER_THAN`: **8760h**: any action older than this expression will be deleted from database, suggest using `8760h` (1 year) because that's the max length of heatmap.
|
||||
- `OLDER_THAN`: **@every 8760h**: any action older than this expression will be deleted from database, suggest using `8760h` (1 year) because that's the max length of heatmap.
|
||||
|
||||
#### Cron - Check for new Gitea versions (`cron.update_checker`)
|
||||
|
||||
@@ -1021,7 +1057,7 @@ Default templates for project boards:
|
||||
- `RUN_AT_START`: **false**: Run tasks at start up time (if ENABLED).
|
||||
- `NO_SUCCESS_NOTICE`: **false**: Set to true to switch off success notices.
|
||||
- `SCHEDULE`: **@every 168h**: Cron syntax to set how often to check.
|
||||
- `OLDER_THAN`: **8760h**: any system notice older than this expression will be deleted from database.
|
||||
- `OLDER_THAN`: **@every 8760h**: any system notice older than this expression will be deleted from database.
|
||||
|
||||
#### Cron - Garbage collect LFS pointers in repositories (`cron.gc_lfs`)
|
||||
|
||||
@@ -1054,7 +1090,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.
|
||||
@@ -1063,15 +1104,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.
|
||||
@@ -1115,7 +1147,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
|
||||
```
|
||||
|
||||
@@ -1166,6 +1198,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`)
|
||||
@@ -1174,7 +1207,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`)
|
||||
|
||||
@@ -1204,26 +1237,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`)
|
||||
@@ -1323,7 +1350,7 @@ PROXY_HOSTS = *.github.com
|
||||
## Actions (`actions`)
|
||||
|
||||
- `ENABLED`: **false**: Enable/Disable actions capabilities
|
||||
- `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`: **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 should we find the relative path action plugin. i.e. when use an action in a workflow file like
|
||||
|
||||
@@ -1357,6 +1384,7 @@ 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"
|
||||
weight: 30
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /zh-cn/config-cheat-sheet
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
@@ -43,6 +41,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`)
|
||||
|
||||
@@ -110,6 +109,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`。
|
||||
@@ -117,6 +120,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`)
|
||||
@@ -214,8 +218,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**: 存储仓库头像的路径。
|
||||
@@ -258,22 +262,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`)
|
||||
|
||||
@@ -337,7 +326,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
|
||||
```
|
||||
|
||||
@@ -479,4 +468,5 @@ PROXY_HOSTS = *.github.com
|
||||
|
||||
## Other (`other`)
|
||||
|
||||
- `SHOW_FOOTER_BRANDING`: 为真则在页面底部显示Gitea的字样。
|
||||
- `SHOW_FOOTER_VERSION`: 为真则在页面底部显示Gitea的版本。
|
||||
|
@@ -5,8 +5,6 @@ slug: "customizing-gitea"
|
||||
weight: 100
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /en-us/customizing-gitea
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
@@ -282,22 +280,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"
|
||||
weight: 100
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /zh-cn/customizing-gitea
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
|
@@ -1,12 +1,10 @@
|
||||
---
|
||||
date: "2019-10-15T10:10:00+05:00"
|
||||
title: "Email setup"
|
||||
title: "Usage: Email setup"
|
||||
slug: "email-setup"
|
||||
weight: 12
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /en-us/email-setup
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
|
@@ -1,91 +0,0 @@
|
||||
---
|
||||
date: "2023-05-23T09:00:00+08:00"
|
||||
title: "Email 设置"
|
||||
slug: "email-setup"
|
||||
weight: 12
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /zh-cn/email-setup
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
name: "Email 设置"
|
||||
weight: 12
|
||||
identifier: "email-setup"
|
||||
---
|
||||
|
||||
# Email 设置
|
||||
|
||||
**目录**
|
||||
|
||||
{{< toc >}}
|
||||
|
||||
Gitea 具有邮件功能,用于发送事务性邮件(例如注册确认邮件)。它可以配置为使用 Sendmail(或兼容的 MTA,例如 Postfix 和 msmtp)或直接使用 SMTP 服务器。
|
||||
|
||||
## 使用 Sendmail
|
||||
|
||||
使用 `sendmail` 命令作为邮件传输代理(mailer)。
|
||||
|
||||
注意:对于在官方Gitea Docker镜像中使用,请使用SMTP版本进行配置(请参考下一节)。
|
||||
|
||||
注意:对于面向互联网的网站,请查阅您的 MTA 文档以了解通过TLS发送邮件的说明。同时设置 SPF、DMARC 和 DKIM DNS 记录,以使发送的邮件被各个电子邮件提供商接受为合法邮件。
|
||||
|
||||
```ini
|
||||
[mailer]
|
||||
ENABLED = true
|
||||
FROM = gitea@mydomain.com
|
||||
MAILER_TYPE = sendmail
|
||||
SENDMAIL_PATH = /usr/sbin/sendmail
|
||||
SENDMAIL_ARGS = "--" ; 大多数 "sendmail" 程序都接受选项,使用 "--" 将防止电子邮件地址被解释为选项。
|
||||
```
|
||||
|
||||
## 使用 SMTP
|
||||
|
||||
直接使用 SMTP 服务器作为中继。如果您不想在实例上设置 MTA,但在电子邮件提供商那里有一个帐户,这个选项非常有用。
|
||||
|
||||
```ini
|
||||
[mailer]
|
||||
ENABLED = true
|
||||
FROM = gitea@mydomain.com
|
||||
MAILER_TYPE = smtp
|
||||
SMTP_ADDR = mail.mydomain.com
|
||||
SMTP_PORT = 587
|
||||
IS_TLS_ENABLED = true
|
||||
USER = gitea@mydomain.com
|
||||
PASSWD = `password`
|
||||
```
|
||||
|
||||
重启 Gitea 以使配置更改生效。
|
||||
|
||||
要发送测试邮件以验证设置,请转到 Gitea > 站点管理 > 配置 > SMTP 邮件配置。
|
||||
|
||||
有关所有选项的完整列表,请查看[配置速查表](doc/administration/config-cheat-sheet.zh-cn.md)。
|
||||
|
||||
请注意:只有在使用 TLS 或 `HOST=localhost` 加密 SMTP 服务器通信时才支持身份验证。TLS 加密可以通过以下方式进行:
|
||||
|
||||
- 通过端口 587 的 STARTTLS(也称为 Opportunistic TLS)。初始连接是明文的,但如果服务器支持,则可以升级为 TLS。
|
||||
- 通过默认端口 465 的 SMTPS 连接。连接到服务器从一开始就使用 TLS。
|
||||
- 使用 `IS_TLS_ENABLED=true` 进行强制的 SMTPS 连接。(这两种方式都被称为 Implicit TLS)
|
||||
这是由于 Go 内部库对 STRIPTLS 攻击的保护机制。
|
||||
|
||||
请注意,自2018年起,[RFC8314](https://tools.ietf.org/html/rfc8314#section-3) 推荐使用 Implicit TLS。
|
||||
|
||||
### Gmail
|
||||
|
||||
以下配置应该适用于 Gmail 的 SMTP 服务器:
|
||||
|
||||
```ini
|
||||
[mailer]
|
||||
ENABLED = true
|
||||
HOST = smtp.gmail.com:465 ; 对于 Gitea >= 1.18.0,删除此行
|
||||
SMTP_ADDR = smtp.gmail.com
|
||||
SMTP_PORT = 465
|
||||
FROM = example.user@gmail.com
|
||||
USER = example.user
|
||||
PASSWD = `***`
|
||||
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"
|
||||
weight: 10
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /en-us/environment-variables
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
|
@@ -5,8 +5,6 @@ slug: "environment-variables"
|
||||
weight: 10
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /zh-cn/environment-variables
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
|
@@ -5,8 +5,6 @@ slug: "external-renderers"
|
||||
weight: 60
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /en-us/external-renderers
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
|
@@ -1,207 +0,0 @@
|
||||
---
|
||||
date: "2023-05-23T09:00:00+08:00"
|
||||
title: "外部渲染器"
|
||||
slug: "external-renderers"
|
||||
weight: 60
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /zh-cn/external-renderers
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
name: "外部渲染器"
|
||||
weight: 60
|
||||
identifier: "external-renderers"
|
||||
---
|
||||
|
||||
# 自定义文件渲染配置
|
||||
|
||||
**目录**
|
||||
|
||||
{{< toc >}}
|
||||
|
||||
Gitea 通过外部二进制文件支持自定义文件渲染(例如 Jupyter notebooks、asciidoc 等),只需要进行以下步骤:
|
||||
|
||||
- 安装外部二进制文件
|
||||
- 在您的 `app.ini` 文件中添加一些配置
|
||||
- 重新启动 Gitea 实例
|
||||
|
||||
此功能支持整个文件的渲染。如果您想要在 Markdown 中渲染代码块,您需要使用 JavaScript 进行一些操作。请参阅 [自定义 Gitea 配置]({{< relref "doc/administration/customizing-gitea.zh-cn.md" >}}) 页面上的一些示例。
|
||||
|
||||
## 安装外部二进制文件
|
||||
|
||||
为了通过外部二进制文件进行文件渲染,必须安装它们的关联软件包。
|
||||
如果您正在使用 Docker 镜像,则您的 `Dockerfile` 应该包含以下内容:
|
||||
|
||||
```docker
|
||||
FROM gitea/gitea:{{< version >}}
|
||||
[...]
|
||||
|
||||
COPY custom/app.ini /data/gitea/conf/app.ini
|
||||
[...]
|
||||
|
||||
RUN apk --no-cache add asciidoctor freetype freetype-dev gcc g++ libpng libffi-dev py-pip python3-dev py3-pip py3-pyzmq
|
||||
# 安装其他您需要的外部渲染器的软件包
|
||||
|
||||
RUN pip3 install --upgrade pip
|
||||
RUN pip3 install -U setuptools
|
||||
RUN pip3 install jupyter docutils
|
||||
# 在上面添加您需要安装的任何其他 Python 软件包
|
||||
```
|
||||
|
||||
## `app.ini` 文件配置
|
||||
|
||||
在您的自定义 `app.ini` 文件中为每个外部渲染器添加一个 `[markup.XXXXX]` 部分:
|
||||
|
||||
```ini
|
||||
[markup.asciidoc]
|
||||
ENABLED = true
|
||||
FILE_EXTENSIONS = .adoc,.asciidoc
|
||||
RENDER_COMMAND = "asciidoctor -s -a showtitle --out-file=- -"
|
||||
; 输入不是标准输入而是文件
|
||||
IS_INPUT_FILE = false
|
||||
|
||||
[markup.jupyter]
|
||||
ENABLED = true
|
||||
FILE_EXTENSIONS = .ipynb
|
||||
RENDER_COMMAND = "jupyter nbconvert --stdin --stdout --to html --template basic"
|
||||
IS_INPUT_FILE = false
|
||||
|
||||
[markup.restructuredtext]
|
||||
ENABLED = true
|
||||
FILE_EXTENSIONS = .rst
|
||||
RENDER_COMMAND = "timeout 30s pandoc +RTS -M512M -RTS -f rst"
|
||||
IS_INPUT_FILE = false
|
||||
```
|
||||
|
||||
如果您的外部标记语言依赖于在生成的 HTML 元素上的额外类和属性,您可能需要启用自定义的清理策略。Gitea 使用 [`bluemonday`](https://godoc.org/github.com/microcosm-cc/bluemonday) 包作为我们的 HTML 清理器。下面的示例可以用于支持从 [`pandoc`](https://pandoc.org/) 输出的服务器端 [KaTeX](https://katex.org/) 渲染结果。
|
||||
|
||||
```ini
|
||||
[markup.sanitizer.TeX]
|
||||
; Pandoc 渲染 TeX 段落为带有 "math" 类的 <span> 元素,根据上下文可能还带有 "inline" 或 "display" 类。
|
||||
; - 请注意,这与我们的 Markdown 解析器中内置的数学支持不同,后者使用 <code> 元素。
|
||||
ELEMENT = span
|
||||
ALLOW_ATTR = class
|
||||
REGEXP = ^\s*((math(\s+|$)|inline(\s+|$)|display(\s+|$)))+
|
||||
|
||||
[markup.markdown]
|
||||
ENABLED = true
|
||||
FILE_EXTENSIONS = .md,.markdown
|
||||
RENDER_COMMAND = pandoc -f markdown -t html --katex
|
||||
```
|
||||
|
||||
您必须在每个部分中定义 `ELEMENT` 和 `ALLOW_ATTR`。
|
||||
|
||||
要定义多个条目,请添加唯一的字母数字后缀(例如,`[markup.sanitizer.1]` 和 `[markup.sanitizer.something]`)。
|
||||
|
||||
要仅为特定的外部渲染器应用清理规则,它们必须使用渲染器名称,例如 `[markup.sanitizer.asciidoc.rule-1]`、`[markup.sanitizer.<renderer>.rule-1]`。
|
||||
|
||||
**注意**:如果规则在渲染器 ini 部分之前定义,或者名称与渲染器不匹配,它将应用于所有渲染器。
|
||||
|
||||
完成配置更改后,请重新启动 Gitea 以使更改生效。
|
||||
|
||||
**注意**:在 Gitea 1.12 之前,存在一个名为 `markup.sanitiser` 的单个部分,其中的键被重新定义为多个规则,但是,这种配置方法存在重大问题,需要通过多个部分进行配置。
|
||||
|
||||
### 示例:HTML
|
||||
|
||||
直接渲染 HTML 文件:
|
||||
|
||||
```ini
|
||||
[markup.html]
|
||||
ENABLED = true
|
||||
FILE_EXTENSIONS = .html,.htm
|
||||
RENDER_COMMAND = cat
|
||||
; 输入不是标准输入,而是文件
|
||||
IS_INPUT_FILE = true
|
||||
|
||||
[markup.sanitizer.html.1]
|
||||
ELEMENT = div
|
||||
ALLOW_ATTR = class
|
||||
|
||||
[markup.sanitizer.html.2]
|
||||
ELEMENT = a
|
||||
ALLOW_ATTR = class
|
||||
```
|
||||
|
||||
请注意:此示例中的配置将允许渲染 HTML 文件,并使用 `cat` 命令将文件内容输出为 HTML。此外,配置中的两个清理规则将允许 `<div>` 和 `<a>` 元素使用 `class` 属性。
|
||||
|
||||
在进行配置更改后,请重新启动 Gitea 以使更改生效。
|
||||
|
||||
### 示例:Office DOCX
|
||||
|
||||
使用 [`pandoc`](https://pandoc.org/) 显示 Office DOCX 文件:
|
||||
|
||||
```ini
|
||||
[markup.docx]
|
||||
ENABLED = true
|
||||
FILE_EXTENSIONS = .docx
|
||||
RENDER_COMMAND = "pandoc --from docx --to html --self-contained --template /path/to/basic.html"
|
||||
|
||||
[markup.sanitizer.docx.img]
|
||||
ALLOW_DATA_URI_IMAGES = true
|
||||
```
|
||||
|
||||
在此示例中,配置将允许显示 Office DOCX 文件,并使用 `pandoc` 命令将文件转换为 HTML 格式。同时,清理规则中的 `ALLOW_DATA_URI_IMAGES` 设置为 `true`,允许使用 Data URI 格式的图片。
|
||||
|
||||
模板文件的内容如下:
|
||||
|
||||
```
|
||||
$body$
|
||||
```
|
||||
|
||||
### 示例:Jupyter Notebook
|
||||
|
||||
使用 [`nbconvert`](https://github.com/jupyter/nbconvert) 显示 Jupyter Notebook 文件:
|
||||
|
||||
```ini
|
||||
[markup.jupyter]
|
||||
ENABLED = true
|
||||
FILE_EXTENSIONS = .ipynb
|
||||
RENDER_COMMAND = "jupyter-nbconvert --stdin --stdout --to html --template basic"
|
||||
|
||||
[markup.sanitizer.jupyter.img]
|
||||
ALLOW_DATA_URI_IMAGES = true
|
||||
```
|
||||
|
||||
在此示例中,配置将允许显示 Jupyter Notebook 文件,并使用 `nbconvert` 命令将文件转换为 HTML 格式。同样,清理规则中的 `ALLOW_DATA_URI_IMAGES` 设置为 `true`,允许使用 Data URI 格式的图片。
|
||||
|
||||
在进行配置更改后,请重新启动 Gitea 以使更改生效。
|
||||
|
||||
## 自定义 CSS
|
||||
|
||||
在 `.ini` 文件中,可以使用 `[markup.XXXXX]` 的格式指定外部渲染器,并且由外部渲染器生成的 HTML 将被包装在一个带有 `markup` 和 `XXXXX` 类的 `<div>` 中。`markup` 类提供了预定义的样式(如果 `XXXXX` 是 `markdown`,则使用 `markdown` 类)。否则,您可以使用这些类来针对渲染的 HTML 内容进行定制样式。
|
||||
|
||||
因此,您可以编写一些 CSS 样式:
|
||||
|
||||
```css
|
||||
.markup.XXXXX html {
|
||||
font-size: 100%;
|
||||
overflow-y: scroll;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
-ms-text-size-adjust: 100%;
|
||||
}
|
||||
|
||||
.markup.XXXXX body {
|
||||
color: #444;
|
||||
font-family: Georgia, Palatino, 'Palatino Linotype', Times, 'Times New Roman', serif;
|
||||
font-size: 12px;
|
||||
line-height: 1.7;
|
||||
padding: 1em;
|
||||
margin: auto;
|
||||
max-width: 42em;
|
||||
background: #fefefe;
|
||||
}
|
||||
|
||||
.markup.XXXXX p {
|
||||
color: orangered;
|
||||
}
|
||||
```
|
||||
|
||||
将您的样式表添加到自定义目录中,例如 `custom/public/css/my-style-XXXXX.css`,并使用自定义的头文件 `custom/templates/custom/header.tmpl` 进行导入:
|
||||
|
||||
```html
|
||||
<link rel="stylesheet" href="{{AppSubUrl}}/assets/css/my-style-XXXXX.css" />
|
||||
```
|
||||
|
||||
通过以上步骤,您可以将自定义的 CSS 样式应用到特定的外部渲染器,使其具有所需的样式效果。
|
@@ -1,12 +1,10 @@
|
||||
---
|
||||
date: "2018-05-11T11:00:00+02:00"
|
||||
title: "Fail2ban Setup "
|
||||
title: "Usage: Setup fail2ban"
|
||||
slug: "fail2ban-setup"
|
||||
weight: 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"
|
||||
weight: 16
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /zh-cn/fail2ban-setup
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
|
@@ -1,12 +1,10 @@
|
||||
---
|
||||
date: "2019-10-06T08:00:00+05:00"
|
||||
title: "Git LFS setup"
|
||||
title: "Usage: Git LFS setup"
|
||||
slug: "git-lfs-setup"
|
||||
weight: 12
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /en-us/git-lfs-setup
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
|
@@ -1,32 +0,0 @@
|
||||
---
|
||||
date: "2023-05-23T09:00:00+08:00"
|
||||
title: "Git LFS 设置"
|
||||
slug: "git-lfs-setup"
|
||||
weight: 12
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /zh-cn/git-lfs-setup
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
name: "Git LFS 设置"
|
||||
weight: 12
|
||||
identifier: "git-lfs-setup"
|
||||
---
|
||||
|
||||
# 配置 Git 大文件存储(Large File Storage,LFS)
|
||||
|
||||
要使用 Gitea 内置的 LFS 支持,您需要更新 `app.ini` 文件:
|
||||
|
||||
```ini
|
||||
[server]
|
||||
; 启用 git-lfs 支持。true 或 false,默认为 false。
|
||||
LFS_START_SERVER = true
|
||||
|
||||
[lfs]
|
||||
; 存放 LFS 文件的路径,默认为 data/lfs。
|
||||
PATH = /home/gitea/data/lfs
|
||||
```
|
||||
|
||||
**注意**:LFS 服务器支持需要服务器上安装 Git v2.1.2 以上版本。
|
@@ -1,12 +1,10 @@
|
||||
---
|
||||
date: "2018-06-02T11:00:00+02:00"
|
||||
title: "HTTPS setup"
|
||||
title: "Usage: HTTPS setup"
|
||||
slug: "https-setup"
|
||||
weight: 12
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /en-us/https-setup
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
|
@@ -1,101 +0,0 @@
|
||||
---
|
||||
date: "2023-04-09T11:00:00+02:00"
|
||||
title: "HTTPS配置"
|
||||
slug: "https-setup"
|
||||
weight: 12
|
||||
toc: false
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
name: "HTTPS setup"
|
||||
weight: 12
|
||||
identifier: "https-setup"
|
||||
---
|
||||
|
||||
# HTTPS setup to encrypt connections to Gitea
|
||||
|
||||
**Table of Contents**
|
||||
|
||||
{{< toc >}}
|
||||
|
||||
## 使用内置服务器
|
||||
|
||||
在启用HTTPS之前,确保您拥有有效的SSL/TLS证书。
|
||||
建议在测试和评估情况下使用自签名证书,请运行 `gitea cert --host [HOST]` 以生成自签名证书
|
||||
|
||||
如果您在服务器上使用阿帕奇(Apache)或Nginx,建议参考 [反向代理指南]({{< relref "doc/administration/reverse-proxies.zh-cn.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,295 +0,0 @@
|
||||
---
|
||||
date: "2019-04-02T17:06:00+01:00"
|
||||
title: "Logging Configuration"
|
||||
slug: "logging-config"
|
||||
weight: 40
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /en-us/logging-configuration
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
name: "Logging Configuration"
|
||||
weight: 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.
|
||||
|
||||
**Table of Contents**
|
||||
|
||||
{{< toc >}}
|
||||
|
||||
## Collecting Logs for Help
|
||||
|
||||
To collect logs for help and issue report, see [Support Options]({{< relref "doc/help/support.en-us.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`.
|
@@ -1,276 +0,0 @@
|
||||
---
|
||||
date: "2023-05-23T09:00:00+08:00"
|
||||
title: "日志配置"
|
||||
slug: "logging-config"
|
||||
weight: 40
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /zh-cn/logging-configuration
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
name: "日志配置"
|
||||
weight: 40
|
||||
identifier: "logging-config"
|
||||
---
|
||||
|
||||
# 日志配置
|
||||
|
||||
Gitea 的日志配置主要由以下三种类型的组件组成:
|
||||
|
||||
- `[log]` 部分用于一般配置
|
||||
- `[log.<mode-name>]` 部分用于配置不同的日志输出方式,也称为 "writer mode",模式名称同时也作为 "writer name"
|
||||
- `[log]` 部分还可以包含遵循 `logger.<logger-name>.<CONFIG-KEY>` 模式的子日志记录器的配置
|
||||
|
||||
默认情况下,已经有一个完全功能的日志输出,因此不需要重新定义。
|
||||
|
||||
**目录**
|
||||
|
||||
{{< toc >}}
|
||||
|
||||
## 收集日志以获取帮助
|
||||
|
||||
要收集日志以获取帮助和报告问题,请参阅 [需要帮助]({{< relref "doc/help/support.zh-cn.md" >}})。
|
||||
|
||||
## `[log]` 部分
|
||||
|
||||
在 Gitea 中,日志设施的配置在 `[log]` 部分及其子部分。
|
||||
|
||||
在顶层的 `[log]` 部分,可以放置以下配置项:
|
||||
|
||||
- `ROOT_PATH`:(默认值:**%(GITEA_WORK_DIR)/log**):日志文件的基本路径。
|
||||
- `MODE`:(默认值:**console**):要用于默认日志记录器的日志输出列表。
|
||||
- `LEVEL`:(默认值:**Info**):要持久化的最严重的日志事件,不区分大小写。可能的值为:`Trace`、`Debug`、`Info`、`Warn`、`Error`、`Fatal`。
|
||||
- `STACKTRACE_LEVEL`:(默认值:**None**):对于此类及更严重的事件,将在记录时打印堆栈跟踪。
|
||||
|
||||
它还可以包含以下子日志记录器:
|
||||
|
||||
- `logger.router.MODE`:(默认值:**,**):用于路由器日志记录器的日志输出列表。
|
||||
- `logger.access.MODE`:(默认值:**\<empty\>**):用于访问日志记录器的日志输出列表。默认情况下,访问日志记录器被禁用。
|
||||
- `logger.xorm.MODE`:(默认值:**,**):用于 XORM 日志记录器的日志输出列表。
|
||||
|
||||
将子日志记录器的模式设置为逗号(`,`)表示使用默认的全局 `MODE`。
|
||||
|
||||
## 快速示例
|
||||
|
||||
### 默认(空)配置
|
||||
|
||||
空配置等同于默认配置:
|
||||
|
||||
```ini
|
||||
[log]
|
||||
ROOT_PATH = %(GITEA_WORK_DIR)/log
|
||||
MODE = console
|
||||
LEVEL = Info
|
||||
STACKTRACE_LEVEL = None
|
||||
logger.router.MODE = ,
|
||||
logger.xorm.MODE = ,
|
||||
logger.access.MODE =
|
||||
|
||||
; 这是“控制台”模式的配置选项(由上面的 MODE=console 使用)
|
||||
[log.console]
|
||||
MODE = console
|
||||
FLAGS = stdflags
|
||||
PREFIX =
|
||||
COLORIZE = true
|
||||
```
|
||||
|
||||
这等同于将所有日志发送到控制台,并将默认的 Golang 日志也发送到控制台日志中。
|
||||
|
||||
这只是一个示例,默认情况下不需要将其写入配置文件中。
|
||||
|
||||
### 禁用路由日志并将一些访问日志记录到文件中
|
||||
|
||||
禁用路由日志,将访问日志(>=Warn)记录到 `access.log` 中:
|
||||
|
||||
```ini
|
||||
[log]
|
||||
logger.router.MODE =
|
||||
logger.access.MODE = access-file
|
||||
|
||||
[log.access-file]
|
||||
MODE = file
|
||||
LEVEL = Warn
|
||||
FILE_NAME = access.log
|
||||
```
|
||||
|
||||
### 为不同的模式设置不同的日志级别
|
||||
|
||||
将默认日志(>=Warn)记录到 `gitea.log` 中,将错误日志记录到 `file-error.log` 中:
|
||||
|
||||
```ini
|
||||
[log]
|
||||
LEVEL = Warn
|
||||
MODE = file, file-error
|
||||
|
||||
; 默认情况下,"file" 模式会将日志记录到 %(log.ROOT_PATH)/gitea.log,因此我们不需要设置它
|
||||
; [log.file]
|
||||
|
||||
[log.file-error]
|
||||
LEVEL = Error
|
||||
FILE_NAME = file-error.log
|
||||
```
|
||||
|
||||
## 日志输出(模式和写入器)
|
||||
|
||||
Gitea 提供以下日志写入器:
|
||||
|
||||
- `console` - 输出日志到 `stdout`(或 `stderr`,如果已在配置中设置)
|
||||
- `file` - 输出日志到文件
|
||||
- `conn` - 输出日志到套接字(网络或 Unix 套接字)
|
||||
|
||||
### 公共配置
|
||||
|
||||
某些配置适用于所有日志输出模式:
|
||||
|
||||
- `MODE` 是日志输出写入器的模式。它将默认为 ini 部分的模式名称。因此,`[log.console]` 将默认为 `MODE = console`。
|
||||
- `LEVEL` 是此输出将记录的最低日志级别。
|
||||
- `STACKTRACE_LEVEL` 是此输出将打印堆栈跟踪的最低日志级别。
|
||||
- `COLORIZE` 对于 `console`,默认为 `true`,否则默认为 `false`。
|
||||
|
||||
#### `EXPRESSION`
|
||||
|
||||
`EXPRESSION` 表示日志事件必须匹配才能被输出写入器记录的正则表达式。
|
||||
日志消息(去除颜色)或 `longfilename:linenumber:functionname` 必须匹配其中之一。
|
||||
注意:整个消息或字符串不需要完全匹配。
|
||||
|
||||
请注意,此表达式将在写入器的 goroutine 中运行,而不是在日志事件的 goroutine 中运行。
|
||||
|
||||
#### `FLAGS`
|
||||
|
||||
`FLAGS` 表示在每条消息之前打印的前置日志上下文信息。
|
||||
它是一个逗号分隔的字符串集。值的顺序无关紧要。
|
||||
|
||||
默认值为 `stdflags`(= `date,time,medfile,shortfuncname,levelinitial`)。
|
||||
|
||||
可能的值为:
|
||||
|
||||
- `none` 或 `,` - 无标志。
|
||||
- `date` - 当地时区的日期:`2009/01/23`。
|
||||
- `time` - 当地时区的时间:`01:23:23`。
|
||||
- `microseconds` - 微秒精度:`01:23:23.123123`。假定有时间。
|
||||
- `longfile` - 完整的文件名和行号:`/a/b/c/d.go:23`。
|
||||
- `shortfile` - 文件名的最后一个部分和行号:`d.go:23`。
|
||||
- `funcname` - 调用者的函数名:`runtime.Caller()`。
|
||||
- `shortfuncname` - 函数名的最后一部分。覆盖 `funcname`。
|
||||
- `utc` - 如果设置了日期或时间,则使用 UTC 而不是本地时区。
|
||||
- `levelinitial` - 提供的级别的初始字符,放在方括号内,例如 `[I]` 表示 info。
|
||||
- `level` - 在方括号内的级别,例如 `[INFO]`。
|
||||
- `gopid` - 上下文的 Goroutine-PID。
|
||||
- `medfile` - 文件名的最后 20 个字符 - 相当于 `shortfile,longfile`。
|
||||
- `stdflags` - 相当于 `date,time,medfile,shortfuncname,levelinitial`。
|
||||
|
||||
### Console 模式
|
||||
|
||||
在此模式下,日志记录器将将日志消息转发到 Gitea 进程附加的 stdout 和 stderr 流。
|
||||
|
||||
对于 console 模式的日志记录器,如果不在 Windows 上,或者 Windows 终端可以设置为 ANSI 模式,或者是 cygwin 或 Msys 管道,则 `COLORIZE` 默认为 `true`。
|
||||
|
||||
设置:
|
||||
|
||||
- `STDERR`:**false**:日志记录器是否应将日志打印到 `stderr` 而不是 `stdout`。
|
||||
|
||||
### File 模式
|
||||
|
||||
在此模式下,日志记录器将将日志消息保存到文件中。
|
||||
|
||||
设置:
|
||||
|
||||
- `FILE_NAME`:要将日志事件写入的文件,相对于 `ROOT_PATH`,默认为 `%(ROOT_PATH)/gitea.log`。异常情况:访问日志默认为 `%(ROOT_PATH)/access.log`。
|
||||
- `MAX_SIZE_SHIFT`:**28**:单个文件的最大大小位移。28 表示 256Mb。详细信息见下文。
|
||||
- `LOG_ROTATE` **true**:是否轮转日志文件。
|
||||
- `DAILY_ROTATE`:**true**:是否每天旋转日志。
|
||||
- `MAX_DAYS`:**7**:在此天数之后删除旋转的日志文件。
|
||||
- `COMPRESS`:**true**:默认情况下是否使用 gzip 压缩旧的日志文件。
|
||||
- `COMPRESSION_LEVEL`:**-1**:压缩级别。详细信息见下文。
|
||||
|
||||
`MAX_SIZE_SHIFT` 通过将给定次数左移 1 (`1 << x`) 来定义文件的最大大小。
|
||||
在 v1.17.3 版本时的确切行为可以在[这里](https://github.com/go-gitea/gitea/blob/v1.17.3/modules/setting/log.go#L185)中查看。
|
||||
|
||||
`COMPRESSION_LEVEL` 的有用值范围从 1 到(包括)9,其中较高的数字表示更好的压缩。
|
||||
请注意,更好的压缩可能会带来更高的资源使用。
|
||||
必须在前面加上 `-` 符号。
|
||||
|
||||
### Conn 模式
|
||||
|
||||
在此模式下,日志记录器将通过网络套接字发送日志消息。
|
||||
|
||||
设置:
|
||||
|
||||
- `ADDR`:**:7020**:设置要连接的地址。
|
||||
- `PROTOCOL`:**tcp**:设置协议,可以是 "tcp"、"unix" 或 "udp"。
|
||||
- `RECONNECT`:**false**:在连接丢失时尝试重新连接。
|
||||
- `RECONNECT_ON_MSG`:**false**:为每条消息重新连接主机。
|
||||
|
||||
### "Router" 日志记录器
|
||||
|
||||
当 Gitea 的路由处理程序工作时,Router 日志记录器记录以下消息类型:
|
||||
|
||||
- `started` 消息将以 TRACE 级别记录
|
||||
- `polling`/`completed` 路由将以 INFO 级别记录。异常情况:"/assets" 静态资源请求也会以 TRACE 级别记录。
|
||||
- `slow` 路由将以 WARN 级别记录
|
||||
- `failed` 路由将以 WARN 级别记录
|
||||
|
||||
### "XORM" 日志记录器
|
||||
|
||||
为了使 XORM 输出 SQL 日志,还应将 `[database]` 部分中的 `LOG_SQL` 设置为 `true`。
|
||||
|
||||
### "Access" 日志记录器
|
||||
|
||||
"Access" 日志记录器是自 Gitea 1.9 版本以来的新日志记录器。它提供了符合 NCSA Common Log 标准的日志格式。虽然它具有高度可配置性,但在更改其模板时应谨慎。此日志记录器的主要好处是,Gitea 现在可以使用标准日志格式记录访问日志,因此可以使用标准工具进行分析。
|
||||
|
||||
您可以通过使用 `logger.access.MODE = ...` 来启用此日志记录器。
|
||||
|
||||
如果需要,可以通过更改 `ACCESS_LOG_TEMPLATE` 的值来更改 "Access" 日志记录器的格式。
|
||||
|
||||
请注意,访问日志记录器将以 `INFO` 级别记录,将此日志记录器的 `LEVEL` 设置为 `WARN` 或更高级别将导致不记录访问日志。
|
||||
|
||||
#### ACCESS_LOG_TEMPLATE
|
||||
|
||||
此值表示一个 Go 模板。其默认值为
|
||||
|
||||
```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}}"`
|
||||
```
|
||||
|
||||
模板接收以下选项:
|
||||
|
||||
- `Ctx` 是 `context.Context`
|
||||
- `Identity` 是 `SignedUserName`,如果用户未登录,则为 "-"
|
||||
- `Start` 是请求的开始时间
|
||||
- `ResponseWriter` 是 `http.ResponseWriter`
|
||||
|
||||
更改此模板时必须小心,因为它在标准的 panic 恢复陷阱之外运行。此模板应该尽可能简单,因为它会为每个请求运行一次。
|
||||
|
||||
## 释放和重新打开、暂停和恢复日志记录
|
||||
|
||||
如果您在 Unix 上运行,您可能希望释放和重新打开日志以使用 `logrotate` 或其他工具。
|
||||
可以通过向运行中的进程发送 `SIGUSR1` 信号或运行 `gitea manager logging release-and-reopen` 命令来强制 Gitea 释放并重新打开其日志文件和连接。
|
||||
|
||||
或者,您可能希望暂停和恢复日志记录 - 可以通过使用 `gitea manager logging pause` 和 `gitea manager logging resume` 命令来实现。请注意,当日志记录暂停时,低于 INFO 级别的日志事件将不会存储,并且只会存储有限数量的事件。在暂停时,日志记录可能会阻塞,尽管是暂时性的,但会大大减慢 Gitea 的运行速度,因此建议仅暂停很短的时间。
|
||||
|
||||
### 在 Gitea 运行时添加和删除日志记录
|
||||
|
||||
可以使用 `gitea manager logging add` 和 `remove` 子命令在 Gitea 运行时添加和删除日志记录。
|
||||
此功能只能调整正在运行的日志系统,不能用于启动未初始化的访问或路由日志记录器。如果您希望启动这些系统,建议调整 app.ini 并(优雅地)重新启动 Gitea 服务。
|
||||
|
||||
这些命令的主要目的是在运行中的系统上轻松添加临时日志记录器,以便调查问题,因为重新启动可能会导致问题消失。
|
||||
|
||||
## 使用 `logrotate` 而不是内置的日志轮转
|
||||
|
||||
Gitea 包含内置的日志轮转功能,对于大多数部署来说应该已经足够了。但是,如果您想使用 `logrotate` 工具:
|
||||
|
||||
- 在 `app.ini` 中将 `LOG_ROTATE` 设置为 `false`,禁用内置的日志轮转。
|
||||
- 安装 `logrotate`。
|
||||
- 根据部署要求配置 `logrotate`,有关配置语法细节,请参阅 `man 8 logrotate`。
|
||||
在 `postrotate/endscript` 块中通过 `kill -USR1` 或 `kill -10` 向 `gitea` 进程本身发送 `USR1` 信号,
|
||||
或者运行 `gitea manager logging release-and-reopen`(使用适当的环境设置)。
|
||||
确保配置适用于由 Gitea 日志记录器生成的所有文件,如上述部分所述。
|
||||
- 始终使用 `logrotate /etc/logrotate.conf --debug` 来测试您的配置。
|
||||
- 如果您正在使用 Docker 并从容器外部运行,您可以使用
|
||||
`docker exec -u $OS_USER $CONTAINER_NAME sh -c 'gitea manager logging release-and-reopen'`
|
||||
或 `docker exec $CONTAINER_NAME sh -c '/bin/s6-svc -1 /etc/s6/gitea/'`,或直接向 Gitea 进程本身发送 `USR1` 信号。
|
||||
|
||||
下一个 `logrotate` 作业将包括您的配置,因此不需要重新启动。
|
||||
您还可以立即使用 `logrotate /etc/logrotate.conf --force` 重新加载 `logrotate`。
|
522
docs/content/doc/administration/logging-documentation.en-us.md
Normal file
522
docs/content/doc/administration/logging-documentation.en-us.md
Normal file
@@ -0,0 +1,522 @@
|
||||
---
|
||||
date: "2019-04-02T17:06:00+01:00"
|
||||
title: "Advanced: Logging Configuration"
|
||||
slug: "logging-configuration"
|
||||
weight: 40
|
||||
toc: false
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
name: "Logging Configuration"
|
||||
weight: 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.
|
||||
|
||||
**Table of Contents**
|
||||
|
||||
{{< toc >}}
|
||||
|
||||
## Collecting Logs for Help
|
||||
|
||||
To collect logs for help and issue report, see [Support Options]({{< relref "doc/help/seek-help.en-us.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