@@ -1,6 +1,6 @@ | |||
{ | |||
"name": "Gitea DevContainer", | |||
"image": "mcr.microsoft.com/devcontainers/go:1.21-bullseye", | |||
"image": "mcr.microsoft.com/devcontainers/go:1.22-bullseye", | |||
"features": { | |||
// installs nodejs into container | |||
"ghcr.io/devcontainers/features/node:1": { | |||
@@ -8,7 +8,9 @@ | |||
}, | |||
"ghcr.io/devcontainers/features/git-lfs:1.1.0": {}, | |||
"ghcr.io/devcontainers-contrib/features/poetry:2": {}, | |||
"ghcr.io/devcontainers/features/python:1": {} | |||
"ghcr.io/devcontainers/features/python:1": { | |||
"version": "3.12" | |||
} | |||
}, | |||
"customizations": { | |||
"vscode": { |
@@ -62,7 +62,6 @@ cpu.out | |||
/data | |||
/indexers | |||
/log | |||
/public/img/avatar | |||
/tests/integration/gitea-integration-* | |||
/tests/integration/indexers-* | |||
/tests/e2e/gitea-e2e-* | |||
@@ -78,6 +77,7 @@ cpu.out | |||
/public/assets/js | |||
/public/assets/css | |||
/public/assets/fonts | |||
/public/assets/img/avatar | |||
/public/assets/img/webpack | |||
/vendor | |||
/web_src/fomantic/node_modules |
@@ -12,6 +12,7 @@ plugins: | |||
- "@eslint-community/eslint-plugin-eslint-comments" | |||
- "@stylistic/eslint-plugin-js" | |||
- eslint-plugin-array-func | |||
- eslint-plugin-github | |||
- eslint-plugin-i | |||
- eslint-plugin-jquery | |||
- eslint-plugin-no-jquery | |||
@@ -41,10 +42,6 @@ overrides: | |||
worker: true | |||
rules: | |||
no-restricted-globals: [2, addEventListener, blur, close, closed, confirm, defaultStatus, defaultstatus, error, event, external, find, focus, frameElement, frames, history, innerHeight, innerWidth, isFinite, isNaN, length, locationbar, menubar, moveBy, moveTo, name, onblur, onerror, onfocus, onload, onresize, onunload, open, opener, opera, outerHeight, outerWidth, pageXOffset, pageYOffset, parent, print, removeEventListener, resizeBy, resizeTo, screen, screenLeft, screenTop, screenX, screenY, scroll, scrollbars, scrollBy, scrollTo, scrollX, scrollY, status, statusbar, stop, toolbar, top] | |||
- files: ["build/generate-images.js"] | |||
rules: | |||
i/no-unresolved: [0] | |||
i/no-extraneous-dependencies: [0] | |||
- files: ["*.config.*"] | |||
rules: | |||
i/no-unused-modules: [0] | |||
@@ -209,6 +206,29 @@ rules: | |||
func-names: [0] | |||
func-style: [0] | |||
getter-return: [2] | |||
github/a11y-aria-label-is-well-formatted: [0] | |||
github/a11y-no-title-attribute: [0] | |||
github/a11y-no-visually-hidden-interactive-element: [0] | |||
github/a11y-role-supports-aria-props: [0] | |||
github/a11y-svg-has-accessible-name: [0] | |||
github/array-foreach: [0] | |||
github/async-currenttarget: [2] | |||
github/async-preventdefault: [2] | |||
github/authenticity-token: [0] | |||
github/get-attribute: [0] | |||
github/js-class-name: [0] | |||
github/no-blur: [0] | |||
github/no-d-none: [0] | |||
github/no-dataset: [2] | |||
github/no-dynamic-script-tag: [2] | |||
github/no-implicit-buggy-globals: [2] | |||
github/no-inner-html: [0] | |||
github/no-innerText: [2] | |||
github/no-then: [2] | |||
github/no-useless-passive: [2] | |||
github/prefer-observers: [2] | |||
github/require-passive-events: [2] | |||
github/unescaped-html-literal: [0] | |||
grouped-accessor-pairs: [2] | |||
guard-for-in: [0] | |||
id-blacklist: [0] | |||
@@ -259,7 +279,7 @@ rules: | |||
i/unambiguous: [0] | |||
init-declarations: [0] | |||
jquery/no-ajax-events: [2] | |||
jquery/no-ajax: [0] | |||
jquery/no-ajax: [2] | |||
jquery/no-animate: [2] | |||
jquery/no-attr: [0] | |||
jquery/no-bind: [2] | |||
@@ -272,7 +292,7 @@ rules: | |||
jquery/no-delegate: [2] | |||
jquery/no-each: [0] | |||
jquery/no-extend: [2] | |||
jquery/no-fade: [0] | |||
jquery/no-fade: [2] | |||
jquery/no-filter: [0] | |||
jquery/no-find: [0] | |||
jquery/no-global-eval: [2] | |||
@@ -285,13 +305,13 @@ rules: | |||
jquery/no-is-function: [2] | |||
jquery/no-is: [0] | |||
jquery/no-load: [2] | |||
jquery/no-map: [0] | |||
jquery/no-map: [2] | |||
jquery/no-merge: [2] | |||
jquery/no-param: [2] | |||
jquery/no-parent: [0] | |||
jquery/no-parents: [0] | |||
jquery/no-parse-html: [2] | |||
jquery/no-prop: [0] | |||
jquery/no-prop: [2] | |||
jquery/no-proxy: [2] | |||
jquery/no-ready: [2] | |||
jquery/no-serialize: [2] | |||
@@ -372,11 +392,11 @@ rules: | |||
no-irregular-whitespace: [2] | |||
no-iterator: [2] | |||
no-jquery/no-ajax-events: [2] | |||
no-jquery/no-ajax: [0] | |||
no-jquery/no-ajax: [2] | |||
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-append-html: [2] | |||
no-jquery/no-attr: [0] | |||
no-jquery/no-bind: [2] | |||
no-jquery/no-box-model: [2] | |||
@@ -427,7 +447,7 @@ rules: | |||
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-map: [2] | |||
no-jquery/no-merge: [2] | |||
no-jquery/no-node-name: [2] | |||
no-jquery/no-noop: [2] | |||
@@ -442,7 +462,7 @@ rules: | |||
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-prop: [2] | |||
no-jquery/no-proxy: [2] | |||
no-jquery/no-ready-shorthand: [2] | |||
no-jquery/no-ready: [2] | |||
@@ -463,7 +483,7 @@ rules: | |||
no-jquery/no-visibility: [2] | |||
no-jquery/no-when: [2] | |||
no-jquery/no-wrap: [2] | |||
no-jquery/variable-pattern: [0] | |||
no-jquery/variable-pattern: [2] | |||
no-label-var: [2] | |||
no-labels: [0] # handled by no-restricted-syntax | |||
no-lone-blocks: [2] | |||
@@ -558,7 +578,6 @@ rules: | |||
prefer-rest-params: [2] | |||
prefer-spread: [2] | |||
prefer-template: [2] | |||
quotes: [2, single, {avoidEscape: true, allowTemplateLiterals: true}] | |||
radix: [2, as-needed] | |||
regexp/confusing-quantifier: [2] | |||
regexp/control-character-escape: [2] | |||
@@ -723,6 +742,7 @@ rules: | |||
unicorn/no-this-assignment: [2] | |||
unicorn/no-typeof-undefined: [2] | |||
unicorn/no-unnecessary-await: [2] | |||
unicorn/no-unnecessary-polyfills: [2] | |||
unicorn/no-unreadable-array-destructuring: [0] | |||
unicorn/no-unreadable-iife: [2] | |||
unicorn/no-unused-properties: [2] | |||
@@ -810,7 +830,7 @@ rules: | |||
wc/no-constructor-params: [2] | |||
wc/no-constructor: [2] | |||
wc/no-customized-built-in-elements: [2] | |||
wc/no-exports-with-element: [2] | |||
wc/no-exports-with-element: [0] | |||
wc/no-invalid-element-name: [2] | |||
wc/no-invalid-extends: [2] | |||
wc/no-method-prefixed-with-on: [2] |
@@ -1,2 +1 @@ | |||
open_collective: gitea | |||
custom: https://www.bountysource.com/teams/gitea |
@@ -1,36 +1,84 @@ | |||
modifies/docs: | |||
- "**/*.md" | |||
- "docs/**" | |||
- changed-files: | |||
- any-glob-to-any-file: | |||
- "**/*.md" | |||
- "docs/**" | |||
modifies/frontend: | |||
- "web_src/**/*" | |||
- changed-files: | |||
- any-glob-to-any-file: | |||
- "web_src/**" | |||
- "tailwind.config.js" | |||
- "webpack.config.js" | |||
modifies/templates: | |||
- all: ["templates/**", "!templates/swagger/v1_json.tmpl"] | |||
- changed-files: | |||
- all-globs-to-any-file: | |||
- "templates/**" | |||
- "!templates/swagger/v1_json.tmpl" | |||
modifies/api: | |||
- "routers/api/**" | |||
- "templates/swagger/v1_json.tmpl" | |||
- changed-files: | |||
- any-glob-to-any-file: | |||
- "routers/api/**" | |||
- "templates/swagger/v1_json.tmpl" | |||
modifies/cli: | |||
- "cmd/**" | |||
- changed-files: | |||
- any-glob-to-any-file: | |||
- "cmd/**" | |||
modifies/translation: | |||
- "options/locale/*.ini" | |||
- changed-files: | |||
- any-glob-to-any-file: | |||
- "options/locale/*.ini" | |||
modifies/migrations: | |||
- "models/migrations/**/*" | |||
- changed-files: | |||
- any-glob-to-any-file: | |||
- "models/migrations/**" | |||
modifies/internal: | |||
- "Makefile" | |||
- "Dockerfile" | |||
- "Dockerfile.rootless" | |||
- "docker/**" | |||
- "webpack.config.js" | |||
- ".eslintrc.yaml" | |||
- ".golangci.yml" | |||
- ".markdownlint.yaml" | |||
- ".spectral.yaml" | |||
- ".stylelintrc.yaml" | |||
- ".yamllint.yaml" | |||
- ".github/**" | |||
- changed-files: | |||
- any-glob-to-any-file: | |||
- ".air.toml" | |||
- "Makefile" | |||
- "Dockerfile" | |||
- "Dockerfile.rootless" | |||
- ".dockerignore" | |||
- "docker/**" | |||
- ".editorconfig" | |||
- ".eslintrc.yaml" | |||
- ".golangci.yml" | |||
- ".gitpod.yml" | |||
- ".markdownlint.yaml" | |||
- ".spectral.yaml" | |||
- ".stylelintrc.yaml" | |||
- ".yamllint.yaml" | |||
- ".github/**" | |||
- ".gitea/" | |||
- ".devcontainer/**" | |||
- "build.go" | |||
- "build/**" | |||
- "contrib/**" | |||
modifies/dependencies: | |||
- changed-files: | |||
- any-glob-to-any-file: | |||
- "package.json" | |||
- "package-lock.json" | |||
- "pyproject.toml" | |||
- "poetry.lock" | |||
- "go.mod" | |||
- "go.sum" | |||
modifies/go: | |||
- changed-files: | |||
- any-glob-to-any-file: | |||
- "**/*.go" | |||
modifies/js: | |||
- changed-files: | |||
- any-glob-to-any-file: | |||
- "**/*.js" | |||
- "**/*.vue" |
@@ -19,4 +19,5 @@ jobs: | |||
steps: | |||
- uses: dessant/lock-threads@v5 | |||
with: | |||
issue-inactive-days: 45 | |||
issue-inactive-days: 10 | |||
pr-inactive-days: 7 |
@@ -35,7 +35,7 @@ jobs: | |||
yaml: ${{ steps.changes.outputs.yaml }} | |||
steps: | |||
- uses: actions/checkout@v4 | |||
- uses: dorny/paths-filter@v2 | |||
- uses: dorny/paths-filter@v3 | |||
id: changes | |||
with: | |||
filters: | | |||
@@ -48,6 +48,7 @@ jobs: | |||
- "Makefile" | |||
- ".golangci.yml" | |||
- ".editorconfig" | |||
- "options/locale/locale_en-US.ini" | |||
frontend: | |||
- "**/*.js" |
@@ -32,9 +32,9 @@ jobs: | |||
runs-on: ubuntu-latest | |||
steps: | |||
- uses: actions/checkout@v4 | |||
- uses: actions/setup-python@v4 | |||
- uses: actions/setup-python@v5 | |||
with: | |||
python-version: "3.11" | |||
python-version: "3.12" | |||
- run: pip install poetry | |||
- run: make deps-py | |||
- run: make lint-templates | |||
@@ -45,9 +45,9 @@ jobs: | |||
runs-on: ubuntu-latest | |||
steps: | |||
- uses: actions/checkout@v4 | |||
- uses: actions/setup-python@v4 | |||
- uses: actions/setup-python@v5 | |||
with: | |||
python-version: "3.11" | |||
python-version: "3.12" | |||
- run: pip install poetry | |||
- run: make deps-py | |||
- run: make lint-yaml | |||
@@ -64,6 +64,18 @@ jobs: | |||
- run: make deps-frontend | |||
- run: make lint-swagger | |||
lint-spell: | |||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.frontend == 'true' || needs.files-changed.outputs.actions == 'true' || needs.files-changed.outputs.docs == 'true' || needs.files-changed.outputs.templates == 'true' | |||
needs: files-changed | |||
runs-on: ubuntu-latest | |||
steps: | |||
- uses: actions/checkout@v4 | |||
- uses: actions/setup-go@v5 | |||
with: | |||
go-version-file: go.mod | |||
check-latest: true | |||
- run: make lint-spell | |||
lint-go-windows: | |||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true' | |||
needs: files-changed |
@@ -49,7 +49,10 @@ jobs: | |||
- run: make backend | |||
env: | |||
TAGS: bindata | |||
- run: make test-pgsql-migration test-pgsql | |||
- name: run migration tests | |||
run: make test-pgsql-migration | |||
- name: run tests | |||
run: make test-pgsql | |||
timeout-minutes: 50 | |||
env: | |||
TAGS: bindata gogit | |||
@@ -72,7 +75,10 @@ jobs: | |||
- run: make backend | |||
env: | |||
TAGS: bindata gogit sqlite sqlite_unlock_notify | |||
- run: make test-sqlite-migration test-sqlite | |||
- name: run migration tests | |||
run: make test-sqlite-migration | |||
- name: run tests | |||
run: make test-sqlite | |||
timeout-minutes: 50 | |||
env: | |||
TAGS: bindata gogit sqlite sqlite_unlock_notify | |||
@@ -175,8 +181,10 @@ jobs: | |||
- run: make backend | |||
env: | |||
TAGS: bindata | |||
- name: run migration tests | |||
run: make test-mysql-migration | |||
- name: run tests | |||
run: make test-mysql-migration integration-test-coverage | |||
run: make integration-test-coverage | |||
env: | |||
TAGS: bindata | |||
RACE_ENABLED: true | |||
@@ -208,7 +216,9 @@ jobs: | |||
- run: make backend | |||
env: | |||
TAGS: bindata | |||
- run: make test-mssql-migration test-mssql | |||
- run: make test-mssql-migration | |||
- name: run tests | |||
run: make test-mssql | |||
timeout-minutes: 50 | |||
env: | |||
TAGS: bindata |
@@ -9,12 +9,12 @@ concurrency: | |||
cancel-in-progress: true | |||
jobs: | |||
label: | |||
labeler: | |||
runs-on: ubuntu-latest | |||
permissions: | |||
contents: read | |||
pull-requests: write | |||
steps: | |||
- uses: actions/labeler@v4 | |||
- uses: actions/labeler@v5 | |||
with: | |||
dot: true | |||
sync-labels: true |
@@ -15,7 +15,7 @@ _test | |||
# MS VSCode | |||
.vscode | |||
__debug_bin | |||
__debug_bin* | |||
*.cgo1.go | |||
*.cgo2.c | |||
@@ -58,7 +58,7 @@ cpu.out | |||
/data | |||
/indexers | |||
/log | |||
/public/img/avatar | |||
/public/assets/img/avatar | |||
/tests/integration/gitea-integration-* | |||
/tests/integration/indexers-* | |||
/tests/e2e/gitea-e2e-* |
@@ -10,10 +10,19 @@ tasks: | |||
- name: Run backend | |||
command: | | |||
gp sync-await setup | |||
if [ ! -f custom/conf/app.ini ] | |||
then | |||
# Get the URL and extract the domain | |||
url=$(gp url 3000) | |||
domain=$(echo $url | awk -F[/:] '{print $4}') | |||
if [ -f custom/conf/app.ini ]; then | |||
sed -i "s|^ROOT_URL =.*|ROOT_URL = ${url}/|" custom/conf/app.ini | |||
sed -i "s|^DOMAIN =.*|DOMAIN = ${domain}|" custom/conf/app.ini | |||
sed -i "s|^SSH_DOMAIN =.*|SSH_DOMAIN = ${domain}|" custom/conf/app.ini | |||
sed -i "s|^NO_REPLY_ADDRESS =.*|SSH_DOMAIN = noreply.${domain}|" custom/conf/app.ini | |||
else | |||
mkdir -p custom/conf/ | |||
echo -e "[server]\nROOT_URL=$(gp url 3000)/" > custom/conf/app.ini | |||
echo -e "[server]\nROOT_URL = ${url}/" > custom/conf/app.ini | |||
echo -e "\n[database]\nDB_TYPE = sqlite3\nPATH = $GITPOD_REPO_ROOT/data/gitea.db" >> custom/conf/app.ini | |||
fi | |||
export TAGS="sqlite sqlite_unlock_notify" |
@@ -5,13 +5,11 @@ heading-increment: false | |||
line-length: {code_blocks: false, tables: false, stern: true, line_length: -1} | |||
no-alt-text: false | |||
no-bare-urls: false | |||
no-blanks-blockquote: false | |||
no-emphasis-as-heading: false | |||
no-empty-links: false | |||
no-hard-tabs: {code_blocks: false} | |||
no-inline-html: false | |||
no-space-in-code: false | |||
no-space-in-emphasis: false | |||
no-trailing-punctuation: false | |||
no-trailing-spaces: {br_spaces: 0} | |||
single-h1: false |
@@ -1,7 +1,7 @@ | |||
plugins: | |||
- stylelint-declaration-strict-value | |||
- stylelint-declaration-block-no-ignored-properties | |||
- stylelint-stylistic | |||
- "@stylistic/stylelint-plugin" | |||
ignoreFiles: | |||
- "**/*.go" | |||
@@ -17,12 +17,89 @@ overrides: | |||
customSyntax: postcss-html | |||
rules: | |||
"@stylistic/at-rule-name-case": null | |||
"@stylistic/at-rule-name-newline-after": null | |||
"@stylistic/at-rule-name-space-after": null | |||
"@stylistic/at-rule-semicolon-newline-after": null | |||
"@stylistic/at-rule-semicolon-space-before": null | |||
"@stylistic/block-closing-brace-empty-line-before": null | |||
"@stylistic/block-closing-brace-newline-after": null | |||
"@stylistic/block-closing-brace-newline-before": null | |||
"@stylistic/block-closing-brace-space-after": null | |||
"@stylistic/block-closing-brace-space-before": null | |||
"@stylistic/block-opening-brace-newline-after": null | |||
"@stylistic/block-opening-brace-newline-before": null | |||
"@stylistic/block-opening-brace-space-after": null | |||
"@stylistic/block-opening-brace-space-before": null | |||
"@stylistic/color-hex-case": lower | |||
"@stylistic/declaration-bang-space-after": never | |||
"@stylistic/declaration-bang-space-before": null | |||
"@stylistic/declaration-block-semicolon-newline-after": null | |||
"@stylistic/declaration-block-semicolon-newline-before": null | |||
"@stylistic/declaration-block-semicolon-space-after": null | |||
"@stylistic/declaration-block-semicolon-space-before": never | |||
"@stylistic/declaration-block-trailing-semicolon": null | |||
"@stylistic/declaration-colon-newline-after": null | |||
"@stylistic/declaration-colon-space-after": null | |||
"@stylistic/declaration-colon-space-before": never | |||
"@stylistic/function-comma-newline-after": null | |||
"@stylistic/function-comma-newline-before": null | |||
"@stylistic/function-comma-space-after": null | |||
"@stylistic/function-comma-space-before": null | |||
"@stylistic/function-max-empty-lines": 0 | |||
"@stylistic/function-parentheses-newline-inside": never-multi-line | |||
"@stylistic/function-parentheses-space-inside": null | |||
"@stylistic/function-whitespace-after": null | |||
"@stylistic/indentation": 2 | |||
"@stylistic/linebreaks": null | |||
"@stylistic/max-empty-lines": 1 | |||
"@stylistic/max-line-length": null | |||
"@stylistic/media-feature-colon-space-after": null | |||
"@stylistic/media-feature-colon-space-before": never | |||
"@stylistic/media-feature-name-case": null | |||
"@stylistic/media-feature-parentheses-space-inside": null | |||
"@stylistic/media-feature-range-operator-space-after": always | |||
"@stylistic/media-feature-range-operator-space-before": always | |||
"@stylistic/media-query-list-comma-newline-after": null | |||
"@stylistic/media-query-list-comma-newline-before": null | |||
"@stylistic/media-query-list-comma-space-after": null | |||
"@stylistic/media-query-list-comma-space-before": null | |||
"@stylistic/named-grid-areas-alignment": null | |||
"@stylistic/no-empty-first-line": null | |||
"@stylistic/no-eol-whitespace": true | |||
"@stylistic/no-extra-semicolons": true | |||
"@stylistic/no-missing-end-of-source-newline": null | |||
"@stylistic/number-leading-zero": null | |||
"@stylistic/number-no-trailing-zeros": null | |||
"@stylistic/property-case": lower | |||
"@stylistic/selector-attribute-brackets-space-inside": null | |||
"@stylistic/selector-attribute-operator-space-after": null | |||
"@stylistic/selector-attribute-operator-space-before": null | |||
"@stylistic/selector-combinator-space-after": null | |||
"@stylistic/selector-combinator-space-before": null | |||
"@stylistic/selector-descendant-combinator-no-non-space": null | |||
"@stylistic/selector-list-comma-newline-after": null | |||
"@stylistic/selector-list-comma-newline-before": null | |||
"@stylistic/selector-list-comma-space-after": always-single-line | |||
"@stylistic/selector-list-comma-space-before": never-single-line | |||
"@stylistic/selector-max-empty-lines": 0 | |||
"@stylistic/selector-pseudo-class-case": lower | |||
"@stylistic/selector-pseudo-class-parentheses-space-inside": never | |||
"@stylistic/selector-pseudo-element-case": lower | |||
"@stylistic/string-quotes": double | |||
"@stylistic/unicode-bom": null | |||
"@stylistic/unit-case": lower | |||
"@stylistic/value-list-comma-newline-after": null | |||
"@stylistic/value-list-comma-newline-before": null | |||
"@stylistic/value-list-comma-space-after": null | |||
"@stylistic/value-list-comma-space-before": null | |||
"@stylistic/value-list-max-empty-lines": 0 | |||
alpha-value-notation: null | |||
annotation-no-unknown: true | |||
at-rule-allowed-list: null | |||
at-rule-disallowed-list: null | |||
at-rule-empty-line-before: null | |||
at-rule-no-unknown: true | |||
at-rule-no-unknown: [true, {ignoreAtRules: [tailwind]}] | |||
at-rule-no-vendor-prefix: true | |||
at-rule-property-required-list: null | |||
block-no-empty: true | |||
@@ -137,82 +214,6 @@ rules: | |||
selector-type-no-unknown: [true, {ignore: [custom-elements]}] | |||
shorthand-property-no-redundant-values: true | |||
string-no-newline: true | |||
stylistic/at-rule-name-case: null | |||
stylistic/at-rule-name-newline-after: null | |||
stylistic/at-rule-name-space-after: null | |||
stylistic/at-rule-semicolon-newline-after: null | |||
stylistic/at-rule-semicolon-space-before: null | |||
stylistic/block-closing-brace-empty-line-before: null | |||
stylistic/block-closing-brace-newline-after: null | |||
stylistic/block-closing-brace-newline-before: null | |||
stylistic/block-closing-brace-space-after: null | |||
stylistic/block-closing-brace-space-before: null | |||
stylistic/block-opening-brace-newline-after: null | |||
stylistic/block-opening-brace-newline-before: null | |||
stylistic/block-opening-brace-space-after: null | |||
stylistic/block-opening-brace-space-before: null | |||
stylistic/color-hex-case: lower | |||
stylistic/declaration-bang-space-after: never | |||
stylistic/declaration-bang-space-before: null | |||
stylistic/declaration-block-semicolon-newline-after: null | |||
stylistic/declaration-block-semicolon-newline-before: null | |||
stylistic/declaration-block-semicolon-space-after: null | |||
stylistic/declaration-block-semicolon-space-before: never | |||
stylistic/declaration-block-trailing-semicolon: null | |||
stylistic/declaration-colon-newline-after: null | |||
stylistic/declaration-colon-space-after: null | |||
stylistic/declaration-colon-space-before: never | |||
stylistic/function-comma-newline-after: null | |||
stylistic/function-comma-newline-before: null | |||
stylistic/function-comma-space-after: null | |||
stylistic/function-comma-space-before: null | |||
stylistic/function-max-empty-lines: 0 | |||
stylistic/function-parentheses-newline-inside: never-multi-line | |||
stylistic/function-parentheses-space-inside: null | |||
stylistic/function-whitespace-after: null | |||
stylistic/indentation: 2 | |||
stylistic/linebreaks: null | |||
stylistic/max-empty-lines: 1 | |||
stylistic/max-line-length: null | |||
stylistic/media-feature-colon-space-after: null | |||
stylistic/media-feature-colon-space-before: never | |||
stylistic/media-feature-name-case: null | |||
stylistic/media-feature-parentheses-space-inside: null | |||
stylistic/media-feature-range-operator-space-after: always | |||
stylistic/media-feature-range-operator-space-before: always | |||
stylistic/media-query-list-comma-newline-after: null | |||
stylistic/media-query-list-comma-newline-before: null | |||
stylistic/media-query-list-comma-space-after: null | |||
stylistic/media-query-list-comma-space-before: null | |||
stylistic/no-empty-first-line: null | |||
stylistic/no-eol-whitespace: true | |||
stylistic/no-extra-semicolons: true | |||
stylistic/no-missing-end-of-source-newline: null | |||
stylistic/number-leading-zero: null | |||
stylistic/number-no-trailing-zeros: null | |||
stylistic/property-case: lower | |||
stylistic/selector-attribute-brackets-space-inside: null | |||
stylistic/selector-attribute-operator-space-after: null | |||
stylistic/selector-attribute-operator-space-before: null | |||
stylistic/selector-combinator-space-after: null | |||
stylistic/selector-combinator-space-before: null | |||
stylistic/selector-descendant-combinator-no-non-space: null | |||
stylistic/selector-list-comma-newline-after: null | |||
stylistic/selector-list-comma-newline-before: null | |||
stylistic/selector-list-comma-space-after: always-single-line | |||
stylistic/selector-list-comma-space-before: never-single-line | |||
stylistic/selector-max-empty-lines: 0 | |||
stylistic/selector-pseudo-class-case: lower | |||
stylistic/selector-pseudo-class-parentheses-space-inside: never | |||
stylistic/selector-pseudo-element-case: lower | |||
stylistic/string-quotes: double | |||
stylistic/unicode-bom: null | |||
stylistic/unit-case: lower | |||
stylistic/value-list-comma-newline-after: null | |||
stylistic/value-list-comma-newline-before: null | |||
stylistic/value-list-comma-space-after: null | |||
stylistic/value-list-comma-space-before: null | |||
stylistic/value-list-max-empty-lines: 0 | |||
time-min-milliseconds: null | |||
unit-allowed-list: null | |||
unit-disallowed-list: null |
@@ -4,6 +4,240 @@ This changelog goes through all the changes that have been made in each release | |||
without substantial changes to our git log; to see the highlights of what has | |||
been added to each release, please refer to the [blog](https://blog.gitea.com). | |||
## [1.21.6](https://github.com/go-gitea/gitea/releases/tag/v1.21.6) - 2024-02-22 | |||
* SECURITY | |||
* Fix XSS vulnerabilities (#29336) | |||
* Use general token signing secret (#29205) (#29325) | |||
* ENHANCEMENTS | |||
* Refactor git version functions and check compatibility (#29155) (#29157) | |||
* Improve user experience for outdated comments (#29050) (#29086) | |||
* Hide code links on release page if user cannot read code (#29064) (#29066) | |||
* Wrap contained tags and branches again (#29021) (#29026) | |||
* Fix incorrect button CSS usages (#29015) (#29023) | |||
* Strip trailing newline in markdown code copy (#29019) (#29022) | |||
* Implement some action notifier functions (#29173) (#29308) | |||
* Load outdated comments when (un)resolving conversation on PR timeline (#29203) (#29221) | |||
* BUGFIXES | |||
* Refactor issue template parsing and fix API endpoint (#29069) (#29140) | |||
* Fix swift packages not resolving (#29095) (#29102) | |||
* Remove SSH workaround (#27893) (#29332) | |||
* Only log error when tag sync fails (#29295) (#29327) | |||
* Fix SSPI user creation (#28948) (#29323) | |||
* Improve the `issue_comment` workflow trigger event (#29277) (#29322) | |||
* Discard unread data of `git cat-file` (#29297) (#29310) | |||
* Fix error display when merging PRs (#29288) (#29309) | |||
* Prevent double use of `git cat-file` session. (#29298) (#29301) | |||
* Fix missing link on outgoing new release notifications (#29079) (#29300) | |||
* Fix debian InRelease Acquire-By-Hash newline (#29204) (#29299) | |||
* Always write proc-receive hook for all git versions (#29287) (#29291) | |||
* Do not show delete button when time tracker is disabled (#29257) (#29279) | |||
* Workaround to clean up old reviews on creating a new one (#28554) (#29264) | |||
* Fix bug when the linked account was disactived and list the linked accounts (#29263) | |||
* Do not use lower tag names to find releases/tags (#29261) (#29262) | |||
* Fix missed edit issues event for actions (#29237) (#29251) | |||
* Only delete scheduled workflows when needed (#29091) (#29235) | |||
* Make submit event code work with both jQuery event and native event (#29223) (#29234) | |||
* Fix push to create with capitalize repo name (#29090) (#29206) | |||
* Use ghost user if user was not found (#29161) (#29169) | |||
* Dont load Review if Comment is CommentTypeReviewRequest (#28551) (#29160) | |||
* Refactor parseSignatureFromCommitLine (#29054) (#29108) | |||
* Avoid showing unnecessary JS errors when there are elements with different origin on the page (#29081) (#29089) | |||
* Fix gitea-origin-url with default ports (#29085) (#29088) | |||
* Fix orgmode link resolving (#29024) (#29076) | |||
* Fix Elasticsearh Request Entity Too Large #28117 (#29062) (#29075) | |||
* Do not render empty comments (#29039) (#29049) | |||
* Avoid sending update/delete release notice when it is draft (#29008) (#29025) | |||
* Fix gitea-action user avatar broken on edited menu (#29190) (#29307) | |||
* Disallow merge when required checked are missing (#29143) (#29268) | |||
* Fix incorrect link to swift doc and swift package-registry login command (#29096) (#29103) | |||
* Convert visibility to number (#29226) (#29244) | |||
* DOCS | |||
* Remove outdated docs from some languages (#27530) (#29208) | |||
* Fix typos in the documentation (#29048) (#29056) | |||
* Explained where create issue/PR template (#29035) | |||
## [1.21.5](https://github.com/go-gitea/gitea/releases/tag/v1.21.5) - 2024-01-31 | |||
* SECURITY | |||
* Prevent anonymous container access if `RequireSignInView` is enabled (#28877) (#28882) | |||
* Update go dependencies and fix go-git (#28893) (#28934) | |||
* BUGFIXES | |||
* Revert "Speed up loading the dashboard on mysql/mariadb (#28546)" (#29006) (#29007) | |||
* Fix an actions schedule bug (#28942) (#28999) | |||
* Fix update enable_prune even if mirror_interval is not provided (#28905) (#28929) | |||
* Fix uploaded artifacts should be overwritten (#28726) backport v1.21 (#28832) | |||
* Preserve BOM in web editor (#28935) (#28959) | |||
* Strip `/` from relative links (#28932) (#28952) | |||
* Don't remove all mirror repository's releases when mirroring (#28817) (#28939) | |||
* Implement `MigrateRepository` for the actions notifier (#28920) (#28923) | |||
* Respect branch info for relative links (#28909) (#28922) | |||
* Don't reload timeline page when (un)resolving or replying conversation (#28654) (#28917) | |||
* Only migrate the first 255 chars of a Github issue title (#28902) (#28912) | |||
* Fix sort bug on repository issues list (#28897) (#28901) | |||
* Fix `DeleteCollaboration` transaction behaviour (#28886) (#28889) | |||
* Fix schedule not trigger bug because matching full ref name with short ref name (#28874) (#28888) | |||
* Fix migrate storage bug (#28830) (#28867) | |||
* Fix archive creating LFS hooks and breaking pull requests (#28848) (#28851) | |||
* Fix reverting a merge commit failing (#28794) (#28825) | |||
* Upgrade xorm to v1.3.7 to fix a resource leak problem caused by Iterate (#28891) (#28895) | |||
* Fix incorrect PostgreSQL connection string for Unix sockets (#28865) (#28870) | |||
* ENHANCEMENTS | |||
* Make loading animation less aggressive (#28955) (#28956) | |||
* Avoid duplicate JS error messages on UI (#28873) (#28881) | |||
* Bump `@github/relative-time-element` to 4.3.1 (#28819) (#28826) | |||
* MISC | |||
* Warn that `DISABLE_QUERY_AUTH_TOKEN` is false only if it's explicitly defined (#28783) (#28868) | |||
* Remove duplicated checkinit on git module (#28824) (#28831) | |||
## [1.21.4](https://github.com/go-gitea/gitea/releases/tag/v1.21.4) - 2024-01-16 | |||
* SECURITY | |||
* Update github.com/cloudflare/circl (#28789) (#28790) | |||
* Require token for GET subscription endpoint (#28765) (#28768) | |||
* BUGFIXES | |||
* Use refname:strip-2 instead of refname:short when syncing tags (#28797) (#28811) | |||
* Fix links in issue card (#28806) (#28807) | |||
* Fix nil pointer panic when exec some gitea cli command (#28791) (#28795) | |||
* Require token for GET subscription endpoint (#28765) (#28778) | |||
* Fix button size in "attached header right" (#28770) (#28774) | |||
* Fix `convert.ToTeams` on empty input (#28426) (#28767) | |||
* Hide code related setting options in repository when code unit is disabled (#28631) (#28749) | |||
* Fix incorrect URL for "Reference in New Issue" (#28716) (#28723) | |||
* Fix panic when parsing empty pgsql host (#28708) (#28709) | |||
* Upgrade xorm to new version which supported update join for all supported databases (#28590) (#28668) | |||
* Fix alpine package files are not rebuilt (#28638) (#28665) | |||
* Avoid cycle-redirecting user/login page (#28636) (#28658) | |||
* Fix empty ref for cron workflow runs (#28640) (#28647) | |||
* Remove unnecessary syncbranchToDB with tests (#28624) (#28629) | |||
* Use known issue IID to generate new PR index number when migrating from GitLab (#28616) (#28618) | |||
* Fix flex container width (#28603) (#28605) | |||
* Fix the scroll behavior for emoji/mention list (#28597) (#28601) | |||
* Fix wrong due date rendering in issue list page (#28588) (#28591) | |||
* Fix `status_check_contexts` matching bug (#28582) (#28589) | |||
* Fix 500 error of searching commits (#28576) (#28579) | |||
* Use information from previous blame parts (#28572) (#28577) | |||
* Update mermaid for 1.21 (#28571) | |||
* Fix 405 method not allowed CORS / OIDC (#28583) (#28586) (#28587) (#28611) | |||
* Fix `GetCommitStatuses` (#28787) (#28804) | |||
* Forbid removing the last admin user (#28337) (#28793) | |||
* Fix schedule tasks bugs (#28691) (#28780) | |||
* Fix issue dependencies (#27736) (#28776) | |||
* Fix system webhooks API bug (#28531) (#28666) | |||
* Fix when private user following user, private user will not be counted in his own view (#28037) (#28792) | |||
* Render code block in activity tab (#28816) (#28818) | |||
* ENHANCEMENTS | |||
* Rework markup link rendering (#26745) (#28803) | |||
* Modernize merge button (#28140) (#28786) | |||
* Speed up loading the dashboard on mysql/mariadb (#28546) (#28784) | |||
* Assign pull request to project during creation (#28227) (#28775) | |||
* Show description as tooltip instead of title for labels (#28754) (#28766) | |||
* Make template `DateTime` show proper tooltip (#28677) (#28683) | |||
* Switch destination directory for apt signing keys (#28639) (#28642) | |||
* Include heap pprof in diagnosis report to help debugging memory leaks (#28596) (#28599) | |||
* DOCS | |||
* Suggest to use Type=simple for systemd service (#28717) (#28722) | |||
* Extend description for ARTIFACT_RETENTION_DAYS (#28626) (#28630) | |||
* MISC | |||
* Add -F to commit search to treat keywords as strings (#28744) (#28748) | |||
* Add download attribute to release attachments (#28739) (#28740) | |||
* Concatenate error in `checkIfPRContentChanged` (#28731) (#28737) | |||
* Improve 1.21 document for Database Preparation (#28643) (#28644) | |||
## [1.21.3](https://github.com/go-gitea/gitea/releases/tag/v1.21.3) - 2023-12-21 | |||
* SECURITY | |||
* Update golang.org/x/crypto (#28519) | |||
* API | |||
* chore(api): support ignore password if login source type is LDAP for creating user API (#28491) (#28525) | |||
* Add endpoint for not implemented Docker auth (#28457) (#28462) | |||
* ENHANCEMENTS | |||
* Add option to disable ambiguous unicode characters detection (#28454) (#28499) | |||
* Refactor SSH clone URL generation code (#28421) (#28480) | |||
* Polyfill SubmitEvent for PaleMoon (#28441) (#28478) | |||
* BUGFIXES | |||
* Fix the issue ref rendering for wiki (#28556) (#28559) | |||
* Fix duplicate ID when deleting repo (#28520) (#28528) | |||
* Only check online runner when detecting matching runners in workflows (#28286) (#28512) | |||
* Initalize stroage for orphaned repository doctor (#28487) (#28490) | |||
* Fix possible nil pointer access (#28428) (#28440) | |||
* Don't show unnecessary citation JS error on UI (#28433) (#28437) | |||
* DOCS | |||
* Update actions document about comparsion as Github Actions (#28560) (#28564) | |||
* Fix documents for "custom/public/assets/" (#28465) (#28467) | |||
* MISC | |||
* Fix inperformant query on retrifing review from database. (#28552) (#28562) | |||
* Improve the prompt for "ssh-keygen sign" (#28509) (#28510) | |||
* Update docs for DISABLE_QUERY_AUTH_TOKEN (#28485) (#28488) | |||
* Fix Chinese translation of config cheat sheet[API] (#28472) (#28473) | |||
* Retry SSH key verification with additional CRLF if it failed (#28392) (#28464) | |||
## [1.21.2](https://github.com/go-gitea/gitea/releases/tag/v1.21.2) - 2023-12-12 | |||
* SECURITY | |||
* Rebuild with recently released golang version | |||
* Fix missing check (#28406) (#28411) | |||
* Do some missing checks (#28423) (#28432) | |||
* BUGFIXES | |||
* Fix margin in server signed signature verification view (#28379) (#28381) | |||
* Fix object does not exist error when checking citation file (#28314) (#28369) | |||
* Use `filepath` instead of `path` to create SQLite3 database file (#28374) (#28378) | |||
* Fix the runs will not be displayed bug when the main branch have no workflows but other branches have (#28359) (#28365) | |||
* Handle repository.size column being NULL in migration v263 (#28336) (#28363) | |||
* Convert git commit summary to valid UTF8. (#28356) (#28358) | |||
* Fix migration panic due to an empty review comment diff (#28334) (#28362) | |||
* Add `HEAD` support for rpm repo files (#28309) (#28360) | |||
* Fix RPM/Debian signature key creation (#28352) (#28353) | |||
* Keep profile tab when clicking on Language (#28320) (#28331) | |||
* Fix missing issue search index update when changing status (#28325) (#28330) | |||
* Fix wrong link in `protect_branch_name_pattern_desc` (#28313) (#28315) | |||
* Read `previous` info from git blame (#28306) (#28310) | |||
* Ignore "non-existing" errors when getDirectorySize calculates the size (#28276) (#28285) | |||
* Use appSubUrl for OAuth2 callback URL tip (#28266) (#28275) | |||
* Meilisearch: require all query terms to be matched (#28293) (#28296) | |||
* Fix required error for token name (#28267) (#28284) | |||
* Fix issue will be detected as pull request when checking `First-time contributor` (#28237) (#28271) | |||
* Use full width for project boards (#28225) (#28245) | |||
* Increase "version" when update the setting value to a same value as before (#28243) (#28244) | |||
* Also sync DB branches on push if necessary (#28361) (#28403) | |||
* Make gogit Repository.GetBranchNames consistent (#28348) (#28386) | |||
* Recover from panic in cron task (#28409) (#28425) | |||
* Deprecate query string auth tokens (#28390) (#28430) | |||
* ENHANCEMENTS | |||
* Improve doctor cli behavior (#28422) (#28424) | |||
* Fix margin in server signed signature verification view (#28379) (#28381) | |||
* Refactor template empty checks (#28351) (#28354) | |||
* Read `previous` info from git blame (#28306) (#28310) | |||
* Use full width for project boards (#28225) (#28245) | |||
* Enable system users search via the API (#28013) (#28018) | |||
## [1.21.1](https://github.com/go-gitea/gitea/releases/tag/v1.21.1) - 2023-11-26 | |||
* SECURITY | |||
* Fix comment permissions (#28213) (#28216) | |||
* BUGFIXES | |||
* Fix delete-orphaned-repos (#28200) (#28202) | |||
* Make CORS work for oauth2 handlers (#28184) (#28185) | |||
* Fix missing buttons (#28179) (#28181) | |||
* Fix no ActionTaskOutput table waring (#28149) (#28152) | |||
* Fix empty action run title (#28113) (#28148) | |||
* Use "is-loading" to avoid duplicate form submit for code comment (#28143) (#28147) | |||
* Fix Matrix and MSTeams nil dereference (#28089) (#28105) | |||
* Fix incorrect pgsql conn builder behavior (#28085) (#28098) | |||
* Fix system config cache expiration timing (#28072) (#28090) | |||
* Restricted users only see repos in orgs which their team was assigned to (#28025) (#28051) | |||
* API | |||
* Fix permissions for Token DELETE endpoint to match GET and POST (#27610) (#28099) | |||
* ENHANCEMENTS | |||
* Do not display search box when there's no packages yet (#28146) (#28159) | |||
* Add missing `packages.cleanup.success` (#28129) (#28132) | |||
* DOCS | |||
* Docs: Replace deprecated IS_TLS_ENABLED mailer setting in email setup (#28205) (#28208) | |||
* Fix the description about the default setting for action in quick start document (#28160) (#28168) | |||
* Add guide page to actions when there's no workflows (#28145) (#28153) | |||
* MISC | |||
* Use full width for PR comparison (#28182) (#28186) | |||
## [1.21.0](https://github.com/go-gitea/gitea/releases/tag/v1.21.0) - 2023-11-14 | |||
* BREAKING |
@@ -8,6 +8,7 @@ | |||
- [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) | |||
- [Issue locking](#issue-locking) | |||
- [Building Gitea](#building-gitea) | |||
- [Dependencies](#dependencies) | |||
- [Backend](#backend) | |||
@@ -47,6 +48,7 @@ | |||
- [Release Cycle](#release-cycle) | |||
- [Maintainers](#maintainers) | |||
- [Technical Oversight Committee (TOC)](#technical-oversight-committee-toc) | |||
- [TOC election process](#toc-election-process) | |||
- [Current TOC members](#current-toc-members) | |||
- [Previous TOC/owners members](#previous-tocowners-members) | |||
- [Governance Compensation](#governance-compensation) | |||
@@ -102,6 +104,13 @@ the goals for the project and tools. | |||
Pull requests should not be the place for architecture discussions. | |||
### Issue locking | |||
Commenting on closed or merged issues/PRs is strongly discouraged. | |||
Such comments will likely be overlooked as some maintainers may not view notifications on closed issues, thinking that the item is resolved. | |||
As such, commenting on closed/merged issues/PRs may be disabled prior to the scheduled auto-locking if a discussion starts or if unrelated comments are posted. | |||
If further discussion is needed, we encourage you to open a new issue instead and we recommend linking to the issue/PR in question for context. | |||
## Building Gitea | |||
See the [development setup instructions](https://docs.gitea.com/development/hacking-on-gitea). | |||
@@ -110,7 +119,7 @@ See the [development setup instructions](https://docs.gitea.com/development/hack | |||
### Backend | |||
Go dependencies are managed using [Go Modules](https://golang.org/cmd/go/#hdr-Module_maintenance). \ | |||
Go dependencies are managed using [Go Modules](https://go.dev/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. \ | |||
@@ -167,7 +176,7 @@ Here's how to run the test suite: | |||
| Command | Action | | | |||
| :------------------------------------- | :----------------------------------------------- | ------------ | | |||
|``make test[\#SpecificTestName]`` | run unit test(s) | | |||
|``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) | | |||
@@ -455,7 +464,7 @@ We assume in good faith that the information you provide is legally binding. | |||
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 | |||
merged before feature freeze. And, during the frozen period, a corresponding | |||
merged before feature freeze. All feature pull requests haven't been merged before this feature freeze will be moved to next milestone, please notice our feature freeze announcement on discord. 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. | |||
@@ -486,36 +495,53 @@ 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/ | |||
Furthermore, any account with write access (like bots and TOC members) **must** use 2FA. | |||
https://help.github.com/articles/securing-your-account-with-two-factor-authentication-2fa/ | |||
## Technical Oversight Committee (TOC) | |||
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. | |||
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 are elected as it has been over the past years, and the other three consist of appointed members from the Gitea company. | |||
https://blog.gitea.com/quarterly-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. | |||
https://help.github.com/articles/securing-your-account-with-two-factor-authentication-2fa/ | |||
### TOC election process | |||
Any maintainer is eligible to be part of the community TOC if they are not associated with the Gitea company. | |||
A maintainer can either nominate themselves, or can be nominated by other maintainers to be a candidate for the TOC election. | |||
If you are nominated by someone else, you must first accept your nomination before the vote starts to be a candidate. | |||
The TOC is elected for one year, the TOC election happens yearly. | |||
After the announcement of the results of the TOC election, elected members have two weeks time to confirm or refuse the seat. | |||
If an elected member does not answer within this timeframe, they are automatically assumed to refuse the seat. | |||
Refusals result in the person with the next highest vote getting the same choice. | |||
As long as seats are empty in the TOC, members of the previous TOC can fill them until an elected member accepts the seat. | |||
If an elected member that accepts the seat does not have 2FA configured yet, they will be temporarily counted as `answer pending` until they manage to configure 2FA, thus leaving their seat empty for this duration. | |||
### Current TOC members | |||
- 2023-01-01 ~ 2023-12-31 - https://blog.gitea.com/quarterly-23q1/ | |||
- 2024-01-01 ~ 2024-12-31 | |||
- 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> | |||
- [Matti Ranta](https://gitea.com/techknowlogick) <techknowlogick@gitea.com> | |||
- Community | |||
- [6543](https://gitea.com/6543) <6543@obermui.de> | |||
- [Andrew Thornton](https://gitea.com/zeripath) <art27@cantab.net> | |||
- [delvh](https://gitea.com/delvh) <dev.lh@web.de> | |||
- [John Olheiser](https://gitea.com/jolheiser) <john.olheiser@gmail.com> | |||
### Previous TOC/owners members | |||
Here's the history of the owners and the time they served: | |||
- [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) | |||
- [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), 2023 | |||
- [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) | |||
- [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), 2023 | |||
- [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), 2023 | |||
- [6543](https://gitea.com/6543) - 2023 | |||
- [John Olheiser](https://gitea.com/jolheiser) - 2023 | |||
- [Jason Song](https://gitea.com/wolfogre) - 2023 | |||
## Governance Compensation | |||
@@ -1,5 +1,5 @@ | |||
# Build stage | |||
FROM docker.io/library/golang:1.21-alpine3.19 AS build-env | |||
FROM docker.io/library/golang:1.22-alpine3.19 AS build-env | |||
ARG GOPROXY | |||
ENV GOPROXY ${GOPROXY:-direct} |
@@ -1,5 +1,5 @@ | |||
# Build stage | |||
FROM docker.io/library/golang:1.21-alpine3.19 AS build-env | |||
FROM docker.io/library/golang:1.22-alpine3.19 AS build-env | |||
ARG GOPROXY | |||
ENV GOPROXY ${GOPROXY:-direct} |
@@ -59,3 +59,4 @@ Rui Chen <rui@chenrui.dev> (@chenrui333) | |||
Nanguan Lin <nanguanlin6@gmail.com> (@lng2020) | |||
kerwin612 <kerwin612@qq.com> (@kerwin612) | |||
Gary Wang <git@blumia.net> (@BLumia) | |||
Tim-Niclas Oelschläger <zokki.softwareschmiede@gmail.com> (@zokkis) |
@@ -23,19 +23,19 @@ SHASUM ?= shasum -a 256 | |||
HAS_GO := $(shell hash $(GO) > /dev/null 2>&1 && echo yes) | |||
COMMA := , | |||
XGO_VERSION := go-1.21.x | |||
XGO_VERSION := go-1.22.x | |||
AIR_PACKAGE ?= github.com/cosmtrek/air@v1.44.0 | |||
AIR_PACKAGE ?= github.com/cosmtrek/air@v1.49.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.55.0 | |||
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.6.0 | |||
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.56.1 | |||
GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.11 | |||
MISSPELL_PACKAGE ?= github.com/client9/misspell/cmd/misspell@v0.3.4 | |||
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.30.5 | |||
MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.4.1 | |||
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@db51e79a0e37c572d8b59ae0c58bf2bbbbe53285 | |||
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest | |||
GO_LICENSES_PACKAGE ?= github.com/google/go-licenses@v1.6.0 | |||
GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@v1.0.1 | |||
ACTIONLINT_PACKAGE ?= github.com/rhysd/actionlint/cmd/actionlint@v1.6.25 | |||
GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@v1.0.3 | |||
ACTIONLINT_PACKAGE ?= github.com/rhysd/actionlint/cmd/actionlint@v1.6.26 | |||
DOCKER_IMAGE ?= gitea/gitea | |||
DOCKER_TAG ?= latest | |||
@@ -115,11 +115,12 @@ LINUX_ARCHS ?= linux/amd64,linux/386,linux/arm-5,linux/arm-6,linux/arm64 | |||
GO_PACKAGES ?= $(filter-out code.gitea.io/gitea/tests/integration/migration-test code.gitea.io/gitea/tests code.gitea.io/gitea/tests/integration code.gitea.io/gitea/tests/e2e,$(shell $(GO) list ./... | grep -v /vendor/)) | |||
GO_TEST_PACKAGES ?= $(filter-out $(shell $(GO) list code.gitea.io/gitea/models/migrations/...) code.gitea.io/gitea/tests/integration/migration-test code.gitea.io/gitea/tests code.gitea.io/gitea/tests/integration code.gitea.io/gitea/tests/e2e,$(shell $(GO) list ./... | grep -v /vendor/)) | |||
MIGRATE_TEST_PACKAGES ?= $(shell $(GO) list code.gitea.io/gitea/models/migrations/...) | |||
FOMANTIC_WORK_DIR := web_src/fomantic | |||
WEBPACK_SOURCES := $(shell find web_src/js web_src/css -type f) | |||
WEBPACK_CONFIGS := webpack.config.js | |||
WEBPACK_CONFIGS := webpack.config.js tailwind.config.js | |||
WEBPACK_DEST := public/assets/js/index.js public/assets/css/index.css | |||
WEBPACK_DEST_ENTRIES := public/assets/js public/assets/css public/assets/fonts public/assets/img/webpack | |||
@@ -146,6 +147,11 @@ TAR_EXCLUDES := .git data indexers queues log node_modules $(EXECUTABLE) $(FOMAN | |||
GO_DIRS := build cmd models modules routers services tests | |||
WEB_DIRS := web_src/js web_src/css | |||
ESLINT_FILES := web_src/js tools *.config.js tests/e2e | |||
STYLELINT_FILES := web_src/css web_src/js/components/*.vue | |||
SPELLCHECK_FILES := $(GO_DIRS) $(WEB_DIRS) docs/content templates options/locale/locale_en-US.ini .github | |||
EDITORCONFIG_FILES := templates .github/workflows options/locale/locale_en-US.ini | |||
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 += $(GENERATED_GO_DEST) | |||
@@ -162,8 +168,8 @@ ifdef DEPS_PLAYWRIGHT | |||
endif | |||
SWAGGER_SPEC := templates/swagger/v1_json.tmpl | |||
SWAGGER_SPEC_S_TMPL := s|"basePath": *"/api/v1"|"basePath": "{{AppSubUrl \| JSEscape \| Safe}}/api/v1"|g | |||
SWAGGER_SPEC_S_JSON := s|"basePath": *"{{AppSubUrl \| JSEscape \| Safe}}/api/v1"|"basePath": "/api/v1"|g | |||
SWAGGER_SPEC_S_TMPL := s|"basePath": *"/api/v1"|"basePath": "{{AppSubUrl \| JSEscape}}/api/v1"|g | |||
SWAGGER_SPEC_S_JSON := s|"basePath": *"{{AppSubUrl \| JSEscape}}/api/v1"|"basePath": "/api/v1"|g | |||
SWAGGER_EXCLUDE := code.gitea.io/sdk | |||
SWAGGER_NEWLINE_COMMAND := -e '$$a\' | |||
@@ -219,6 +225,8 @@ help: | |||
@echo " - lint-swagger lint swagger files" | |||
@echo " - lint-templates lint template files" | |||
@echo " - lint-yaml lint yaml files" | |||
@echo " - lint-spell lint spelling" | |||
@echo " - lint-spell-fix lint spelling and fix issues" | |||
@echo " - checks run various consistency checks" | |||
@echo " - checks-frontend check frontend files" | |||
@echo " - checks-backend check backend files" | |||
@@ -308,10 +316,6 @@ fmt-check: fmt | |||
exit 1; \ | |||
fi | |||
.PHONY: misspell-check | |||
misspell-check: | |||
go run $(MISSPELL_PACKAGE) -error $(GO_DIRS) $(WEB_DIRS) | |||
.PHONY: $(TAGS_EVIDENCE) | |||
$(TAGS_EVIDENCE): | |||
@mkdir -p $(MAKE_EVIDENCE_DIR) | |||
@@ -351,13 +355,13 @@ checks: checks-frontend checks-backend | |||
checks-frontend: lockfile-check svg-check | |||
.PHONY: checks-backend | |||
checks-backend: tidy-check swagger-check fmt-check misspell-check swagger-validate security-check | |||
checks-backend: tidy-check swagger-check fmt-check swagger-validate security-check | |||
.PHONY: lint | |||
lint: lint-frontend lint-backend | |||
lint: lint-frontend lint-backend lint-spell | |||
.PHONY: lint-fix | |||
lint-fix: lint-frontend-fix lint-backend-fix | |||
lint-fix: lint-frontend-fix lint-backend-fix lint-spell-fix | |||
.PHONY: lint-frontend | |||
lint-frontend: lint-js lint-css | |||
@@ -373,19 +377,19 @@ lint-backend-fix: lint-go-fix lint-go-vet lint-editorconfig | |||
.PHONY: lint-js | |||
lint-js: node_modules | |||
npx eslint --color --max-warnings=0 --ext js,vue web_src/js build *.config.js tests/e2e | |||
npx eslint --color --max-warnings=0 --ext js,vue $(ESLINT_FILES) | |||
.PHONY: lint-js-fix | |||
lint-js-fix: node_modules | |||
npx eslint --color --max-warnings=0 --ext js,vue web_src/js build *.config.js tests/e2e --fix | |||
npx eslint --color --max-warnings=0 --ext js,vue $(ESLINT_FILES) --fix | |||
.PHONY: lint-css | |||
lint-css: node_modules | |||
npx stylelint --color --max-warnings=0 web_src/css web_src/js/components/*.vue | |||
npx stylelint --color --max-warnings=0 $(STYLELINT_FILES) | |||
.PHONY: lint-css-fix | |||
lint-css-fix: node_modules | |||
npx stylelint --color --max-warnings=0 web_src/css web_src/js/components/*.vue --fix | |||
npx stylelint --color --max-warnings=0 $(STYLELINT_FILES) --fix | |||
.PHONY: lint-swagger | |||
lint-swagger: node_modules | |||
@@ -395,6 +399,14 @@ lint-swagger: node_modules | |||
lint-md: node_modules | |||
npx markdownlint docs *.md | |||
.PHONY: lint-spell | |||
lint-spell: | |||
@go run $(MISSPELL_PACKAGE) -error $(SPELLCHECK_FILES) | |||
.PHONY: lint-spell-fix | |||
lint-spell-fix: | |||
@go run $(MISSPELL_PACKAGE) -w $(SPELLCHECK_FILES) | |||
.PHONY: lint-go | |||
lint-go: | |||
$(GO) run $(GOLANGCI_LINT_PACKAGE) run | |||
@@ -418,7 +430,7 @@ lint-go-vet: | |||
.PHONY: lint-editorconfig | |||
lint-editorconfig: | |||
$(GO) run $(EDITORCONFIG_CHECKER_PACKAGE) templates .github/workflows | |||
@$(GO) run $(EDITORCONFIG_CHECKER_PACKAGE) $(EDITORCONFIG_FILES) | |||
.PHONY: lint-actions | |||
lint-actions: | |||
@@ -434,7 +446,7 @@ lint-yaml: .venv | |||
.PHONY: watch | |||
watch: | |||
@bash build/watch.sh | |||
@bash tools/watch.sh | |||
.PHONY: watch-frontend | |||
watch-frontend: node-check node_modules | |||
@@ -594,8 +606,7 @@ test-mssql\#%: integrations.mssql.test generate-ini-mssql | |||
test-mssql-migration: migrations.mssql.test migrations.individual.mssql.test | |||
.PHONY: playwright | |||
playwright: $(PLAYWRIGHT_DIR) | |||
npm install --no-save @playwright/test | |||
playwright: deps-frontend | |||
npx playwright install $(PLAYWRIGHT_FLAGS) | |||
.PHONY: test-e2e% | |||
@@ -702,9 +713,7 @@ migrations.sqlite.test: $(GO_SOURCES) generate-ini-sqlite | |||
.PHONY: migrations.individual.mysql.test | |||
migrations.individual.mysql.test: $(GO_SOURCES) | |||
for pkg in $(shell $(GO) list code.gitea.io/gitea/models/migrations/...); do \ | |||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg; \ | |||
done | |||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini $(GO) test $(GOTESTFLAGS) -tags='$(TEST_TAGS)' -p 1 $(MIGRATE_TEST_PACKAGES) | |||
.PHONY: migrations.individual.sqlite.test\#% | |||
migrations.individual.sqlite.test\#%: $(GO_SOURCES) generate-ini-sqlite | |||
@@ -712,20 +721,15 @@ migrations.individual.sqlite.test\#%: $(GO_SOURCES) generate-ini-sqlite | |||
.PHONY: migrations.individual.pgsql.test | |||
migrations.individual.pgsql.test: $(GO_SOURCES) | |||
for pkg in $(shell $(GO) list code.gitea.io/gitea/models/migrations/...); do \ | |||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg; \ | |||
done | |||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini $(GO) test $(GOTESTFLAGS) -tags='$(TEST_TAGS)' -p 1 $(MIGRATE_TEST_PACKAGES) | |||
.PHONY: migrations.individual.pgsql.test\#% | |||
migrations.individual.pgsql.test\#%: $(GO_SOURCES) generate-ini-pgsql | |||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' code.gitea.io/gitea/models/migrations/$* | |||
.PHONY: migrations.individual.mssql.test | |||
migrations.individual.mssql.test: $(GO_SOURCES) generate-ini-mssql | |||
for pkg in $(shell $(GO) list code.gitea.io/gitea/models/migrations/...); do \ | |||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg -test.failfast; \ | |||
done | |||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini $(GO) test $(GOTESTFLAGS) -tags='$(TEST_TAGS)' -p 1 $(MIGRATE_TEST_PACKAGES) | |||
.PHONY: migrations.individual.mssql.test\#% | |||
migrations.individual.mssql.test\#%: $(GO_SOURCES) generate-ini-mssql | |||
@@ -733,9 +737,7 @@ migrations.individual.mssql.test\#%: $(GO_SOURCES) generate-ini-mssql | |||
.PHONY: migrations.individual.sqlite.test | |||
migrations.individual.sqlite.test: $(GO_SOURCES) generate-ini-sqlite | |||
for pkg in $(shell $(GO) list code.gitea.io/gitea/models/migrations/...); do \ | |||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg; \ | |||
done | |||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini $(GO) test $(GOTESTFLAGS) -tags='$(TEST_TAGS)' -p 1 $(MIGRATE_TEST_PACKAGES) | |||
.PHONY: migrations.individual.sqlite.test\#% | |||
migrations.individual.sqlite.test\#%: $(GO_SOURCES) generate-ini-sqlite | |||
@@ -839,10 +841,6 @@ release-sources: | $(DIST_DIRS) | |||
release-docs: | $(DIST_DIRS) docs | |||
tar -czf $(DIST)/release/gitea-docs-$(VERSION).tar.gz -C ./docs . | |||
.PHONY: docs | |||
docs: | |||
cd docs; bash scripts/trans-copy.sh; | |||
.PHONY: deps | |||
deps: deps-frontend deps-backend deps-tools deps-py | |||
@@ -901,6 +899,7 @@ fomantic: | |||
cd $(FOMANTIC_WORK_DIR) && npm install --no-save | |||
cp -f $(FOMANTIC_WORK_DIR)/theme.config.less $(FOMANTIC_WORK_DIR)/node_modules/fomantic-ui/src/theme.config | |||
cp -rf $(FOMANTIC_WORK_DIR)/_site $(FOMANTIC_WORK_DIR)/node_modules/fomantic-ui/src/ | |||
$(SED_INPLACE) -e 's/ overrideBrowserslist\r/ overrideBrowserslist: ["defaults"]\r/g' $(FOMANTIC_WORK_DIR)/node_modules/fomantic-ui/tasks/config/tasks.js | |||
cd $(FOMANTIC_WORK_DIR) && npx gulp -f node_modules/fomantic-ui/gulpfile.js build | |||
# fomantic uses "touchstart" as click event for some browsers, it's not ideal, so we force fomantic to always use "click" as click event | |||
$(SED_INPLACE) -e 's/clickEvent[ \t]*=/clickEvent = "click", unstableClickEvent =/g' $(FOMANTIC_WORK_DIR)/build/semantic.js | |||
@@ -919,7 +918,7 @@ $(WEBPACK_DEST): $(WEBPACK_SOURCES) $(WEBPACK_CONFIGS) package-lock.json | |||
.PHONY: svg | |||
svg: node-check | node_modules | |||
rm -rf $(SVG_DEST_DIR) | |||
node build/generate-svg.js | |||
node tools/generate-svg.js | |||
.PHONY: svg-check | |||
svg-check: svg | |||
@@ -962,8 +961,8 @@ generate-gitignore: | |||
.PHONY: generate-images | |||
generate-images: | node_modules | |||
npm install --no-save --no-package-lock fabric@5 imagemin-zopfli@7 | |||
node build/generate-images.js $(TAGS) | |||
npm install --no-save fabric@6.0.0-beta19 imagemin-zopfli@7 | |||
node tools/generate-images.js $(TAGS) | |||
.PHONY: generate-manpage | |||
generate-manpage: | |||
@@ -980,3 +979,8 @@ docker: | |||
# This endif closes the if at the top of the file | |||
endif | |||
# Disable parallel execution because it would break some targets that don't | |||
# specify exact dependencies like 'backend' which does currently not depend | |||
# on 'frontend' to enable Node.js-less builds from source tarballs. | |||
.NOTPARALLEL: |
@@ -1,58 +1,19 @@ | |||
<p align="center"> | |||
<a href="https://gitea.io/"> | |||
<img alt="Gitea" src="https://raw.githubusercontent.com/go-gitea/gitea/main/public/assets/img/gitea.svg" width="220"/> | |||
</a> | |||
</p> | |||
<h1 align="center">Gitea - Git with a cup of tea</h1> | |||
<p align="center"> | |||
<a href="https://github.com/go-gitea/gitea/actions/workflows/release-nightly.yml?query=branch%3Amain" title="Release Nightly"> | |||
<img src="https://github.com/go-gitea/gitea/actions/workflows/release-nightly.yml/badge.svg?branch=main"> | |||
</a> | |||
<a href="https://discord.gg/Gitea" title="Join the Discord chat at https://discord.gg/Gitea"> | |||
<img src="https://img.shields.io/discord/322538954119184384.svg?logo=discord&logoColor=white&label=Discord&color=5865F2"> | |||
</a> | |||
<a href="https://app.codecov.io/gh/go-gitea/gitea" title="Codecov"> | |||
<img src="https://codecov.io/gh/go-gitea/gitea/branch/main/graph/badge.svg"> | |||
</a> | |||
<a href="https://goreportcard.com/report/code.gitea.io/gitea" title="Go Report Card"> | |||
<img src="https://goreportcard.com/badge/code.gitea.io/gitea"> | |||
</a> | |||
<a href="https://pkg.go.dev/code.gitea.io/gitea" title="GoDoc"> | |||
<img src="https://pkg.go.dev/badge/code.gitea.io/gitea?status.svg"> | |||
</a> | |||
<a href="https://github.com/go-gitea/gitea/releases/latest" title="GitHub release"> | |||
<img src="https://img.shields.io/github/release/go-gitea/gitea.svg"> | |||
</a> | |||
<a href="https://www.codetriage.com/go-gitea/gitea" title="Help Contribute to Open Source"> | |||
<img src="https://www.codetriage.com/go-gitea/gitea/badges/users.svg"> | |||
</a> | |||
<a href="https://opencollective.com/gitea" title="Become a backer/sponsor of gitea"> | |||
<img src="https://opencollective.com/gitea/tiers/backers/badge.svg?label=backers&color=brightgreen"> | |||
</a> | |||
<a href="https://opensource.org/licenses/MIT" title="License: MIT"> | |||
<img src="https://img.shields.io/badge/License-MIT-blue.svg"> | |||
</a> | |||
<a href="https://gitpod.io/#https://github.com/go-gitea/gitea"> | |||
<img | |||
src="https://img.shields.io/badge/Contribute%20with-Gitpod-908a85?logo=gitpod" | |||
alt="Contribute with Gitpod" | |||
/> | |||
</a> | |||
<a href="https://crowdin.com/project/gitea" title="Crowdin"> | |||
<img src="https://badges.crowdin.net/gitea/localized.svg"> | |||
</a> | |||
<a href="https://www.tickgit.com/browse?repo=github.com/go-gitea/gitea&branch=main" title="TODOs"> | |||
<img src="https://badgen.net/https/api.tickgit.com/badgen/github.com/go-gitea/gitea/main"> | |||
</a> | |||
<a href="https://app.bountysource.com/teams/gitea" title="Bountysource"> | |||
<img src="https://img.shields.io/bountysource/team/gitea/activity"> | |||
</a> | |||
</p> | |||
<p align="center"> | |||
<a href="README_ZH.md">View this document in Chinese</a> | |||
</p> | |||
# Gitea | |||
[![](https://github.com/go-gitea/gitea/actions/workflows/release-nightly.yml/badge.svg?branch=main)](https://github.com/go-gitea/gitea/actions/workflows/release-nightly.yml?query=branch%3Amain "Release Nightly") | |||
[![](https://img.shields.io/discord/322538954119184384.svg?logo=discord&logoColor=white&label=Discord&color=5865F2)](https://discord.gg/Gitea "Join the Discord chat at https://discord.gg/Gitea") | |||
[![](https://codecov.io/gh/go-gitea/gitea/branch/main/graph/badge.svg)](https://app.codecov.io/gh/go-gitea/gitea "Codecov") | |||
[![](https://goreportcard.com/badge/code.gitea.io/gitea)](https://goreportcard.com/report/code.gitea.io/gitea "Go Report Card") | |||
[![](https://pkg.go.dev/badge/code.gitea.io/gitea?status.svg)](https://pkg.go.dev/code.gitea.io/gitea "GoDoc") | |||
[![](https://img.shields.io/github/release/go-gitea/gitea.svg)](https://github.com/go-gitea/gitea/releases/latest "GitHub release") | |||
[![](https://www.codetriage.com/go-gitea/gitea/badges/users.svg)](https://www.codetriage.com/go-gitea/gitea "Help Contribute to Open Source") | |||
[![](https://opencollective.com/gitea/tiers/backers/badge.svg?label=backers&color=brightgreen)](https://opencollective.com/gitea "Become a backer/sponsor of gitea") | |||
[![](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT "License: MIT") | |||
[![Contribute with Gitpod](https://img.shields.io/badge/Contribute%20with-Gitpod-908a85?logo=gitpod)](https://gitpod.io/#https://github.com/go-gitea/gitea) | |||
[![](https://badges.crowdin.net/gitea/localized.svg)](https://crowdin.com/project/gitea "Crowdin") | |||
[![](https://badgen.net/https/api.tickgit.com/badgen/github.com/go-gitea/gitea/main)](https://www.tickgit.com/browse?repo=github.com/go-gitea/gitea&branch=main "TODOs") | |||
[View this document in Chinese](./README_ZH.md) | |||
## Purpose | |||
@@ -89,25 +50,23 @@ The `build` target is split into two sub-targets: | |||
Internet connectivity is required to download the go and npm modules. When building from the official source tarballs which include pre-built frontend files, the `frontend` target will not be triggered, making it possible to build without Node.js. | |||
Parallelism (`make -j <num>`) is not supported. | |||
More info: https://docs.gitea.com/installation/install-from-source | |||
## Using | |||
./gitea web | |||
NOTE: If you're interested in using our APIs, we have experimental | |||
support with [documentation](https://try.gitea.io/api/swagger). | |||
> [!NOTE] | |||
> If you're interested in using our APIs, we have experimental support with [documentation](https://try.gitea.io/api/swagger). | |||
## Contributing | |||
Expected workflow is: Fork -> Patch -> Push -> Pull Request | |||
NOTES: | |||
1. **YOU MUST READ THE [CONTRIBUTORS GUIDE](CONTRIBUTING.md) BEFORE STARTING TO WORK ON A PULL REQUEST.** | |||
2. If you have found a vulnerability in the project, please write privately to **security@gitea.io**. Thanks! | |||
> [!NOTE] | |||
> | |||
> 1. **YOU MUST READ THE [CONTRIBUTORS GUIDE](CONTRIBUTING.md) BEFORE STARTING TO WORK ON A PULL REQUEST.** | |||
> 2. If you have found a vulnerability in the project, please write privately to **security@gitea.io**. Thanks! | |||
## Translating | |||
@@ -178,5 +137,5 @@ Looking for an overview of the interface? Check it out! | |||
|![Dashboard](https://dl.gitea.com/screenshots/home_timeline.png)|![User Profile](https://dl.gitea.com/screenshots/user_profile.png)|![Global Issues](https://dl.gitea.com/screenshots/global_issues.png)| | |||
|:---:|:---:|:---:| | |||
|![Branches](https://dl.gitea.com/screenshots/branches.png)|![Web Editor](https://dl.gitea.com/screenshots/web_editor.png)|![Activity](https://dl.gitea.com/screenshots/activity.png)| | |||
|![New Migration](https://dl.gitea.com/screenshots/migration.png)|![Migrating](https://dl.gitea.com/screenshots/migration.gif)|![Pull Request View](https://image.ibb.co/e02dSb/6.png) | |||
![Pull Request Dark](https://dl.gitea.com/screenshots/pull_requests_dark.png)|![Diff Review Dark](https://dl.gitea.com/screenshots/review_dark.png)|![Diff Dark](https://dl.gitea.com/screenshots/diff_dark.png)| | |||
|![New Migration](https://dl.gitea.com/screenshots/migration.png)|![Migrating](https://dl.gitea.com/screenshots/migration.gif)|![Pull Request View](https://image.ibb.co/e02dSb/6.png)| | |||
|![Pull Request Dark](https://dl.gitea.com/screenshots/pull_requests_dark.png)|![Diff Review Dark](https://dl.gitea.com/screenshots/review_dark.png)|![Diff Dark](https://dl.gitea.com/screenshots/diff_dark.png)| |
@@ -1,58 +1,19 @@ | |||
<p align="center"> | |||
<a href="https://gitea.io/"> | |||
<img alt="Gitea" src="https://raw.githubusercontent.com/go-gitea/gitea/main/public/assets/img/gitea.svg" width="220"/> | |||
</a> | |||
</p> | |||
<h1 align="center">Gitea - Git with a cup of tea</h1> | |||
<p align="center"> | |||
<a href="https://github.com/go-gitea/gitea/actions/workflows/release-nightly.yml?query=branch%3Amain" title="Release Nightly"> | |||
<img src="https://github.com/go-gitea/gitea/actions/workflows/release-nightly.yml/badge.svg?branch=main"> | |||
</a> | |||
<a href="https://discord.gg/Gitea" title="Join the Discord chat at https://discord.gg/Gitea"> | |||
<img src="https://img.shields.io/discord/322538954119184384.svg"> | |||
</a> | |||
<a href="https://app.codecov.io/gh/go-gitea/gitea" title="Codecov"> | |||
<img src="https://codecov.io/gh/go-gitea/gitea/branch/main/graph/badge.svg"> | |||
</a> | |||
<a href="https://goreportcard.com/report/code.gitea.io/gitea" title="Go Report Card"> | |||
<img src="https://goreportcard.com/badge/code.gitea.io/gitea"> | |||
</a> | |||
<a href="https://pkg.go.dev/code.gitea.io/gitea" title="GoDoc"> | |||
<img src="https://pkg.go.dev/badge/code.gitea.io/gitea?status.svg"> | |||
</a> | |||
<a href="https://github.com/go-gitea/gitea/releases/latest" title="GitHub release"> | |||
<img src="https://img.shields.io/github/release/go-gitea/gitea.svg"> | |||
</a> | |||
<a href="https://www.codetriage.com/go-gitea/gitea" title="Help Contribute to Open Source"> | |||
<img src="https://www.codetriage.com/go-gitea/gitea/badges/users.svg"> | |||
</a> | |||
<a href="https://opencollective.com/gitea" title="Become a backer/sponsor of gitea"> | |||
<img src="https://opencollective.com/gitea/tiers/backers/badge.svg?label=backers&color=brightgreen"> | |||
</a> | |||
<a href="https://opensource.org/licenses/MIT" title="License: MIT"> | |||
<img src="https://img.shields.io/badge/License-MIT-blue.svg"> | |||
</a> | |||
<a href="https://gitpod.io/#https://github.com/go-gitea/gitea"> | |||
<img | |||
src="https://img.shields.io/badge/Contribute%20with-Gitpod-908a85?logo=gitpod" | |||
alt="Contribute with Gitpod" | |||
/> | |||
</a> | |||
<a href="https://crowdin.com/project/gitea" title="Crowdin"> | |||
<img src="https://badges.crowdin.net/gitea/localized.svg"> | |||
</a> | |||
<a href="https://www.tickgit.com/browse?repo=github.com/go-gitea/gitea&branch=main" title="TODOs"> | |||
<img src="https://badgen.net/https/api.tickgit.com/badgen/github.com/go-gitea/gitea/main"> | |||
</a> | |||
<a href="https://app.bountysource.com/teams/gitea" title="Bountysource"> | |||
<img src="https://img.shields.io/bountysource/team/gitea/activity"> | |||
</a> | |||
</p> | |||
<p align="center"> | |||
<a href="README.md">View this document in English</a> | |||
</p> | |||
# Gitea | |||
[![](https://github.com/go-gitea/gitea/actions/workflows/release-nightly.yml/badge.svg?branch=main)](https://github.com/go-gitea/gitea/actions/workflows/release-nightly.yml?query=branch%3Amain "Release Nightly") | |||
[![](https://img.shields.io/discord/322538954119184384.svg?logo=discord&logoColor=white&label=Discord&color=5865F2)](https://discord.gg/Gitea "Join the Discord chat at https://discord.gg/Gitea") | |||
[![](https://codecov.io/gh/go-gitea/gitea/branch/main/graph/badge.svg)](https://app.codecov.io/gh/go-gitea/gitea "Codecov") | |||
[![](https://goreportcard.com/badge/code.gitea.io/gitea)](https://goreportcard.com/report/code.gitea.io/gitea "Go Report Card") | |||
[![](https://pkg.go.dev/badge/code.gitea.io/gitea?status.svg)](https://pkg.go.dev/code.gitea.io/gitea "GoDoc") | |||
[![](https://img.shields.io/github/release/go-gitea/gitea.svg)](https://github.com/go-gitea/gitea/releases/latest "GitHub release") | |||
[![](https://www.codetriage.com/go-gitea/gitea/badges/users.svg)](https://www.codetriage.com/go-gitea/gitea "Help Contribute to Open Source") | |||
[![](https://opencollective.com/gitea/tiers/backers/badge.svg?label=backers&color=brightgreen)](https://opencollective.com/gitea "Become a backer/sponsor of gitea") | |||
[![](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT "License: MIT") | |||
[![Contribute with Gitpod](https://img.shields.io/badge/Contribute%20with-Gitpod-908a85?logo=gitpod)](https://gitpod.io/#https://github.com/go-gitea/gitea) | |||
[![](https://badges.crowdin.net/gitea/localized.svg)](https://crowdin.com/project/gitea "Crowdin") | |||
[![](https://badgen.net/https/api.tickgit.com/badgen/github.com/go-gitea/gitea/main)](https://www.tickgit.com/browse?repo=github.com/go-gitea/gitea&branch=main "TODOs") | |||
[View this document in English](./README.md) | |||
## 目标 | |||
@@ -98,5 +59,5 @@ Fork -> Patch -> Push -> Pull Request | |||
|![Dashboard](https://dl.gitea.com/screenshots/home_timeline.png)|![User Profile](https://dl.gitea.com/screenshots/user_profile.png)|![Global Issues](https://dl.gitea.com/screenshots/global_issues.png)| | |||
|:---:|:---:|:---:| | |||
|![Branches](https://dl.gitea.com/screenshots/branches.png)|![Web Editor](https://dl.gitea.com/screenshots/web_editor.png)|![Activity](https://dl.gitea.com/screenshots/activity.png)| | |||
|![New Migration](https://dl.gitea.com/screenshots/migration.png)|![Migrating](https://dl.gitea.com/screenshots/migration.gif)|![Pull Request View](https://image.ibb.co/e02dSb/6.png) | |||
![Pull Request Dark](https://dl.gitea.com/screenshots/pull_requests_dark.png)|![Diff Review Dark](https://dl.gitea.com/screenshots/review_dark.png)|![Diff Dark](https://dl.gitea.com/screenshots/diff_dark.png)| | |||
|![New Migration](https://dl.gitea.com/screenshots/migration.png)|![Migrating](https://dl.gitea.com/screenshots/migration.gif)|![Pull Request View](https://image.ibb.co/e02dSb/6.png)| | |||
|![Pull Request Dark](https://dl.gitea.com/screenshots/pull_requests_dark.png)|![Diff Review Dark](https://dl.gitea.com/screenshots/review_dark.png)|![Diff Dark](https://dl.gitea.com/screenshots/diff_dark.png)| |
@@ -50,6 +50,6 @@ func runGenerateActionsRunnerToken(c *cli.Context) error { | |||
if extra.HasError() { | |||
return handleCliResponseExtra(extra) | |||
} | |||
_, _ = fmt.Printf("%s\n", respText) | |||
_, _ = fmt.Printf("%s\n", respText.Text) | |||
return nil | |||
} |
@@ -11,6 +11,7 @@ import ( | |||
"code.gitea.io/gitea/models/db" | |||
repo_model "code.gitea.io/gitea/models/repo" | |||
"code.gitea.io/gitea/modules/git" | |||
"code.gitea.io/gitea/modules/gitrepo" | |||
"code.gitea.io/gitea/modules/log" | |||
repo_module "code.gitea.io/gitea/modules/repository" | |||
@@ -122,7 +123,7 @@ func runRepoSyncReleases(_ *cli.Context) error { | |||
log.Trace("Processing next %d repos of %d", len(repos), count) | |||
for _, repo := range repos { | |||
log.Trace("Synchronizing repo %s with path %s", repo.FullName(), repo.RepoPath()) | |||
gitRepo, err := git.OpenRepository(ctx, repo.RepoPath()) | |||
gitRepo, err := gitrepo.OpenRepository(ctx, repo) | |||
if err != nil { | |||
log.Warn("OpenRepository: %v", err) | |||
continue | |||
@@ -157,10 +158,10 @@ func runRepoSyncReleases(_ *cli.Context) error { | |||
} | |||
func getReleaseCount(ctx context.Context, id int64) (int64, error) { | |||
return repo_model.GetReleaseCountByRepoID( | |||
return db.Count[repo_model.Release]( | |||
ctx, | |||
id, | |||
repo_model.FindReleasesOptions{ | |||
RepoID: id, | |||
IncludeTags: true, | |||
}, | |||
) |
@@ -4,8 +4,8 @@ | |||
package cmd | |||
import ( | |||
asymkey_model "code.gitea.io/gitea/models/asymkey" | |||
"code.gitea.io/gitea/modules/graceful" | |||
asymkey_service "code.gitea.io/gitea/services/asymkey" | |||
repo_service "code.gitea.io/gitea/services/repository" | |||
"github.com/urfave/cli/v2" | |||
@@ -42,5 +42,5 @@ func runRegenerateKeys(_ *cli.Context) error { | |||
if err := initDB(ctx); err != nil { | |||
return err | |||
} | |||
return asymkey_model.RewriteAllPublicKeys(ctx) | |||
return asymkey_service.RewriteAllPublicKeys(ctx) | |||
} |
@@ -4,13 +4,14 @@ | |||
package cmd | |||
import ( | |||
"context" | |||
"errors" | |||
"fmt" | |||
user_model "code.gitea.io/gitea/models/user" | |||
pwd "code.gitea.io/gitea/modules/auth/password" | |||
"code.gitea.io/gitea/modules/auth/password" | |||
"code.gitea.io/gitea/modules/optional" | |||
"code.gitea.io/gitea/modules/setting" | |||
user_service "code.gitea.io/gitea/services/user" | |||
"github.com/urfave/cli/v2" | |||
) | |||
@@ -32,6 +33,10 @@ var microcmdUserChangePassword = &cli.Command{ | |||
Value: "", | |||
Usage: "New password to set for user", | |||
}, | |||
&cli.BoolFlag{ | |||
Name: "must-change-password", | |||
Usage: "User must change password", | |||
}, | |||
}, | |||
} | |||
@@ -46,31 +51,32 @@ func runChangePassword(c *cli.Context) error { | |||
if err := initDB(ctx); err != nil { | |||
return err | |||
} | |||
if len(c.String("password")) < setting.MinPasswordLength { | |||
return fmt.Errorf("Password is not long enough. Needs to be at least %d", setting.MinPasswordLength) | |||
} | |||
if !pwd.IsComplexEnough(c.String("password")) { | |||
return errors.New("Password does not meet complexity requirements") | |||
} | |||
pwned, err := pwd.IsPwned(context.Background(), c.String("password")) | |||
user, err := user_model.GetUserByName(ctx, c.String("username")) | |||
if err != nil { | |||
return err | |||
} | |||
if pwned { | |||
return errors.New("The password you chose is on a list of stolen passwords previously exposed in public data breaches. Please try again with a different password.\nFor more details, see https://haveibeenpwned.com/Passwords") | |||
} | |||
uname := c.String("username") | |||
user, err := user_model.GetUserByName(ctx, uname) | |||
if err != nil { | |||
return err | |||
} | |||
if err = user.SetPassword(c.String("password")); err != nil { | |||
return err | |||
var mustChangePassword optional.Option[bool] | |||
if c.IsSet("must-change-password") { | |||
mustChangePassword = optional.Some(c.Bool("must-change-password")) | |||
} | |||
if err = user_model.UpdateUserCols(ctx, user, "passwd", "passwd_hash_algo", "salt"); err != nil { | |||
return err | |||
opts := &user_service.UpdateAuthOptions{ | |||
Password: optional.Some(c.String("password")), | |||
MustChangePassword: mustChangePassword, | |||
} | |||
if err := user_service.UpdateAuth(ctx, user, opts); err != nil { | |||
switch { | |||
case errors.Is(err, password.ErrMinLength): | |||
return fmt.Errorf("Password is not long enough. Needs to be at least %d", setting.MinPasswordLength) | |||
case errors.Is(err, password.ErrComplexity): | |||
return errors.New("Password does not meet complexity requirements") | |||
case errors.Is(err, password.ErrIsPwned): | |||
return errors.New("The password you chose is on a list of stolen passwords previously exposed in public data breaches. Please try again with a different password.\nFor more details, see https://haveibeenpwned.com/Passwords") | |||
default: | |||
return err | |||
} | |||
} | |||
fmt.Printf("%s's password has been successfully updated!\n", user.Name) |
@@ -10,8 +10,8 @@ import ( | |||
auth_model "code.gitea.io/gitea/models/auth" | |||
user_model "code.gitea.io/gitea/models/user" | |||
pwd "code.gitea.io/gitea/modules/auth/password" | |||
"code.gitea.io/gitea/modules/optional" | |||
"code.gitea.io/gitea/modules/setting" | |||
"code.gitea.io/gitea/modules/util" | |||
"github.com/urfave/cli/v2" | |||
) | |||
@@ -123,10 +123,10 @@ func runCreateUser(c *cli.Context) error { | |||
changePassword = c.Bool("must-change-password") | |||
} | |||
restricted := util.OptionalBoolNone | |||
restricted := optional.None[bool]() | |||
if c.IsSet("restricted") { | |||
restricted = util.OptionalBoolOf(c.Bool("restricted")) | |||
restricted = optional.Some(c.Bool("restricted")) | |||
} | |||
// default user visibility in app.ini | |||
@@ -142,7 +142,7 @@ func runCreateUser(c *cli.Context) error { | |||
} | |||
overwriteDefault := &user_model.CreateUserOverwriteOptions{ | |||
IsActive: util.OptionalBoolTrue, | |||
IsActive: optional.Some(true), | |||
IsRestricted: restricted, | |||
} | |||
@@ -15,9 +15,9 @@ import ( | |||
"code.gitea.io/gitea/models/migrations" | |||
migrate_base "code.gitea.io/gitea/models/migrations/base" | |||
"code.gitea.io/gitea/modules/container" | |||
"code.gitea.io/gitea/modules/doctor" | |||
"code.gitea.io/gitea/modules/log" | |||
"code.gitea.io/gitea/modules/setting" | |||
"code.gitea.io/gitea/services/doctor" | |||
"github.com/urfave/cli/v2" | |||
"xorm.io/xorm" |
@@ -7,8 +7,8 @@ import ( | |||
"context" | |||
"testing" | |||
"code.gitea.io/gitea/modules/doctor" | |||
"code.gitea.io/gitea/modules/log" | |||
"code.gitea.io/gitea/services/doctor" | |||
"github.com/stretchr/testify/assert" | |||
"github.com/urfave/cli/v2" |
@@ -70,7 +70,7 @@ func runGenerateInternalToken(c *cli.Context) error { | |||
} | |||
func runGenerateLfsJwtSecret(c *cli.Context) error { | |||
_, jwtSecretBase64, err := generate.NewJwtSecretBase64() | |||
_, jwtSecretBase64, err := generate.NewJwtSecretWithBase64() | |||
if err != nil { | |||
return err | |||
} |
@@ -71,13 +71,13 @@ func runKeys(c *cli.Context) error { | |||
ctx, cancel := installSignals() | |||
defer cancel() | |||
setup(ctx, false) | |||
setup(ctx, c.Bool("debug")) | |||
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 | |||
} | |||
_, _ = fmt.Fprintln(c.App.Writer, strings.TrimSpace(authorizedString)) | |||
_, _ = fmt.Fprintln(c.App.Writer, strings.TrimSpace(authorizedString.Text)) | |||
return nil | |||
} |
@@ -45,6 +45,6 @@ func runSendMail(c *cli.Context) error { | |||
if extra.HasError() { | |||
return handleCliResponseExtra(extra) | |||
} | |||
_, _ = fmt.Printf("Sent %s email(s) to all users\n", respText) | |||
_, _ = fmt.Printf("Sent %s email(s) to all users\n", respText.Text) | |||
return nil | |||
} |
@@ -110,6 +110,9 @@ func migrateLFS(ctx context.Context, dstStorage storage.ObjectStorage) error { | |||
func migrateAvatars(ctx context.Context, dstStorage storage.ObjectStorage) error { | |||
return db.Iterate(ctx, nil, func(ctx context.Context, user *user_model.User) error { | |||
if user.CustomAvatarRelativePath() == "" { | |||
return nil | |||
} | |||
_, err := storage.Copy(dstStorage, user.CustomAvatarRelativePath(), storage.Avatars, user.CustomAvatarRelativePath()) | |||
return err | |||
}) | |||
@@ -117,6 +120,9 @@ func migrateAvatars(ctx context.Context, dstStorage storage.ObjectStorage) error | |||
func migrateRepoAvatars(ctx context.Context, dstStorage storage.ObjectStorage) error { | |||
return db.Iterate(ctx, nil, func(ctx context.Context, repo *repo_model.Repository) error { | |||
if repo.CustomAvatarRelativePath() == "" { | |||
return nil | |||
} | |||
_, err := storage.Copy(dstStorage, repo.CustomAvatarRelativePath(), storage.RepoAvatars, repo.CustomAvatarRelativePath()) | |||
return err | |||
}) |
@@ -63,21 +63,10 @@ func setup(ctx context.Context, debug bool) { | |||
setupConsoleLogger(log.FATAL, false, os.Stderr) | |||
} | |||
setting.MustInstalled() | |||
if debug { | |||
setting.RunMode = "dev" | |||
} | |||
// Check if setting.RepoRootPath exists. It could be the case that it doesn't exist, this can happen when | |||
// `[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) | |||
} else { | |||
_ = fail(ctx, "Incorrect configuration, repository directory is inaccessible", "Directory `[repository].ROOT` %q is inaccessible. err: %v", setting.RepoRootPath, err) | |||
} | |||
_ = fail(ctx, "Unable to access repository path", "Unable to access repository path %q, 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) | |||
} | |||
@@ -216,16 +205,18 @@ func runServ(c *cli.Context) error { | |||
} | |||
} | |||
// LowerCase and trim the repoPath as that's how they are stored. | |||
repoPath = strings.ToLower(strings.TrimSpace(repoPath)) | |||
rr := strings.SplitN(repoPath, "/", 2) | |||
if len(rr) != 2 { | |||
return fail(ctx, "Invalid repository path", "Invalid repository path: %v", repoPath) | |||
} | |||
username := strings.ToLower(rr[0]) | |||
reponame := strings.ToLower(strings.TrimSuffix(rr[1], ".git")) | |||
username := rr[0] | |||
reponame := strings.TrimSuffix(rr[1], ".git") | |||
// LowerCase and trim the repoPath as that's how they are stored. | |||
// This should be done after splitting the repoPath into username and reponame | |||
// so that username and reponame are not affected. | |||
repoPath = strings.ToLower(strings.TrimSpace(repoPath)) | |||
if alphaDashDotPattern.MatchString(reponame) { | |||
return fail(ctx, "Invalid repo name", "Invalid repo name: %s", reponame) |
@@ -1,6 +1,5 @@ | |||
[Unit] | |||
Description=Gitea (Git with a cup of tea) | |||
After=syslog.target | |||
After=network.target | |||
### | |||
# Don't forget to add the database service dependencies |
@@ -412,6 +412,10 @@ USER = root | |||
;; | |||
;; Whether execute database models migrations automatically | |||
;AUTO_MIGRATION = true | |||
;; | |||
;; Threshold value (in seconds) beyond which query execution time is logged as a warning in the xorm logger | |||
;; | |||
;SLOW_QUERY_THRESHOLD = 5s | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
@@ -431,7 +435,7 @@ SECRET_KEY = | |||
;SECRET_KEY_URI = file:/etc/gitea/secret_key | |||
;; | |||
;; Secret used to validate communication within Gitea binary. | |||
INTERNAL_TOKEN= | |||
INTERNAL_TOKEN = | |||
;; | |||
;; Alternative location to specify internal token, instead of this file; you cannot specify both this and INTERNAL_TOKEN, and must pick one | |||
;INTERNAL_TOKEN_URI = file:/etc/gitea/internal_token | |||
@@ -524,7 +528,7 @@ INTERNAL_TOKEN= | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
;; | |||
;; Enables OAuth2 provider | |||
ENABLE = true | |||
ENABLED = true | |||
;; | |||
;; Algorithm used to sign OAuth2 tokens. Valid values: HS256, HS384, HS512, RS256, RS384, RS512, ES256, ES384, ES512, EdDSA | |||
;JWT_SIGNING_ALGORITHM = RS256 | |||
@@ -952,6 +956,12 @@ LEVEL = Info | |||
;GO_GET_CLONE_URL_PROTOCOL = https | |||
;; | |||
;; Close issues as long as a commit on any branch marks it as fixed | |||
;DEFAULT_CLOSE_ISSUES_VIA_COMMITS_IN_ANY_BRANCH = false | |||
;; | |||
;; Allow users to push local repositories to Gitea and have them automatically created for a user or an org | |||
;ENABLE_PUSH_CREATE_USER = false | |||
;ENABLE_PUSH_CREATE_ORG = false | |||
;; | |||
;; 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 = | |||
;; | |||
@@ -1044,7 +1054,7 @@ LEVEL = Info | |||
;; List of keywords used in Pull Request comments to automatically reopen a related issue | |||
;REOPEN_KEYWORDS = reopen,reopens,reopened | |||
;; | |||
;; Set default merge style for repository creating, valid options: merge, rebase, rebase-merge, squash | |||
;; Set default merge style for repository creating, valid options: merge, rebase, rebase-merge, squash, fast-forward-only | |||
;DEFAULT_MERGE_STYLE = merge | |||
;; | |||
;; In the default merge message for squash commits include at most this many commits | |||
@@ -1067,6 +1077,9 @@ LEVEL = Info | |||
;; | |||
;; In addition to testing patches using the three-way merge method, re-test conflicting patches with git apply | |||
;TEST_CONFLICTING_PATCHES_WITH_GIT_APPLY = false | |||
;; | |||
;; Retarget child pull requests to the parent pull request branch target on merge of parent pull request. It only works on merged PRs where the head and base branch target the same repo. | |||
;RETARGET_CHILDREN_ON_MERGE = true | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
@@ -1467,6 +1480,11 @@ LEVEL = Info | |||
;; | |||
;; Default configuration for email notifications for users (user configurable). Options: enabled, onmention, disabled | |||
;DEFAULT_EMAIL_NOTIFICATIONS = enabled | |||
;; Disabled features for users, could be "deletion", "manage_ssh_keys","manage_gpg_keys" more features can be disabled in future | |||
;; - deletion: a user cannot delete their own account | |||
;; - manage_ssh_keys: a user cannot configure ssh keys | |||
;; - manage_gpg_keys: a user cannot configure gpg keys | |||
;USER_DISABLED_FEATURES = | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
@@ -2590,7 +2608,7 @@ LEVEL = Info | |||
;ENDLESS_TASK_TIMEOUT = 3h | |||
;; Timeout to cancel the jobs which have waiting status, but haven't been picked by a runner for a long time | |||
;ABANDONED_JOB_TIMEOUT = 24h | |||
;; Strings committers can place inside a commit message to skip executing the corresponding actions workflow | |||
;; Strings committers can place inside a commit message or PR title to skip executing the corresponding actions workflow | |||
;SKIP_WORKFLOW_STRINGS = [skip ci],[ci skip],[no ci],[skip actions],[actions skip] | |||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
@@ -92,7 +92,7 @@ cd gitea-dump-1610949662 | |||
mv app.ini /etc/gitea/conf/app.ini | |||
mv data/* /var/lib/gitea/data/ | |||
mv log/* /var/lib/gitea/log/ | |||
mv repos/* /var/lib/gitea/gitea-repositories/ | |||
mv repos/* /var/lib/gitea/data/gitea-repositories/ | |||
chown -R gitea:gitea /etc/gitea/conf/app.ini /var/lib/gitea | |||
# mysql | |||
@@ -111,6 +111,8 @@ With Gitea running, and from the directory Gitea's binary is located, execute: ` | |||
This ensures that application and configuration file paths in repository Git Hooks are consistent and applicable to the current installation. If these paths are not updated, repository `push` actions will fail. | |||
If you still have issues, consider running `./gitea doctor check` to inspect possible errors (or run with `--fix`). | |||
### Using Docker (`restore`) | |||
There is also no support for a recovery command in a Docker-based gitea instance. The restore process contains the same steps as described in the previous section but with different paths. |
@@ -19,6 +19,12 @@ menu: | |||
Gitea 已经实现了 `dump` 命令可以用来备份所有需要的文件到一个zip压缩文件。该压缩文件可以被用来进行数据恢复。 | |||
## 备份一致性 | |||
为了确保 Gitea 实例的一致性,在备份期间必须关闭它。 | |||
Gitea 包括数据库、文件和 Git 仓库,当它被使用时所有这些都会发生变化。例如,当迁移正在进行时,在数据库中创建一个事务,而 Git 仓库正在被复制。如果备份发生在迁移的中间,Git 仓库可能是不完整的,尽管数据库声称它是完整的,因为它是在之后被转储的。避免这种竞争条件的唯一方法是在备份期间停止 Gitea 实例。 | |||
## 备份命令 (`dump`) | |||
先转到git用户的权限: `su git`. 再Gitea目录运行 `./gitea dump`。一般会显示类似如下的输出: | |||
@@ -34,15 +40,43 @@ Gitea 已经实现了 `dump` 命令可以用来备份所有需要的文件到一 | |||
最后生成的 `gitea-dump-1482906742.zip` 文件将会包含如下内容: | |||
* `custom` - 所有保存在 `custom/` 目录下的配置和自定义的文件。 | |||
* `data` - 数据目录下的所有内容不包含使用文件session的文件。该目录包含 `attachments`, `avatars`, `lfs`, `indexers`, 如果使用sqlite 还会包含 sqlite 数据库文件。 | |||
* `app.ini` - 如果原先存储在默认的 custom/ 目录之外,则是配置文件的可选副本 | |||
* `custom/` - 所有保存在 `custom/` 目录下的配置和自定义的文件。 | |||
* `data/` - 数据目录(APP_DATA_PATH),如果使用文件会话,则不包括会话。该目录包括 `attachments`、`avatars`、`lfs`、`indexers`、如果使用 SQLite 则包括 SQLite 文件。 | |||
* `repos/` - 仓库目录的完整副本。 | |||
* `gitea-db.sql` - 数据库dump出来的 SQL。 | |||
* `gitea-repo.zip` - Git仓库压缩文件。 | |||
* `log/` - Logs文件,如果用作迁移不是必须的。 | |||
中间备份文件将会在临时目录进行创建,如果您要重新指定临时目录,可以用 `--tempdir` 参数,或者用 `TMPDIR` 环境变量。 | |||
## Restore Command (`restore`) | |||
## 备份数据库 | |||
`gitea dump` 创建的 SQL 转储使用 XORM,Gitea 管理员可能更喜欢使用本地的 MySQL 和 PostgreSQL 转储工具。使用 XORM 转储数据库时仍然存在一些问题,可能会导致在尝试恢复时出现问题。 | |||
```sh | |||
# mysql | |||
mysqldump -u$USER -p$PASS --database $DATABASE > gitea-db.sql | |||
# postgres | |||
pg_dump -U $USER $DATABASE > gitea-db.sql | |||
``` | |||
### 使用Docker (`dump`) | |||
在使用 Docker 时,使用 `dump` 命令有一些注意事项。 | |||
必须以 `gitea/conf/app.ini` 中指定的 `RUN_USER = <OS_USERNAME>` 执行该命令;并且,为了让备份文件夹的压缩过程能够顺利执行,`docker exec` 命令必须在 `--tempdir` 内部执行。 | |||
示例: | |||
```none | |||
docker exec -u <OS_USERNAME> -it -w <--tempdir> $(docker ps -qf 'name=^<NAME_OF_DOCKER_CONTAINER>$') bash -c '/usr/local/bin/gitea dump -c </path/to/app.ini>' | |||
``` | |||
\*注意:`--tempdir` 指的是 Gitea 使用的 Docker 环境的临时目录;如果您没有指定自定义的 `--tempdir`,那么 Gitea 将使用 `/tmp` 或 Docker 容器的 `TMPDIR` 环境变量。对于 `--tempdir`,请相应调整您的 `docker exec` 命令选项。 | |||
结果应该是一个文件,存储在指定的 `--tempdir` 中,类似于:`gitea-dump-1482906742.zip` | |||
## 恢复命令 (`restore`) | |||
当前还没有恢复命令,恢复需要人工进行。主要是把文件和数据库进行恢复。 | |||
@@ -51,10 +85,10 @@ Gitea 已经实现了 `dump` 命令可以用来备份所有需要的文件到一 | |||
```sh | |||
unzip gitea-dump-1610949662.zip | |||
cd gitea-dump-1610949662 | |||
mv data/conf/app.ini /etc/gitea/conf/app.ini | |||
mv app.ini /etc/gitea/conf/app.ini | |||
mv data/* /var/lib/gitea/data/ | |||
mv log/* /var/lib/gitea/log/ | |||
mv repos/* /var/lib/gitea/repositories/ | |||
mv repos/* /var/lib/gitea/gitea-repositories/ | |||
chown -R gitea:gitea /etc/gitea/conf/app.ini /var/lib/gitea | |||
# mysql | |||
@@ -66,3 +100,55 @@ psql -U $USER -d $DATABASE < gitea-db.sql | |||
service gitea restart | |||
``` | |||
如果安装方式发生了变化(例如 二进制 -> Docker),或者 Gitea 安装到了与之前安装不同的目录,则需要重新生成仓库 Git 钩子。 | |||
在 Gitea 运行时,并从 Gitea 二进制文件所在的目录执行:`./gitea admin regenerate hooks` | |||
这样可以确保仓库 Git 钩子中的应用程序和配置文件路径与当前安装一致。如果这些路径没有更新,仓库的 `push` 操作将失败。 | |||
### 使用 Docker (`restore`) | |||
在基于 Docker 的 Gitea 实例中,也没有恢复命令的支持。恢复过程与前面描述的步骤相同,但路径不同。 | |||
示例: | |||
```sh | |||
# 在容器中打开 bash 会话 | |||
docker exec --user git -it 2a83b293548e bash | |||
# 在容器内解压您的备份文件 | |||
unzip gitea-dump-1610949662.zip | |||
cd gitea-dump-1610949662 | |||
# 恢复 Gitea 数据 | |||
mv data/* /data/gitea | |||
# 恢复仓库本身 | |||
mv repos/* /data/git/gitea-repositories/ | |||
# 调整文件权限 | |||
chown -R git:git /data | |||
# 重新生成 Git 钩子 | |||
/usr/local/bin/gitea -c '/data/gitea/conf/app.ini' admin regenerate hooks | |||
``` | |||
Gitea 容器中的默认用户是 `git`(1000:1000)。请用您的 Gitea 容器 ID 或名称替换 `2a83b293548e`。 | |||
### 使用 Docker-rootless (`restore`) | |||
在 Docker-rootless 容器中的恢复工作流程只是要使用的目录不同: | |||
```sh | |||
# 在容器中打开 bash 会话 | |||
docker exec --user git -it 2a83b293548e bash | |||
# 在容器内解压您的备份文件 | |||
unzip gitea-dump-1610949662.zip | |||
cd gitea-dump-1610949662 | |||
# 恢复 app.ini | |||
mv data/conf/app.ini /etc/gitea/app.ini | |||
# 恢复 Gitea 数据 | |||
mv data/* /var/lib/gitea | |||
# 恢复仓库本身 | |||
mv repos/* /var/lib/gitea/git/gitea-repositories | |||
# 调整文件权限 | |||
chown -R git:git /etc/gitea/app.ini /var/lib/gitea | |||
# 重新生成 Git 钩子 | |||
/usr/local/bin/gitea -c '/etc/gitea/app.ini' admin regenerate hooks | |||
``` |
@@ -37,7 +37,7 @@ gitea embedded list [--include-vendored] [patterns...] | |||
- 列出所有模板文件,无论在哪个虚拟目录下:`**.tmpl` | |||
- 列出所有邮件模板文件:`templates/mail/**.tmpl` | |||
- 列出 `public/img` 目录下的所有文件:`public/img/**` | |||
列出 `public/assets/img` 目录下的所有文件:`public/assets/img/**` | |||
不要忘记为模式使用引号,因为空格、`*` 和其他字符可能对命令行解释器有特殊含义。 | |||
@@ -49,8 +49,8 @@ gitea embedded list [--include-vendored] [patterns...] | |||
```sh | |||
$ gitea embedded list '**openid**' | |||
public/img/auth/openid_connect.svg | |||
public/img/openid-16x16.png | |||
public/assets/img/auth/openid_connect.svg | |||
public/assets/img/openid-16x16.png | |||
templates/user/auth/finalize_openid.tmpl | |||
templates/user/auth/signin_openid.tmpl | |||
templates/user/auth/signup_openid_connect.tmpl |
@@ -95,6 +95,7 @@ Admin operations: | |||
- Options: | |||
- `--username value`, `-u value`: Username. Required. | |||
- `--password value`, `-p value`: New password. Required. | |||
- `--must-change-password`: If provided, the user is required to choose a new password after the login. Optional. | |||
- Examples: | |||
- `gitea admin user change-password --username myname --password asecurepassword` | |||
- `must-change-password`: |
@@ -126,7 +126,7 @@ In addition, there is _`StaticRootPath`_ which can be set as a built-in at build | |||
keywords used in Pull Request comments to automatically close a related issue | |||
- `REOPEN_KEYWORDS`: **reopen**, **reopens**, **reopened**: List of keywords used in Pull Request comments to automatically reopen | |||
a related issue | |||
- `DEFAULT_MERGE_STYLE`: **merge**: Set default merge style for repository creating, valid options: `merge`, `rebase`, `rebase-merge`, `squash` | |||
- `DEFAULT_MERGE_STYLE`: **merge**: Set default merge style for repository creating, valid options: `merge`, `rebase`, `rebase-merge`, `squash`, `fast-forward-only` | |||
- `DEFAULT_MERGE_MESSAGE_COMMITS_LIMIT`: **50**: In the default merge message for squash commits include at most this many commits. Set to `-1` to include all commits | |||
- `DEFAULT_MERGE_MESSAGE_SIZE`: **5120**: In the default merge message for squash commits limit the size of the commit messages. Set to `-1` to have no limit. Only used if `POPULATE_SQUASH_COMMENT_WITH_COMMIT_MESSAGES` is `true`. | |||
- `DEFAULT_MERGE_MESSAGE_ALL_AUTHORS`: **false**: In the default merge message for squash commits walk all commits to include all authors in the Co-authored-by otherwise just use those in the limited list | |||
@@ -135,6 +135,7 @@ In addition, there is _`StaticRootPath`_ which can be set as a built-in at build | |||
- `POPULATE_SQUASH_COMMENT_WITH_COMMIT_MESSAGES`: **false**: In default squash-merge messages include the commit message of all commits comprising the pull request. | |||
- `ADD_CO_COMMITTER_TRAILERS`: **true**: Add co-authored-by and co-committed-by trailers to merge commit messages if committer does not match author. | |||
- `TEST_CONFLICTING_PATCHES_WITH_GIT_APPLY`: **false**: PR patches are tested using a three-way merge method to discover if there are conflicts. If this setting is set to **true**, conflicting patches will be retested using `git apply` - This was the previous behaviour in 1.18 (and earlier) but is somewhat inefficient. Please report if you find that this setting is required. | |||
- `RETARGET_CHILDREN_ON_MERGE`: **true**: Retarget child pull requests to the parent pull request branch target on merge of parent pull request. It only works on merged PRs where the head and base branch target the same repo. | |||
### Repository - Issue (`repository.issue`) | |||
@@ -457,6 +458,7 @@ The following configuration set `Content-Type: application/vnd.android.package-a | |||
- `MAX_IDLE_CONNS` **2**: Max idle database connections on connection pool, default is 2 - this will be capped to `MAX_OPEN_CONNS`. | |||
- `CONN_MAX_LIFETIME` **0 or 3s**: Sets the maximum amount of time a DB connection may be reused - default is 0, meaning there is no limit (except on MySQL where it is 3s - see #6804 & #7071). | |||
- `AUTO_MIGRATION` **true**: Whether execute database models migrations automatically. | |||
- `SLOW_QUERY_THRESHOLD` **5s**: Threshold value in seconds beyond which query execution time is logged as a warning in the xorm logger. | |||
[^1]: It may be necessary to specify a hostport even when listening on a unix socket, as the port is part of the socket name. see [#24552](https://github.com/go-gitea/gitea/issues/24552#issuecomment-1681649367) for additional details. | |||
@@ -516,6 +518,10 @@ And the following unique queues: | |||
- `DEFAULT_EMAIL_NOTIFICATIONS`: **enabled**: Default configuration for email notifications for users (user configurable). Options: enabled, onmention, disabled | |||
- `DISABLE_REGULAR_ORG_CREATION`: **false**: Disallow regular (non-admin) users from creating organizations. | |||
- `USER_DISABLED_FEATURES`: **_empty_** Disabled features for users, could be `deletion`, `manage_ssh_keys`, `manage_gpg_keys` and more features can be added in future. | |||
- `deletion`: User cannot delete their own account. | |||
- `manage_ssh_keys`: User cannot configure ssh keys. | |||
- `manage_gpg_keys`: User cannot configure gpg keys. | |||
## Security (`security`) | |||
@@ -826,7 +832,7 @@ Default templates for project boards: | |||
## Issue and pull request attachments (`attachment`) | |||
- `ENABLED`: **true**: Whether issue and pull request attachments are enabled. | |||
- `ALLOWED_TYPES`: **.csv,.docx,.fodg,.fodp,.fods,.fodt,.gif,.gz,.jpeg,.jpg,.log,.md,.mov,.mp4,.odf,.odg,.odp,.ods,.odt,.patch,.pdf,.png,.pptx,.svg,.tgz,.txt,.webm,.xls,.xlsx,.zip**: Comma-separated list of allowed file extensions (`.zip`), mime types (`text/plain`) or wildcard type (`image/*`, `audio/*`, `video/*`). Empty value or `*/*` allows all types. | |||
- `ALLOWED_TYPES`: **.cpuprofile,.csv,.dmp,.docx,.fodg,.fodp,.fods,.fodt,.gif,.gz,.jpeg,.jpg,.json,.jsonc,.log,.md,.mov,.mp4,.odf,.odg,.odp,.ods,.odt,.patch,.pdf,.png,.pptx,.svg,.tgz,.txt,.webm,.xls,.xlsx,.zip**: Comma-separated list of allowed file extensions (`.zip`), mime types (`text/plain`) or wildcard type (`image/*`, `audio/*`, `video/*`). Empty value or `*/*` allows all types. | |||
- `MAX_SIZE`: **2048**: Maximum size (MB). | |||
- `MAX_FILES`: **5**: Maximum number of attachments that can be uploaded at once. | |||
- `STORAGE_TYPE`: **local**: Storage type for attachments, `local` for local disk or `minio` for s3 compatible object storage service, default is `local` or other name defined with `[storage.xxx]` | |||
@@ -1106,7 +1112,7 @@ This section only does "set" config, a removed config key from this section won' | |||
## OAuth2 (`oauth2`) | |||
- `ENABLE`: **true**: Enables OAuth2 provider. | |||
- `ENABLED`: **true**: Enables OAuth2 provider. | |||
- `ACCESS_TOKEN_EXPIRATION_TIME`: **3600**: Lifetime of an OAuth2 access token in seconds | |||
- `REFRESH_TOKEN_EXPIRATION_TIME`: **730**: Lifetime of an OAuth2 refresh token in hours | |||
- `INVALIDATE_REFRESH_TOKENS`: **false**: Check if refresh token has already been used | |||
@@ -1400,7 +1406,7 @@ PROXY_HOSTS = *.github.com | |||
- `ZOMBIE_TASK_TIMEOUT`: **10m**: Timeout to stop the task which have running status, but haven't been updated for a long time | |||
- `ENDLESS_TASK_TIMEOUT`: **3h**: Timeout to stop the tasks which have running status and continuous updates, but don't end for a long time | |||
- `ABANDONED_JOB_TIMEOUT`: **24h**: Timeout to cancel the jobs which have waiting status, but haven't been picked by a runner for a long time | |||
- `SKIP_WORKFLOW_STRINGS`: **[skip ci],[ci skip],[no ci],[skip actions],[actions skip]**: Strings committers can place inside a commit message to skip executing the corresponding actions workflow | |||
- `SKIP_WORKFLOW_STRINGS`: **[skip ci],[ci skip],[no ci],[skip actions],[actions skip]**: Strings committers can place inside a commit message or PR title to skip executing the corresponding actions workflow | |||
`DEFAULT_ACTIONS_URL` indicates where the Gitea Actions runners should find the actions with relative path. | |||
For example, `uses: actions/checkout@v4` means `https://github.com/actions/checkout@v4` since the value of `DEFAULT_ACTIONS_URL` is `github`. |
@@ -29,7 +29,7 @@ menu: | |||
[ini](https://github.com/go-ini/ini/#recursive-values) 这里的说明。 | |||
标注了 :exclamation: 的配置项表明除非你真的理解这个配置项的意义,否则最好使用默认值。 | |||
在下面的默认值中,`$XYZ`代表环境变量`XYZ`的值(详见:`enviroment-to-ini`)。 _`XxYyZz`_是指默认配置的一部分列出的值。这些在 app.ini 文件中不起作用,仅在此处列出作为文档说明。 | |||
在下面的默认值中,`$XYZ`代表环境变量`XYZ`的值(详见:`environment-to-ini`)。 _`XxYyZz`_是指默认配置的一部分列出的值。这些在 app.ini 文件中不起作用,仅在此处列出作为文档说明。 | |||
包含`#`或者`;`的变量必须使用引号(`` ` ``或者`""""`)包裹,否则会被解析为注释。 | |||
@@ -125,7 +125,7 @@ menu: | |||
- `CLOSE_KEYWORDS`: **close**, **closes**, **closed**, **fix**, **fixes**, **fixed**, **resolve**, **resolves**, **resolved**: 在拉取请求评论中用于自动关闭相关问题的关键词列表。 | |||
- `REOPEN_KEYWORDS`: **reopen**, **reopens**, **reopened**: 在拉取请求评论中用于自动重新打开相关问题的 | |||
关键词列表。 | |||
- `DEFAULT_MERGE_STYLE`: **merge**: 设置创建仓库的默认合并方式,可选: `merge`, `rebase`, `rebase-merge`, `squash` | |||
- `DEFAULT_MERGE_STYLE`: **merge**: 设置创建仓库的默认合并方式,可选: `merge`, `rebase`, `rebase-merge`, `squash`, `fast-forward-only` | |||
- `DEFAULT_MERGE_MESSAGE_COMMITS_LIMIT`: **50**: 在默认合并消息中,对于`squash`提交,最多包括此数量的提交。设置为 -1 以包括所有提交。 | |||
- `DEFAULT_MERGE_MESSAGE_SIZE`: **5120**: 在默认的合并消息中,对于`squash`提交,限制提交消息的大小。设置为 `-1`以取消限制。仅在`POPULATE_SQUASH_COMMENT_WITH_COMMIT_MESSAGES`为`true`时使用。 | |||
- `DEFAULT_MERGE_MESSAGE_ALL_AUTHORS`: **false**: 在默认合并消息中,对于`squash`提交,遍历所有提交以包括所有作者的`Co-authored-by`,否则仅使用限定列表中的作者。 | |||
@@ -497,6 +497,10 @@ Gitea 创建以下非唯一队列: | |||
- `DEFAULT_EMAIL_NOTIFICATIONS`: **enabled**:用户电子邮件通知的默认配置(用户可配置)。选项:enabled、onmention、disabled | |||
- `DISABLE_REGULAR_ORG_CREATION`: **false**:禁止普通(非管理员)用户创建组织。 | |||
- `USER_DISABLED_FEATURES`:**_empty_** 禁用的用户特性,当前允许为空或者 `deletion`,`manage_ssh_keys`, `manage_gpg_keys` 未来可以增加更多设置。 | |||
- `deletion`: 用户不能通过界面或者API删除他自己。 | |||
- `manage_ssh_keys`: 用户不能通过界面或者API配置SSH Keys。 | |||
- `manage_gpg_keys`: 用户不能配置 GPG 密钥。 | |||
## 安全性 (`security`) | |||
@@ -778,7 +782,7 @@ Gitea 创建以下非唯一队列: | |||
## 工单和合并请求的附件 (`attachment`) | |||
- `ENABLED`: **true**: 是否允许用户上传附件。 | |||
- `ALLOWED_TYPES`: **.csv,.docx,.fodg,.fodp,.fods,.fodt,.gif,.gz,.jpeg,.jpg,.log,.md,.mov,.mp4,.odf,.odg,.odp,.ods,.odt,.patch,.pdf,.png,.pptx,.svg,.tgz,.txt,.webm,.xls,.xlsx,.zip**: 允许的文件扩展名(`.zip`)、mime 类型(`text/plain`)或通配符类型(`image/*`、`audio/*`、`video/*`)的逗号分隔列表。空值或 `*/*` 允许所有类型。 | |||
- `ALLOWED_TYPES`: **.cpuprofile,.csv,.dmp,.docx,.fodg,.fodp,.fods,.fodt,.gif,.gz,.jpeg,.jpg,.json,.jsonc,.log,.md,.mov,.mp4,.odf,.odg,.odp,.ods,.odt,.patch,.pdf,.png,.pptx,.svg,.tgz,.txt,.webm,.xls,.xlsx,.zip**: 允许的文件扩展名(`.zip`)、mime 类型(`text/plain`)或通配符类型(`image/*`、`audio/*`、`video/*`)的逗号分隔列表。空值或 `*/*` 允许所有类型。 | |||
- `MAX_SIZE`: **2048**: 附件的最大限制(MB)。 | |||
- `MAX_FILES`: **5**: 一次最多上传的附件数量。 | |||
- `STORAGE_TYPE`: **local**: 附件的存储类型,`local` 表示本地磁盘,`minio` 表示兼容 S3 的对象存储服务,如果未设置将使用默认值 `local` 或其他在 `[storage.xxx]` 中定义的名称。 | |||
@@ -1043,7 +1047,7 @@ Gitea 创建以下非唯一队列: | |||
## OAuth2 (`oauth2`) | |||
- `ENABLE`: **true**:启用OAuth2提供者。 | |||
- `ENABLED`: **true**:启用OAuth2提供者。 | |||
- `ACCESS_TOKEN_EXPIRATION_TIME`:**3600**:OAuth2访问令牌的生命周期,以秒为单位。 | |||
- `REFRESH_TOKEN_EXPIRATION_TIME`:**730**:OAuth2刷新令牌的生命周期,以小时为单位。 | |||
- `INVALIDATE_REFRESH_TOKENS`:**false**:检查刷新令牌是否已被使用。 |
@@ -284,7 +284,7 @@ syntax and shouldn't be touched without fully understanding these components. | |||
Google Analytics, Matomo (previously Piwik), and other analytics services can be added to Gitea. To add the tracking code, refer to the `Other additions to the page` section of this document, and add the JavaScript to the `$GITEA_CUSTOM/templates/custom/header.tmpl` file. | |||
## Customizing gitignores, labels, licenses, locales, and readmes. | |||
## Customizing gitignores, labels, licenses, locales, and readmes | |||
Place custom files in corresponding sub-folder under `custom/options`. | |||
@@ -27,14 +27,15 @@ GITEA_CUSTOM=/home/gitea/custom ./gitea web | |||
## From Go language | |||
As Gitea is written in Go, it uses some Go variables, such as: | |||
As Gitea is written in Go, it uses some variables that influence the behaviour of Go's runtime, such as: | |||
- `GOOS` | |||
- `GOARCH` | |||
- [`GOPATH`](https://golang.org/cmd/go/#hdr-GOPATH_environment_variable) | |||
- `GOMEMLIMIT` | |||
- `GOGC` | |||
- `GOMAXPROCS` | |||
- `GODEBUG` | |||
For documentation about each of the variables available, refer to the | |||
[official Go documentation](https://golang.org/cmd/go/#hdr-Environment_variables). | |||
[official Go documentation on runtime environment variables](https://pkg.go.dev/runtime#hdr-Environment_Variables). | |||
## Gitea files | |||
@@ -29,9 +29,9 @@ GITEA_CUSTOM=/home/gitea/custom ./gitea web | |||
* `GOOS` | |||
* `GOARCH` | |||
* [`GOPATH`](https://golang.org/cmd/go/#hdr-GOPATH_environment_variable) | |||
* [`GOPATH`](https://go.dev/cmd/go/#hdr-GOPATH_environment_variable) | |||
您可以在[官方文档](https://golang.org/cmd/go/#hdr-Environment_variables)中查阅这些配置参数的详细信息。 | |||
您可以在[官方文档](https://go.dev/cmd/go/#hdr-Environment_variables)中查阅这些配置参数的详细信息。 | |||
## Gitea 的文件目录 | |||
@@ -35,7 +35,7 @@ CERT_FILE = cert.pem | |||
KEY_FILE = key.pem | |||
``` | |||
Note that if your certificate is signed by a third party certificate authority (i.e. not self-signed), then cert.pem should contain the certificate chain. The server certificate must be the first entry in cert.pem, followed by the intermediaries in order (if any). The root certificate does not have to be included because the connecting client must already have it in order to estalbish the trust relationship. | |||
Note that if your certificate is signed by a third party certificate authority (i.e. not self-signed), then cert.pem should contain the certificate chain. The server certificate must be the first entry in cert.pem, followed by the intermediaries in order (if any). The root certificate does not have to be included because the connecting client must already have it in order to establish the trust relationship. | |||
To learn more about the config values, please checkout the [Config Cheat Sheet](administration/config-cheat-sheet.md#server-server). | |||
For the `CERT_FILE` or `KEY_FILE` field, the file path is relative to the `GITEA_CUSTOM` environment variable when it is a relative path. It can be an absolute path as well. |
@@ -85,7 +85,7 @@ Text and macros for the mail body | |||
Specifying a _subject_ section is optional (and therefore also the dash line separator). When used, the separator between | |||
_subject_ and _mail body_ templates requires at least three dashes; no other characters are allowed in the separator line. | |||
_Subject_ and _mail body_ are parsed by [Golang's template engine](https://golang.org/pkg/text/template/) and | |||
_Subject_ and _mail body_ are parsed by [Golang's template engine](https://go.dev/pkg/text/template/) and | |||
are provided with a _metadata context_ assembled for each notification. The context contains the following elements: | |||
| Name | Type | Available | Usage | | |||
@@ -110,7 +110,7 @@ All names are case sensitive. | |||
### The _subject_ part of the template | |||
The template engine used for the mail _subject_ is golang's [`text/template`](https://golang.org/pkg/text/template/). | |||
The template engine used for the mail _subject_ is golang's [`text/template`](https://go.dev/pkg/text/template/). | |||
Please refer to the linked documentation for details about its syntax. | |||
The _subject_ is built using the following steps: | |||
@@ -138,7 +138,7 @@ the two templates, even if a valid subject template is present. | |||
### The _mail body_ part of the template | |||
The template engine used for the _mail body_ is golang's [`html/template`](https://golang.org/pkg/html/template/). | |||
The template engine used for the _mail body_ is golang's [`html/template`](https://go.dev/pkg/html/template/). | |||
Please refer to the linked documentation for details about its syntax. | |||
The _mail body_ is parsed after the mail subject, so there is an additional _metadata_ field which is | |||
@@ -146,7 +146,7 @@ the actual rendered subject, after all considerations. | |||
The expected result is HTML (including structural elements like`<html>`, `<body>`, etc.). Styling | |||
through `<style>` blocks, `class` and `style` attributes is possible. However, `html/template` | |||
does some [automatic escaping](https://golang.org/pkg/html/template/#hdr-Contexts) that should be considered. | |||
does some [automatic escaping](https://go.dev/pkg/html/template/#hdr-Contexts) that should be considered. | |||
Attachments (such as images or external style sheets) are not supported. However, other templates can | |||
be referenced too, for example to provide the contents of a `<style>` element in a centralized fashion. | |||
@@ -163,7 +163,7 @@ clients don't even support HTML, so they show the text version included in the g | |||
If the template fails to render, it will be noticed only at the moment the mail is sent. | |||
A default subject is used if the subject template fails, and whatever was rendered successfully | |||
from the the _mail body_ is used, disregarding the rest. | |||
from the _mail body_ is used, disregarding the rest. | |||
Please check [Gitea's logs](administration/logging-config.md) for error messages in case of trouble. | |||
@@ -222,9 +222,9 @@ Please check [Gitea's logs](administration/logging-config.md) for error messages | |||
<a href="{{.Link}}">{{.Repo}}#{{.Issue.Index}}</a>. | |||
</p> | |||
{{if not (eq .Body "")}} | |||
<h3>Message content:</h3> | |||
<h3>Message content</h3> | |||
<hr> | |||
{{.Body | Str2html}} | |||
{{.Body}} | |||
{{end}} | |||
</p> | |||
<hr> | |||
@@ -245,7 +245,7 @@ This template produces something along these lines: | |||
> [@rhonda](#) (Rhonda Myers) updated [mike/stuff#38](#). | |||
> | |||
> #### Message content: | |||
> #### Message content | |||
> | |||
> \_********************************\_******************************** | |||
> | |||
@@ -259,20 +259,20 @@ This template produces something along these lines: | |||
The template system contains several functions that can be used to further process and format | |||
the messages. Here's a list of some of them: | |||
| Name | Parameters | Available | Usage | | |||
| ---------------- | ----------- | --------- | --------------------------------------------------------------------------- | | |||
| `AppUrl` | - | Any | Gitea's URL | | |||
| `AppName` | - | Any | Set from `app.ini`, usually "Gitea" | | |||
| `AppDomain` | - | Any | Gitea's host name | | |||
| `EllipsisString` | string, int | Any | Truncates a string to the specified length; adds ellipsis as needed | | |||
| `Str2html` | string | Body only | Sanitizes text by removing any HTML tags from it. | | |||
| `Safe` | string | Body only | Takes the input as HTML; can be used for `.ReviewComments.RenderedContent`. | | |||
| Name | Parameters | Available | Usage | | |||
| ---------------- | ----------- | --------- | ------------------------------------------------------------------- | | |||
| `AppUrl` | - | Any | Gitea's URL | | |||
| `AppName` | - | Any | Set from `app.ini`, usually "Gitea" | | |||
| `AppDomain` | - | Any | Gitea's host name | | |||
| `EllipsisString` | string, int | Any | Truncates a string to the specified length; adds ellipsis as needed | | |||
| `SanitizeHTML` | string | Body only | Sanitizes text by removing any dangerous HTML tags from it | | |||
| `SafeHTML` | string | Body only | Takes the input as HTML, can be used for outputing raw HTML content | | |||
These are _functions_, not metadata, so they have to be used: | |||
```html | |||
Like this: {{Str2html "Escape<my>text"}} | |||
Or this: {{"Escape<my>text" | Str2html}} | |||
Like this: {{SanitizeHTML "Escape<my>text"}} | |||
Or this: {{"Escape<my>text" | SanitizeHTML}} | |||
Or this: {{AppUrl}} | |||
But not like this: {{.AppUrl}} | |||
``` |
@@ -81,7 +81,7 @@ custom/templates/mail/pull/comment.tmpl | |||
指定 _主题_ 部分是可选的(因此也是虚线分隔符)。在使用时,_主题_ 和 _邮件正文_ 模板之间的分隔符需要至少三个虚线;分隔符行中不允许使用其他字符。 | |||
_主题_ 和 _邮件正文_ 由 [Golang的模板引擎](https://golang.org/pkg/text/template/) 解析,并提供了为每个通知组装的 _元数据上下文_。上下文包含以下元素: | |||
_主题_ 和 _邮件正文_ 由 [Golang的模板引擎](https://go.dev/pkg/text/template/) 解析,并提供了为每个通知组装的 _元数据上下文_。上下文包含以下元素: | |||
| 名称 | 类型 | 可用性 | 用途 | | |||
| -------------------- | ------------------ | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | |||
@@ -105,7 +105,7 @@ _主题_ 和 _邮件正文_ 由 [Golang的模板引擎](https://golang.org/pkg/t | |||
### 模板中的主题部分 | |||
用于邮件主题的模板引擎是 Golang 的 [`text/template`](https://golang.org/pkg/text/template/)。 | |||
用于邮件主题的模板引擎是 Golang 的 [`text/template`](https://go.dev/pkg/text/template/)。 | |||
有关语法的详细信息,请参阅链接的文档。 | |||
主题构建的步骤如下: | |||
@@ -130,12 +130,12 @@ _主题_ 和 _邮件正文_ 由 [Golang的模板引擎](https://golang.org/pkg/t | |||
### 模板中的邮件正文部分 | |||
用于邮件正文的模板引擎是 Golang 的 [`html/template`](https://golang.org/pkg/html/template/)。 | |||
用于邮件正文的模板引擎是 Golang 的 [`html/template`](https://go.dev/pkg/html/template/)。 | |||
有关语法的详细信息,请参阅链接的文档。 | |||
邮件正文在邮件主题之后进行解析,因此还有一个额外的 _元数据_ 字段,即在考虑所有情况之后实际呈现的主题。 | |||
期望的结果是 HTML(包括结构元素,如`<html>`,`<body>`等)。可以通过 `<style>` 块、`class` 和 `style` 属性进行样式设置。但是,`html/template` 会进行一些 [自动转义](https://golang.org/pkg/html/template/#hdr-Contexts),需要考虑这一点。 | |||
期望的结果是 HTML(包括结构元素,如`<html>`,`<body>`等)。可以通过 `<style>` 块、`class` 和 `style` 属性进行样式设置。但是,`html/template` 会进行一些 [自动转义](https://go.dev/pkg/html/template/#hdr-Contexts),需要考虑这一点。 | |||
不支持附件(例如图像或外部样式表)。但是,也可以引用其他模板,例如以集中方式提供 `<style>` 元素的内容。外部模板必须放置在 `custom/mail` 下,并相对于该目录引用。例如,可以使用 `{{template styles/base}}` 包含 `custom/mail/styles/base.tmpl`。 | |||
@@ -207,7 +207,7 @@ _主题_ 和 _邮件正文_ 由 [Golang的模板引擎](https://golang.org/pkg/t | |||
{{if not (eq .Body "")}} | |||
<h3>消息内容:</h3> | |||
<hr> | |||
{{.Body | Str2html}} | |||
{{.Body}} | |||
{{end}} | |||
</p> | |||
<hr> | |||
@@ -228,7 +228,7 @@ _主题_ 和 _邮件正文_ 由 [Golang的模板引擎](https://golang.org/pkg/t | |||
> [@rhonda](#)(Rhonda Myers)更新了 [mike/stuff#38](#)。 | |||
> | |||
> #### 消息内容: | |||
> #### 消息内容 | |||
> | |||
> \_********************************\_******************************** | |||
> | |||
@@ -242,20 +242,20 @@ _主题_ 和 _邮件正文_ 由 [Golang的模板引擎](https://golang.org/pkg/t | |||
模板系统包含一些函数,可用于进一步处理和格式化消息。以下是其中一些函数的列表: | |||
| 函数名 | 参数 | 可用于 | 用法 | | |||
| ----------------- | ----------- | ------------ | --------------------------------------------------------------------------------- | | |||
| `AppUrl` | - | 任何地方 | Gitea 的 URL | | |||
| `AppName` | - | 任何地方 | 从 `app.ini` 中设置,通常为 "Gitea" | | |||
| `AppDomain` | - | 任何地方 | Gitea 的主机名 | | |||
| `EllipsisString` | string, int | 任何地方 | 将字符串截断为指定长度;根据需要添加省略号 | | |||
| `Str2html` | string | 仅正文部分 | 通过删除其中的 HTML 标签对文本进行清理 | | |||
| `Safe` | string | 仅正文部分 | 将输入作为 HTML 处理;可用于 `.ReviewComments.RenderedContent` 等字段 | | |||
| 函数名 | 参数 | 可用于 | 用法 | | |||
|------------------| ----------- | ------------ | ------------------------------ | | |||
| `AppUrl` | - | 任何地方 | Gitea 的 URL | | |||
| `AppName` | - | 任何地方 | 从 `app.ini` 中设置,通常为 "Gitea" | | |||
| `AppDomain` | - | 任何地方 | Gitea 的主机名 | | |||
| `EllipsisString` | string, int | 任何地方 | 将字符串截断为指定长度;根据需要添加省略号 | | |||
| `SanitizeHTML` | string | 仅正文部分 | 通过删除其中的危险 HTML 标签对文本进行清理 | | |||
| `SafeHTML` | string | 仅正文部分 | 将输入作为 HTML 处理;可用于输出原始的 HTML 内容 | | |||
这些都是 _函数_,而不是元数据,因此必须按以下方式使用: | |||
```html | |||
像这样使用: {{Str2html "Escape<my>text"}} | |||
或者这样使用: {{"Escape<my>text" | Str2html}} | |||
像这样使用: {{SanitizeHTML "Escape<my>text"}} | |||
或者这样使用: {{"Escape<my>text" | SanitizeHTML}} | |||
或者这样使用: {{AppUrl}} | |||
但不要像这样使用: {{.AppUrl}} | |||
``` |
@@ -101,6 +101,10 @@ i.e. `services/user`, `models/repository`. | |||
Since there are some packages which use the same package name, it is possible that you find packages like `modules/user`, `models/user`, and `services/user`. When these packages are imported in one Go file, it's difficult to know which package we are using and if it's a variable name or an import name. So, we always recommend to use import aliases. To differ from package variables which are commonly in camelCase, just use **snake_case** for import aliases. | |||
i.e. `import user_service "code.gitea.io/gitea/services/user"` | |||
### Implementing `io.Closer` | |||
If a type implements `io.Closer`, calling `Close` multiple times must not fail or `panic` but return an error or `nil`. | |||
### Important Gotchas | |||
- Never write `x.Update(exemplar)` without an explicit `WHERE` clause: |
@@ -34,7 +34,7 @@ The source files can be found in the following directories: | |||
We recommend [Google HTML/CSS Style Guide](https://google.github.io/styleguide/htmlcssguide.html) and [Google JavaScript Style Guide](https://google.github.io/styleguide/jsguide.html) | |||
### Gitea specific guidelines: | |||
### Gitea specific guidelines | |||
1. Every feature (Fomantic-UI/jQuery module) should be put in separate files/directories. | |||
2. HTML ids and classes should use kebab-case, it's preferred to contain 2-3 feature related keywords. | |||
@@ -47,7 +47,7 @@ We recommend [Google HTML/CSS Style Guide](https://google.github.io/styleguide/h | |||
9. Avoid unnecessary `!important` in CSS, add comments to explain why it's necessary if it can't be avoided. | |||
10. Avoid mixing different events in one event listener, prefer to use individual event listeners for every event. | |||
11. Custom event names are recommended to use `ce-` prefix. | |||
12. Gitea's tailwind-style CSS classes use `gt-` prefix (`gt-relative`), while Gitea's own private framework-level CSS classes use `g-` prefix (`g-modal-confirm`). | |||
12. Prefer using Tailwind CSS which is available via `tw-` prefix, e.g. `tw-relative`. Gitea's helper CSS classes use `gt-` prefix (`gt-df`), while Gitea's own private framework-level CSS classes use `g-` prefix (`g-modal-confirm`). | |||
13. Avoid inline scripts & styles as much as possible, it's recommended to put JS code into JS files and use CSS classes. If inline scripts & styles are unavoidable, explain the reason why it can't be avoided. | |||
### Accessibility / ARIA | |||
@@ -65,14 +65,17 @@ Recommended implementations: | |||
* Vue + Vanilla JS | |||
* Fomantic-UI (jQuery) | |||
* htmx (partial page reloads for otherwise static components) | |||
* Vanilla JS | |||
Discouraged implementations: | |||
* Vue + Fomantic-UI (jQuery) | |||
* jQuery + Vanilla JS | |||
* htmx + any other framework which requires heavy JS code, or unnecessary features like htmx scripting (`hx-on`) | |||
To make UI consistent, Vue components can use Fomantic-UI CSS classes. | |||
We use htmx for simple interactions. You can see an example for simple interactions where htmx should be used in this [PR](https://github.com/go-gitea/gitea/pull/28908). Do not use htmx if you require more advanced reactivity, use another framework (Vue/Vanilla JS). | |||
Although mixing different frameworks is discouraged, | |||
it should also work if the mixing is necessary and the code is well-designed and maintainable. | |||
@@ -34,7 +34,7 @@ HTML 页面由[Go HTML Template](https://pkg.go.dev/html/template)渲染。 | |||
我们推荐使用[Google HTML/CSS Style Guide](https://google.github.io/styleguide/htmlcssguide.html)和[Google JavaScript Style Guide](https://google.github.io/styleguide/jsguide.html)。 | |||
## Gitea 特定准则: | |||
## Gitea 特定准则 | |||
1. 每个功能(Fomantic-UI/jQuery 模块)应放在单独的文件/目录中。 | |||
2. HTML 的 id 和 class 应使用 kebab-case,最好包含2-3个与功能相关的关键词。 | |||
@@ -47,12 +47,13 @@ HTML 页面由[Go HTML Template](https://pkg.go.dev/html/template)渲染。 | |||
9. 避免在 CSS 中使用不必要的`!important`,如果无法避免,添加注释解释为什么需要它。 | |||
10. 避免在一个事件监听器中混合不同的事件,优先为每个事件使用独立的事件监听器。 | |||
11. 推荐使用自定义事件名称前缀`ce-`。 | |||
12. Gitea 的 tailwind-style CSS 类使用`gt-`前缀(`gt-relative`),而 Gitea 自身的私有框架级 CSS 类使用`g-`前缀(`g-modal-confirm`)。 | |||
12. 建议使用 Tailwind CSS,它可以通过 `tw-` 前缀获得,例如 `tw-relative`. Gitea 自身的助手类 CSS 使用 `gt-` 前缀(`gt-df`),Gitea 自身的私有框架级 CSS 类使用 `g-` 前缀(`g-modal-confirm`)。 | |||
13. 尽量避免内联脚本和样式,建议将JS代码放入JS文件中并使用CSS类。如果内联脚本和样式不可避免,请解释无法避免的原因。 | |||
### 可访问性 / ARIA | |||
在历史上,Gitea大量使用了可访问性不友好的框架 Fomantic UI。 | |||
Gitea使用一些补丁使Fomantic UI更具可访问性(参见`aria.js`和`aria.md`), | |||
Gitea 使用一些补丁使 Fomantic UI 更具可访问性(参见 `aria.md`), | |||
但仍然存在许多问题需要大量的工作和时间来修复。 | |||
### 框架使用 | |||
@@ -64,18 +65,21 @@ Gitea使用一些补丁使Fomantic UI更具可访问性(参见`aria.js`和`ari | |||
* Vue + Vanilla JS | |||
* Fomantic-UI(jQuery) | |||
* htmx (部分页面重新加载其他静态组件) | |||
* Vanilla JS | |||
不推荐的实现方式: | |||
* Vue + Fomantic-UI(jQuery) | |||
* jQuery + Vanilla JS | |||
* htmx + 任何其他需要大量 JavaScript 代码或不必要的功能,如 htmx 脚本 (`hx-on`) | |||
为了保持界面一致,Vue 组件可以使用 Fomantic-UI 的 CSS 类。 | |||
尽管不建议混合使用不同的框架, | |||
我们使用 htmx 进行简单的交互。您可以在此 [PR](https://github.com/go-gitea/gitea/pull/28908) 中查看一个简单交互的示例,其中应使用 htmx。如果您需要更高级的反应性,请不要使用 htmx,请使用其他框架(Vue/Vanilla JS)。 | |||
但如果混合使用是必要的,并且代码设计良好且易于维护,也可以工作。 | |||
### async 函数 | |||
### `async` 函数 | |||
只有当函数内部存在`await`调用或返回`Promise`时,才将函数标记为`async`。 | |||
@@ -91,6 +95,12 @@ Gitea使用一些补丁使Fomantic UI更具可访问性(参见`aria.js`和`ari | |||
这是有意为之的,我们想调用异步函数并忽略Promise。 | |||
一些 lint 规则和 IDE 也会在未处理返回的 Promise 时发出警告。 | |||
### 获取数据 | |||
要获取数据,请使用`modules/fetch.js`中的包装函数`GET`、`POST`等。他们 | |||
接受内容的`data`选项,将自动设置 CSRF 令牌并返回 | |||
[Response](https://developer.mozilla.org/en-US/docs/Web/API/Response)。 | |||
### HTML 属性和 dataset | |||
禁止使用`dataset`,它的驼峰命名行为使得搜索属性变得困难。 | |||
@@ -132,3 +142,7 @@ Gitea使用一些补丁使Fomantic UI更具可访问性(参见`aria.js`和`ari | |||
### Vue3 和 JSX | |||
Gitea 现在正在使用 Vue3。我们决定不引入 JSX,以保持 HTML 代码和 JavaScript 代码分离。 | |||
### UI示例 | |||
Gitea 使用一些自制的 UI 元素并自定义其他元素,以将它们更好地集成到通用 UI 方法中。当在开发模式(`RUN_MODE=dev`)下运行 Gitea 时,在 `http(s)://your-gitea-url:port/devtest` 下会提供一个包含一些标准化 UI 示例的页面。 |
@@ -60,7 +60,7 @@ curl "http://localhost:4000/api/v1/repos/test1/test1/issues" \ | |||
`/users/:name/tokens` 是一个特殊的接口,需要您使用 basic authentication 进行认证,具体原因在 issue 中 | |||
[#3842](https://github.com/go-gitea/gitea/issues/3842#issuecomment-397743346) 有所提及,使用方法如下所示: | |||
### 使用 Basic authentication 认证: | |||
### 使用 Basic authentication 认证 | |||
``` | |||
$ curl --url https://yourusername:yourpassword@gitea.your.host/api/v1/users/yourusername/tokens |
@@ -25,7 +25,7 @@ To get a quick working development environment you could use Gitpod. | |||
## Installing go | |||
You should [install go](https://golang.org/doc/install) and set up your go | |||
You should [install go](https://go.dev/doc/install) and set up your go | |||
environment correctly. | |||
Next, [install Node.js with npm](https://nodejs.org/en/download/) which is | |||
@@ -214,7 +214,7 @@ REPO_INDEXER_CONN_STR = http://elastic:changeme@localhost:9200 | |||
### Building and adding SVGs | |||
SVG icons are built using the `make svg` target which compiles the icon sources defined in `build/generate-svg.js` into the output directory `public/assets/img/svg`. Custom icons can be added in the `web_src/svg` directory. | |||
SVG icons are built using the `make svg` target which compiles the icon sources into the output directory `public/assets/img/svg`. Custom icons can be added in the `web_src/svg` directory. | |||
### Building the Logo | |||
@@ -243,10 +243,10 @@ documentation using: | |||
make generate-swagger | |||
``` | |||
You should validate your generated Swagger file and spell-check it with: | |||
You should validate your generated Swagger file: | |||
```bash | |||
make swagger-validate misspell-check | |||
make swagger-validate | |||
``` | |||
You should commit the changed swagger JSON file. The continuous integration | |||
@@ -333,14 +333,9 @@ Documentation for the website is found in `docs/`. If you change this you | |||
can test your changes to ensure that they pass continuous integration using: | |||
```bash | |||
# from the docs directory within Gitea | |||
make trans-copy clean build | |||
make lint-md | |||
``` | |||
You will require a copy of [Hugo](https://gohugo.io/) to run this task. Please | |||
note: this may generate a number of untracked Git objects, which will need to | |||
be cleaned up. | |||
## Visual Studio Code | |||
A `launch.json` and `tasks.json` are provided within `contrib/ide/vscode` for |
@@ -25,7 +25,7 @@ menu: | |||
## 安装 Golang | |||
您需要 [安装 go]( https://golang.org/doc/install ) 并设置您的 go 环境。 | |||
您需要 [安装 go]( https://go.dev/doc/install ) 并设置您的 go 环境。 | |||
接下来,[使用 npm 安装 Node.js](https://nodejs.org/en/download/) ,这是构建 | |||
JavaScript 和 CSS 文件的必要工具。最低支持的 Node.js 版本是 @minNodeVersion@ | |||
@@ -201,7 +201,7 @@ REPO_INDEXER_CONN_STR = http://elastic:changeme@localhost:9200 | |||
### 构建和添加 SVGs | |||
SVG 图标是使用 `make svg` 目标构建的,该目标将 `build/generate-svg.js` 中定义的图标源编译到输出目录 `public/img/svg` 中。可以在 `web_src/svg` 目录中添加自定义图标。 | |||
SVG 图标是使用 `make svg` 命令构建的,该命令将图标资源编译到输出目录 `public/assets/img/svg` 中。可以在 `web_src/svg` 目录中添加自定义图标。 | |||
### 构建 Logo | |||
@@ -228,10 +228,10 @@ Gitea Logo的 PNG 和 SVG 版本是使用 `TAGS="gitea" make generate-images` | |||
make generate-swagger | |||
``` | |||
您应该验证生成的 Swagger 文件并使用以下命令对其进行拼写检查: | |||
您应该验证生成的 Swagger 文件: | |||
```bash | |||
make swagger-validate misspell-check | |||
make swagger-validate | |||
``` | |||
您应该提交更改后的 swagger JSON 文件。持续集成服务器将使用以下方法检查是否已完成: | |||
@@ -307,13 +307,9 @@ TAGS="bindata sqlite sqlite_unlock_notify" make build test-sqlite | |||
该网站的文档位于 `docs/` 中。如果你改变了文档内容,你可以使用以下测试方法进行持续集成: | |||
```bash | |||
# 来自 Gitea 中的 docs 目录 | |||
make trans-copy clean build | |||
make lint-md | |||
``` | |||
运行此任务依赖于 [Hugo](https://gohugo.io/)。请注意:这可能会生成一些未跟踪的 Git 对象, | |||
需要被清理干净。 | |||
## Visual Studio Code | |||
`contrib/ide/vscode` 中为 Visual Studio Code 提供了 `launch.json` 和 `tasks.json`。查看 |
@@ -221,9 +221,11 @@ Our translations are currently crowd-sourced on our [Crowdin project](https://cr | |||
Whether you want to change a translation or add a new one, it will need to be there as all translations are overwritten in our CI via the Crowdin integration. | |||
## Push Hook / Webhook aren't running | |||
## Push Hook / Webhook / Actions aren't running | |||
If you can push but can't see push activities on the home dashboard, or the push doesn't trigger webhook, there are a few possibilities: | |||
If you can push but can't see push activities on the home dashboard, or the push doesn't trigger webhook and Actions workflows, it's likely that the git hooks are not working. | |||
There are a few possibilities: | |||
1. The git hooks are out of sync: run "Resynchronize pre-receive, update and post-receive hooks of all repositories" on the site admin panel | |||
2. The git repositories (and hooks) are stored on some filesystems (ex: mounted by NAS) which don't support script execution, make sure the filesystem supports `chmod a+x any-script` |
@@ -225,9 +225,11 @@ Gitea还提供了自己的SSH服务器,用于在SSHD不可用时使用。 | |||
无论您想要更改翻译还是添加新的翻译,都需要在Crowdin集成中进行,因为所有翻译都会被CI覆盖。 | |||
## 推送钩子/ Webhook未运行 | |||
## 推送钩子/ Webhook / Actions 未运行 | |||
如果您可以推送但无法在主页仪表板上看到推送活动,或者推送不触发Webhook,有几种可能性: | |||
如果您可以推送但无法在主页仪表板上看到推送活动,或者推送不触发 Webhook 和 Actions,可能是 git 钩子不工作而导致的。 | |||
这可能是由于以下原因: | |||
1. Git钩子不同步:在站点管理面板上运行“重新同步所有仓库的pre-receive、update和post-receive钩子” | |||
2. Git仓库(和钩子)存储在一些不支持脚本执行的文件系统上(例如由NAS挂载),请确保文件系统支持`chmod a+x any-script` |
@@ -15,11 +15,64 @@ menu: | |||
identifier: "support" | |||
--- | |||
## 需要帮助? | |||
# 支持选项 | |||
如果您在使用或者开发过程中遇到问题,请到以下渠道咨询: | |||
- [付费商业支持](https://about.gitea.com/) | |||
- [Discord](https://discord.gg/Gitea) | |||
- [Discourse 论坛](https://discourse.gitea.io/) | |||
- [Matrix](https://matrix.to/#/#gitea-space:matrix.org) | |||
- 注意:大多数 Matrix 频道都与 Discord 中的对应频道桥接,可能在桥接过程中会出现一定程度的不稳定性。 | |||
- 中文支持 | |||
- [Discourse 中文分类](https://discourse.gitea.io/c/5-category/5) | |||
- QQ 群 328432459 | |||
- 到 [GitHub Issue](https://github.com/go-gitea/gitea/issues) 提问(因为项目维护人员来自世界各地,为保证沟通顺畅,请使用英文提问) | |||
- 中文问题到 [Gitea 论坛](https://discourse.gitea.io/c/5-category/5) 提问 | |||
- 访问 [Discord Gitea 聊天室 - 英文](https://discord.gg/Gitea) | |||
- 加入 QQ群 328432459 获得进一步的支持 | |||
# Bug 报告 | |||
如果您发现了 Bug,请在 GitHub 上 [创建一个问题](https://github.com/go-gitea/gitea/issues)。 | |||
**注意:** 在请求支持时,可能需要准备以下信息,以便帮助者获得所需的所有信息: | |||
1. 您的 `app.ini`(将任何敏感数据进行必要的清除)。 | |||
2. 您看到的任何错误消息。 | |||
3. Gitea 日志以及与情况相关的所有其他日志。 | |||
- 收集 `trace` / `debug` 级别的日志更有用(参见下一节)。 | |||
- 在使用 systemd 时,使用 `journalctl --lines 1000 --unit gitea` 收集日志。 | |||
- 在使用 Docker 时,使用 `docker logs --tail 1000 <gitea-container>` 收集日志。 | |||
4. 可重现的步骤,以便他人能够更快速、更容易地重现和理解问题。 | |||
- [try.gitea.io](https://try.gitea.io) 可用于重现问题。 | |||
5. 如果遇到慢速/挂起/死锁等问题,请在出现问题时报告堆栈跟踪。 | |||
转到 "Site Admin" -> "Monitoring" -> "Stacktrace" -> "Download diagnosis report"。 | |||
# 高级 Bug 报告提示 | |||
## 更多日志的配置选项 | |||
默认情况下,日志以 `info` 级别输出到控制台。 | |||
如果您需要设置日志级别和/或从文件中收集日志, | |||
您只需将以下配置复制到您的 `app.ini` 中(删除所有其他 `[log]` 部分), | |||
然后您将在 Gitea 的日志目录中找到 `*.log` 文件(默认为 `%(GITEA_WORK_DIR)/log`)。 | |||
```ini | |||
; 要显示所有 SQL 日志,您还可以在 [database] 部分中设置 LOG_SQL=true | |||
[log] | |||
LEVEL=debug | |||
MODE=console,file | |||
``` | |||
## 使用命令行收集堆栈跟踪 | |||
Gitea 可以使用 Golang 的 pprof 处理程序和工具链来收集堆栈跟踪和其他运行时信息。 | |||
如果 Web UI 停止工作,您可以尝试通过命令行收集堆栈跟踪: | |||
1. 设置 app.ini: | |||
``` | |||
[server] | |||
ENABLE_PPROF = true | |||
``` | |||
2. 重新启动 Gitea | |||
3. 尝试触发bug,当请求卡住一段时间,使用或浏览器访问:获取堆栈跟踪。 | |||
`curl http://127.0.0.1:6060/debug/pprof/goroutine?debug=1` |
@@ -52,6 +52,7 @@ _Symbols used in table:_ | |||
| Markdown support | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | |||
| CSV support | ✓ | ✘ | ✓ | ✘ | ✘ | ✓ | ✘ | ✘ | | |||
| 'GitHub / GitLab pages' | [⚙️][gitea-pages-server], [⚙️][gitea-caddy-plugin] | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ | ✘ | | |||
| Gists / Snippets | [⚙️][opengist] | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | |||
| Repo-specific wiki (as a repo itself) | ✓ | ✓ | ✓ | ✓ | ✓ | / | ✘ | ✘ | | |||
| Deploy Tokens | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | |||
| Repository Tokens with write rights | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | |||
@@ -147,3 +148,4 @@ _Symbols used in table:_ | |||
[gitea-caddy-plugin]: https://github.com/42wim/caddy-gitea | |||
[gitea-pages-server]: https://codeberg.org/Codeberg/pages-server | |||
[opengist]: https://github.com/thomiceli/opengist |
@@ -17,7 +17,9 @@ menu: | |||
# 数据库准备 | |||
在使用 Gitea 前,您需要准备一个数据库。Gitea 支持 PostgreSQL(>= 12)、MySQL(>= 8.0)、SQLite 和 MSSQL(>= 2012 SP4)这几种数据库。本页将指导您准备数据库。由于 PostgreSQL 和 MySQL 在生产环境中被广泛使用,因此本文档将仅涵盖这两种数据库。如果您计划使用 SQLite,则可以忽略本章内容。 | |||
在使用 Gitea 前,您需要准备一个数据库。Gitea 支持 PostgreSQL(>= 12)、MySQL(>= 8.0)、MariaDB(>= 10.4)、SQLite(内置) 和 MSSQL(>= 2012 SP4)这几种数据库。本页将指导您准备数据库。由于 PostgreSQL 和 MySQL 在生产环境中被广泛使用,因此本文档将仅涵盖这两种数据库。如果您计划使用 SQLite,则可以忽略本章内容。 | |||
如果您使用不受支持的数据库版本,请通过 [联系我们](/help/support) 以获取有关我们的扩展支持的信息。我们可以为旧数据库提供测试和支持,并将这些修复集成到 Gitea 代码库中。 | |||
数据库实例可以与 Gitea 实例在相同机器上(本地数据库),也可以与 Gitea 实例在不同机器上(远程数据库)。 | |||
@@ -61,7 +63,9 @@ menu: | |||
4. 使用 UTF-8 字符集和大小写敏感的排序规则创建数据库。 | |||
Gitea 启动后会尝试把数据库修改为更合适的字符集,如果你想指定自己的字符集规则,可以在 app.ini 中设置 `[database].CHARSET_COLLATION`。 | |||
`utf8mb4_bin` 是 MySQL/MariaDB 的通用排序规则。 | |||
Gitea 启动后会尝试把数据库修改为更合适的字符集 (`utf8mb4_0900_as_cs` 或者 `uca1400_as_cs`) 并在可能的情况下更改数据库。 | |||
如果你想指定自己的字符集规则,可以在 `app.ini` 中设置 `[database].CHARSET_COLLATION`。 | |||
```sql | |||
CREATE DATABASE giteadb CHARACTER SET 'utf8mb4' COLLATE 'utf8mb4_bin'; | |||
@@ -85,7 +89,7 @@ menu: | |||
FLUSH PRIVILEGES; | |||
``` | |||
6. 通过 exit 退出数据库控制台。 | |||
6. 通过 `exit` 退出数据库控制台。 | |||
7. 在您的 Gitea 服务器上,测试与数据库的连接: | |||
@@ -93,13 +97,13 @@ menu: | |||
mysql -u gitea -h 203.0.113.3 -p giteadb | |||
``` | |||
其中 `gitea` 是数据库用户名,`giteadb` 是数据库名称,`203.0.113.3` 是数据库实例的 IP 地址。对于本地数据库,省略 -h 选项。 | |||
其中 `gitea` 是数据库用户名,`giteadb` 是数据库名称,`203.0.113.3` 是数据库实例的 IP 地址。对于本地数据库,省略 `-h` 选项。 | |||
到此您应该能够连接到数据库了。 | |||
## PostgreSQL | |||
1. 对于远程数据库设置,通过编辑数据库实例上的 postgresql.conf 文件中的 listen_addresses 将 PostgreSQL 配置为监听您的 IP 地址: | |||
1. 对于远程数据库设置,通过编辑数据库实例上的 postgresql.conf 文件中的 `listen_addresses` 将 `PostgreSQL` 配置为监听您的 IP 地址: | |||
```ini | |||
listen_addresses = 'localhost, 203.0.113.3' |
@@ -17,7 +17,7 @@ menu: | |||
# Installation from source | |||
You should [install go](https://golang.org/doc/install) and set up your go | |||
You should [install go](https://go.dev/doc/install) and set up your go | |||
environment correctly. In particular, it is recommended to set the `$GOPATH` | |||
environment variable and to add the go bin directory or directories | |||
`${GOPATH//://bin:}/bin` to the `$PATH`. See the Go wiki entry for | |||
@@ -27,13 +27,7 @@ Next, [install Node.js with npm](https://nodejs.org/en/download/) which is | |||
required to build the JavaScript and CSS files. The minimum supported Node.js | |||
version is @minNodeVersion@ and the latest LTS version is recommended. | |||
**Note**: When executing make tasks that require external tools, like | |||
`make misspell-check`, Gitea will automatically download and build these as | |||
necessary. To be able to use these, you must have the `"$GOPATH/bin"` directory | |||
on the executable path. If you don't add the go bin directory to the | |||
executable path, you will have to manage this yourself. | |||
**Note 2**: Go version @minGoVersion@ or higher is required. However, it is recommended to | |||
**Note**: Go version @minGoVersion@ or higher is required. However, it is recommended to | |||
obtain the same version as our continuous integration, see the advice given in | |||
[Hacking on Gitea](development/hacking-on-gitea.md) | |||
@@ -82,7 +76,7 @@ git checkout v@version@ # or git checkout pr-xyz | |||
To build from source, the following programs must be present on the system: | |||
- `go` @minGoVersion@ or higher, see [here](https://golang.org/dl/) | |||
- `go` @minGoVersion@ or higher, see [here](https://go.dev/dl/) | |||
- `node` @minNodeVersion@ or higher with `npm`, see [here](https://nodejs.org/en/download/) | |||
- `make`, see [here](development/hacking-on-gitea.md#installing-make) | |||
@@ -119,7 +113,7 @@ TAGS="bindata sqlite sqlite_unlock_notify" make build | |||
The `build` target is split into two sub-targets: | |||
- `make backend` which requires [Go @minGoVersion@](https://golang.org/dl/) or greater. | |||
- `make backend` which requires [Go @minGoVersion@](https://go.dev/dl/) or greater. | |||
- `make frontend` which requires [Node.js @minNodeVersion@](https://nodejs.org/en/download/) or greater. | |||
If pre-built frontend files are present it is possible to only build the backend: | |||
@@ -165,7 +159,7 @@ Running `gitea help` will allow you to review what the computed settings will be | |||
## Cross Build | |||
The `go` compiler toolchain supports cross-compiling to different architecture targets that are supported by the toolchain. See [`GOOS` and `GOARCH` environment variable](https://golang.org/doc/install/source#environment) for the list of supported targets. Cross compilation is helpful if you want to build Gitea for less-powerful systems (such as Raspberry Pi). | |||
The `go` compiler toolchain supports cross-compiling to different architecture targets that are supported by the toolchain. See [`GOOS` and `GOARCH` environment variable](https://go.dev/doc/install/source#environment) for the list of supported targets. Cross compilation is helpful if you want to build Gitea for less-powerful systems (such as Raspberry Pi). | |||
To cross build Gitea with build tags (`TAGS`), you also need a C cross compiler which targets the same architecture as selected by the `GOOS` and `GOARCH` variables. For example, to cross build for Linux ARM64 (`GOOS=linux` and `GOARCH=arm64`), you need the `aarch64-unknown-linux-gnu-gcc` cross compiler. This is required because Gitea build tags uses `cgo`'s foreign-function interface (FFI). | |||
@@ -21,9 +21,7 @@ menu: | |||
接下来,[安装 Node.js 和 npm](https://nodejs.org/zh-cn/download/), 这是构建 JavaScript 和 CSS 文件所需的。最低支持的 Node.js 版本是 @minNodeVersion@,建议使用最新的 LTS 版本。 | |||
**注意**:当执行需要外部工具的 make 任务(如`make misspell-check`)时,Gitea 将根据需要自动下载和构建这些工具。为了能够实现这个目的,你必须将`"$GOPATH/bin"`目录添加到可执行路径中。如果没有将 Go 的二进制目录添加到可执行路径中,你需要自行解决产生的问题。 | |||
**注意2**:需要 Go 版本 @minGoVersion@ 或更高版本。不过,建议获取与我们的持续集成(continuous integration, CI)相同的版本,请参阅在 [Hacking on Gitea](development/hacking-on-gitea.md) 中给出的建议。 | |||
**注意**:需要 Go 版本 @minGoVersion@ 或更高版本。不过,建议获取与我们的持续集成(continuous integration, CI)相同的版本,请参阅在 [Hacking on Gitea](development/hacking-on-gitea.md) 中给出的建议。 | |||
## 下载 | |||
@@ -62,7 +60,7 @@ git checkout v@version@ # or git checkout pr-xyz | |||
要从源代码进行构建,系统必须预先安装以下程序: | |||
- `go` @minGoVersion@ 或更高版本,请参阅 [这里](https://golang.org/dl/) | |||
- `go` @minGoVersion@ 或更高版本,请参阅 [这里](https://go.dev/dl/) | |||
- `node` @minNodeVersion@ 或更高版本,并且安装 `npm`, 请参阅 [这里](https://nodejs.org/zh-cn/download/) | |||
- `make`, 请参阅 [这里](development/hacking-on-gitea.md) | |||
@@ -128,7 +126,7 @@ Gitea 将从`CustomPath`中查找许多信息。默认的,这会在运行 Gite | |||
## 交叉编译 | |||
`go`编译器工具链支持将代码交叉编译到不同的目标架构上。请参考[`GOOS`和`GOARCH`环境变量](https://golang.org/doc/install/source#environment) 以获取支持的目标列表。如果您想为性能较弱的系统(如树莓派)构建 Gitea,交叉编译非常有用。 | |||
`go`编译器工具链支持将代码交叉编译到不同的目标架构上。请参考[`GOOS`和`GOARCH`环境变量](https://go.dev/doc/install/source#environment) 以获取支持的目标列表。如果您想为性能较弱的系统(如树莓派)构建 Gitea,交叉编译非常有用。 | |||
要使用构建标签(`TAGS`)进行交叉编译Gitea,您还需要一个 C 交叉编译器,该编译器的目标架构与`GOOS`和`GOARCH`变量选择的架构相同。例如,要为 Linux ARM64(`GOOS=linux`和`GOARCH=arm64`)进行交叉编译,您需要`aarch64-unknown-linux-gnu-gcc`交叉编译器。这是因为 Gitea 构建标签使用了`cgo`的外部函数接口(FFI)。 | |||
@@ -15,7 +15,7 @@ menu: | |||
identifier: "windows-service" | |||
--- | |||
# 准备工作 | |||
## 准备工作 | |||
在 C:\gitea\custom\conf\app.ini 中进行了以下更改: | |||
@@ -27,7 +27,7 @@ RUN_USER = COMPUTERNAME$ | |||
COMPUTERNAME 是从命令行中运行 `echo %COMPUTERNAME%` 后得到的响应。如果响应是 `USER-PC`,那么 `RUN_USER = USER-PC$`。 | |||
## 使用绝对路径 | |||
### 使用绝对路径 | |||
如果您使用 SQLite3,请将 `PATH` 更改为包含完整路径: | |||
@@ -36,7 +36,7 @@ COMPUTERNAME 是从命令行中运行 `echo %COMPUTERNAME%` 后得到的响应 | |||
PATH = c:/gitea/data/gitea.db | |||
``` | |||
# 注册为Windows服务 | |||
## 注册为Windows服务 | |||
要注册为Windows服务,首先以Administrator身份运行 `cmd`,然后执行以下命令: | |||
@@ -48,7 +48,16 @@ sc.exe create gitea start= auto binPath= "\"C:\gitea\gitea.exe\" web --config \" | |||
之后在控制面板打开 "Windows Services",搜索 "gitea",右键选择 "Run"。在浏览器打开 `http://localhost:3000` 就可以访问了。(如果你修改了端口,请访问对应的端口,3000是默认端口)。 | |||
## 添加启动依赖项 | |||
### 服务启动类型 | |||
据观察,在启动期间加载的系统上,Gitea 服务可能无法启动,并在 Windows 事件日志中记录超时。 | |||
在这种情况下,将启动类型更改为`Automatic-Delayed`。这可以在服务创建期间完成,或者通过运行配置命令来完成。 | |||
``` | |||
sc.exe config gitea start= delayed-auto | |||
``` | |||
### 添加启动依赖项 | |||
要将启动依赖项添加到 Gitea Windows 服务(例如 Mysql、Mariadb),作为管理员,然后运行以下命令: | |||
@@ -120,6 +120,8 @@ A registration token can also be obtained from the gitea [command-line interface | |||
gitea --config /etc/gitea/app.ini actions generate-runner-token | |||
``` | |||
Tokens are valid for registering multiple runners, until they are revoked and replaced by a new token using the token reset link in the web interface. | |||
### Register the runner | |||
The act runner can be registered by running the following command: |
@@ -95,12 +95,6 @@ Gitea Actions目前不支持此功能,如果使用它,结果将始终为空 | |||
## 缺失的功能 | |||
### 变量 | |||
请参阅[变量](https://docs.github.com/zh/actions/learn-github-actions/variables)。 | |||
目前变量功能正在开发中。 | |||
### 问题匹配器 | |||
问题匹配器是一种扫描Actions输出以查找指定正则表达式模式并在用户界面中突出显示该信息的方法。 | |||
@@ -132,7 +126,7 @@ Gitea Actions目前不支持此功能。 | |||
如果你使用 `uses: actions/checkout@v4`,Gitea将会从 https://github.com/actions/checkout.git 下载这个 actions 项目。 | |||
如果你想要从另外一个 Git服务下载actions,你只需要使用绝对URL `uses: https://gitea.com/actions/checkout@v4` 来下载。 | |||
如果你的 Gitea 实例是部署在一个互联网限制的网络中,有可以使用绝对地址来下载 actions。你也可以讲配置项修改为 `[actions].DEFAULT_ACTIONS_URL = self`。这样所有的相对路径的actions引用,将不再会从 github.com 去下载,而会从这个 Gitea 实例自己的仓库中去下载。例如: `uses: actions/checkout@v4` 将会从 `[server].ROOT_URL`/actions/checkout.git 这个地址去下载 actions。 | |||
如果你的 Gitea 实例是部署在一个互联网限制的网络中,也可以使用绝对地址来下载 actions。你也可以将配置项修改为 `[actions].DEFAULT_ACTIONS_URL = self`。这样所有的相对路径的actions引用,将不再会从 github.com 去下载,而会从这个 Gitea 实例自己的仓库中去下载。例如: `uses: actions/checkout@v4` 将会从 `[server].ROOT_URL`/actions/checkout.git 这个地址去下载 actions。 | |||
设置`[actions].DEFAULT_ACTIONS_URL`进行配置。请参阅[配置备忘单](administration/config-cheat-sheet.md#actions-actions)。 | |||
@@ -45,25 +45,24 @@ It is technically possible to implement, but we need to discuss whether it is ne | |||
## Where will the runner download scripts when using actions such as `actions/checkout@v4`? | |||
You may be aware that there are tens of thousands of [marketplace actions](https://github.com/marketplace?type=actions) in GitHub. | |||
However, when you write `uses: actions/checkout@v4`, it actually downloads the scripts from [gitea.com/actions/checkout](http://gitea.com/actions/checkout) by default (not GitHub). | |||
This is a mirror of [github.com/actions/checkout](http://github.com/actions/checkout), but it's impossible to mirror all of them. | |||
That's why you may encounter failures when trying to use some actions that haven't been mirrored. | |||
There are tens of thousands of [actions scripts](https://github.com/marketplace?type=actions) in GitHub, and when you write `uses: actions/checkout@v4`, it downloads the scripts from [github.com/actions/checkout](http://github.com/actions/checkout) by default. | |||
But what if you want to use actions from other places such as gitea.com instead of GitHub? | |||
The good news is that you can specify the URL prefix to use actions from anywhere. | |||
This is an extra syntax in Gitea Actions. | |||
For example: | |||
- `uses: https://github.com/xxx/xxx@xxx` | |||
- `uses: https://gitea.com/xxx/xxx@xxx` | |||
- `uses: https://github.com/xxx/xxx@xxx` | |||
- `uses: http://your_gitea_instance.com/xxx@xxx` | |||
Be careful, the `https://` or `http://` prefix is necessary! | |||
Alternatively, if you want your runners to download actions from GitHub or your own Gitea instance by default, you can configure it by setting `[actions].DEFAULT_ACTIONS_URL`. | |||
See [Configuration Cheat Sheet](administration/config-cheat-sheet.md#actions-actions). | |||
This is one of the differences from GitHub Actions which supports actions scripts only from GitHub. | |||
But it should allow users much more flexibility in how they run Actions. | |||
This is one of the differences from GitHub Actions, but it should allow users much more flexibility in how they run Actions. | |||
Alternatively, if you want your runners to download actions from your own Gitea instance by default, you can configure it by setting `[actions].DEFAULT_ACTIONS_URL`. | |||
See [Configuration Cheat Sheet](administration/config-cheat-sheet.md#actions-actions). | |||
## How to limit the permission of the runners? | |||
@@ -45,25 +45,25 @@ DEFAULT_REPO_UNITS = ...,repo.actions | |||
## 使用`actions/checkout@v4`等Actions时,Job容器会从何处下载脚本? | |||
您可能知道GitHub上有成千上万个[Actions市场](https://github.com/marketplace?type=actions)。 | |||
然而,当您编写`uses: actions/checkout@v4`时,它实际上默认从[gitea.com/actions/checkout](http://gitea.com/actions/checkout)下载脚本(而不是从GitHub下载)。 | |||
这是[github.com/actions/checkout](http://github.com/actions/checkout)的镜像,但无法将它们全部镜像。 | |||
这就是为什么在尝试使用尚未镜像的某些Actions时可能会遇到失败的原因。 | |||
GitHub 上有成千上万个 [Actions 脚本](https://github.com/marketplace?type=actions)。 | |||
当您编写 `uses: actions/checkout@v4` 时,它默认会从 [github.com/actions/checkout](https://github.com/actions/checkout) 下载脚本。 | |||
那如果您想使用一些托管在其它平台上的脚本呢,比如在 gitea.com 上的? | |||
好消息是,您可以指定要从任何位置使用Actions的URL前缀。 | |||
这是Gitea Actions中的额外语法。 | |||
例如: | |||
- `uses: https://github.com/xxx/xxx@xxx` | |||
- `uses: https://gitea.com/xxx/xxx@xxx` | |||
- `uses: https://github.com/xxx/xxx@xxx` | |||
- `uses: http://your_gitea_instance.com/xxx@xxx` | |||
注意,`https://`或`http://`前缀是必需的! | |||
另外,如果您希望您的Runner默认从GitHub或您自己的Gitea实例下载Actions,可以通过设置 `[actions].DEFAULT_ACTIONS_URL`进行配置。 | |||
参见[配置速查表](administration/config-cheat-sheet.md#actions-actions)。 | |||
这是与 GitHub Actions 的一个区别,GitHub Actions 只允许使用托管在 GitHub 上的 actions 脚本。 | |||
但用户理应拥有权利去灵活决定如何运行 Actions。 | |||
这是与GitHub Actions的一个区别,但它应该允许用户以更灵活的方式运行Actions。 | |||
另外,如果您希望您的 Runner 默认从您自己的 Gitea 实例下载 Actions,可以通过设置 `[actions].DEFAULT_ACTIONS_URL`进行配置。 | |||
参见[配置速查表](administration/config-cheat-sheet.md#actions-actions)。 | |||
## 如何限制Runner的权限? | |||
@@ -61,8 +61,8 @@ It is always a bad idea to use a loopback address such as `127.0.0.1` or `localh | |||
If you are unsure which address to use, the LAN address is usually the right choice. | |||
`token` is used for authentication and identification, such as `P2U1U0oB4XaRCi8azcngmPCLbRpUGapalhmddh23`. | |||
It is one-time use only and cannot be used to register multiple runners. | |||
You can obtain different levels of 'tokens' from the following places to create the corresponding level of' runners': | |||
Each token can be used to create multiple runners, until it is replaced with a new token using the reset link. | |||
You can obtain different levels of 'tokens' from the following places to create the corresponding level of 'runners': | |||
- Instance level: The admin settings page, like `<your_gitea.com>/admin/actions/runners`. | |||
- Organization level: The organization settings page, like `<your_gitea.com>/<org>/settings/actions/runners`. |
@@ -0,0 +1,37 @@ | |||
--- | |||
date: "2023-02-25T00:00:00+00:00" | |||
title: "Badge" | |||
slug: "badge" | |||
sidebar_position: 11 | |||
toc: false | |||
draft: false | |||
aliases: | |||
- /en-us/badge | |||
menu: | |||
sidebar: | |||
parent: "usage" | |||
name: "Badge" | |||
sidebar_position: 11 | |||
identifier: "Badge" | |||
--- | |||
# Badge | |||
Gitea has its builtin Badge system which allows you to display the status of your repository in other places. You can use the following badges: | |||
## Workflow Badge | |||
The Gitea Actions workflow badge is a badge that shows the status of the latest workflow run. | |||
It is designed to be compatible with [GitHub Actions workflow badge](https://docs.github.com/en/actions/monitoring-and-troubleshooting-workflows/adding-a-workflow-status-badge). | |||
You can use the following URL to get the badge: | |||
``` | |||
https://your-gitea-instance.com/{owner}/{repo}/actions/workflows/{workflow_file}?branch={branch}&event={event} | |||
``` | |||
- `{owner}`: The owner of the repository. | |||
- `{repo}`: The name of the repository. | |||
- `{workflow_file}`: The name of the workflow file. | |||
- `{branch}`: Optional. The branch of the workflow. Default to your repository's default branch. | |||
- `{event}`: Optional. The event of the workflow. Default to none. |
@@ -0,0 +1,56 @@ | |||
--- | |||
date: "2024-01-31T00:00:00+00:00" | |||
title: "Blocking a user" | |||
slug: "blocking-user" | |||
sidebar_position: 25 | |||
toc: false | |||
draft: false | |||
aliases: | |||
- /en-us/webhooks | |||
menu: | |||
sidebar: | |||
parent: "usage" | |||
name: "Blocking a user" | |||
sidebar_position: 30 | |||
identifier: "blocking-user" | |||
--- | |||
# Blocking a user | |||
Gitea supports blocking of users to restrict how they can interact with you and your content. | |||
You can block a user in your account settings, from the user's profile or from comments created by the user. | |||
The user is not directly notified about the block, but they can notice they are blocked when they attempt to interact with you. | |||
Organization owners can block anyone who is not a member of the organization too. | |||
If a blocked user has admin permissions, they can still perform all actions even if blocked. | |||
### When you block a user | |||
- the user stops following you | |||
- you stop following the user | |||
- the user's stars are removed from your repositories | |||
- your stars are removed from their repositories | |||
- the user stops watching your repositories | |||
- you stop watching their repositories | |||
- the user's issue assignments are removed from your repositories | |||
- your issue assignments are removed from their repositories | |||
- the user is removed as a collaborator on your repositories | |||
- you are removed as a collaborator on their repositories | |||
- any pending repository transfers to or from the blocked user are canceled | |||
### When you block a user, the user cannot | |||
- follow you | |||
- watch your repositories | |||
- star your repositories | |||
- fork your repositories | |||
- transfer repositories to you | |||
- open issues or pull requests on your repositories | |||
- comment on issues or pull requests you've created | |||
- comment on issues or pull requests on your repositories | |||
- react to your comments on issues or pull requests | |||
- react to comments on issues or pull requests on your repositories | |||
- assign you to issues or pull requests | |||
- add you as a collaborator on their repositories | |||
- send you notifications by @mentioning your username | |||
- be added as team member (if blocked by an organization) |
@@ -19,9 +19,10 @@ menu: | |||
Some projects have a standard list of questions that users need to answer | |||
when creating an issue or pull request. Gitea supports adding templates to the | |||
main branch of the repository so that they can autopopulate the form when users are | |||
**default branch of the repository** so that they can autopopulate the form when users are | |||
creating issues and pull requests. This will cut down on the initial back and forth | |||
of getting some clarifying details. | |||
It is currently not possible to provide generic issue/pull-request templates globally. | |||
Additionally, the New Issue page URL can be suffixed with `?title=Issue+Title&body=Issue+Text` and the form will be populated with those strings. Those strings will be used instead of the template if there is one. | |||
@@ -135,6 +136,12 @@ body: | |||
attributes: | |||
value: | | |||
Thanks for taking the time to fill out this bug report! | |||
# some markdown that will only be visible once the issue has been created | |||
- type: markdown | |||
attributes: | |||
value: | | |||
This issue was created by an issue **template** :) | |||
visible: [content] | |||
- type: input | |||
id: contact | |||
attributes: | |||
@@ -186,11 +193,16 @@ body: | |||
options: | |||
- label: I agree to follow this project's Code of Conduct | |||
required: true | |||
- label: I have also read the CONTRIBUTION.MD | |||
required: true | |||
visible: [form] | |||
- label: This is a TODO only visible after issue creation | |||
visible: [content] | |||
``` | |||
### Markdown | |||
You can use a `markdown` element to display Markdown in your form that provides extra context to the user, but is not submitted. | |||
You can use a `markdown` element to display Markdown in your form that provides extra context to the user, but is not submitted by default. | |||
Attributes: | |||
@@ -198,6 +210,8 @@ Attributes: | |||
|-------|--------------------------------------------------------------|----------|--------|---------|--------------| | |||
| value | The text that is rendered. Markdown formatting is supported. | Required | String | - | - | | |||
visible: Default is **[form]** | |||
### Textarea | |||
You can use a `textarea` element to add a multi-line text field to your form. Contributors can also attach files in `textarea` fields. | |||
@@ -218,6 +232,8 @@ Validations: | |||
|----------|------------------------------------------------------|----------|---------|---------|--------------| | |||
| required | Prevents form submission until element is completed. | Optional | Boolean | false | - | | |||
visible: Default is **[form, content]** | |||
### Input | |||
You can use an `input` element to add a single-line text field to your form. | |||
@@ -239,6 +255,8 @@ Validations: | |||
| is_number | Prevents form submission until element is filled with a number. | Optional | Boolean | false | - | | |||
| regex | Prevents form submission until element is filled with a value that match the regular expression. | Optional | String | - | a [regular expression](https://en.wikipedia.org/wiki/Regular_expression) | | |||
visible: Default is **[form, content]** | |||
### Dropdown | |||
You can use a `dropdown` element to add a dropdown menu in your form. | |||
@@ -258,6 +276,8 @@ Validations: | |||
|----------|------------------------------------------------------|----------|---------|---------|--------------| | |||
| required | Prevents form submission until element is completed. | Optional | Boolean | false | - | | |||
visible: Default is **[form, content]** | |||
### Checkboxes | |||
You can use the `checkboxes` element to add a set of checkboxes to your form. | |||
@@ -265,17 +285,20 @@ You can use the `checkboxes` element to add a set of checkboxes to your form. | |||
Attributes: | |||
| Key | Description | Required | Type | Default | Valid values | | |||
|-------------|-------------------------------------------------------------------------------------------------------|----------|--------|--------------|--------------| | |||
| ----------- | ----------------------------------------------------------------------------------------------------- | -------- | ------ | ------------ | ------------ | | |||
| label | A brief description of the expected user input, which is displayed in the form. | Required | String | - | - | | |||
| description | A description of the set of checkboxes, which is displayed in the form. Supports Markdown formatting. | Optional | String | Empty String | - | | |||
| options | An array of checkboxes that the user can select. For syntax, see below. | Required | Array | - | - | | |||
For each value in the options array, you can set the following keys. | |||
| Key | Description | Required | Type | Default | Options | | |||
|----------|------------------------------------------------------------------------------------------------------------------------------------------|----------|---------|---------|---------| | |||
| label | The identifier for the option, which is displayed in the form. Markdown is supported for bold or italic text formatting, and hyperlinks. | Required | String | - | - | | |||
| required | Prevents form submission until element is completed. | Optional | Boolean | false | - | | |||
| Key | Description | Required | Type | Default | Options | | |||
|--------------|------------------------------------------------------------------------------------------------------------------------------------------|----------|--------------|---------|---------| | |||
| label | The identifier for the option, which is displayed in the form. Markdown is supported for bold or italic text formatting, and hyperlinks. | Required | String | - | - | | |||
| required | Prevents form submission until element is completed. | Optional | Boolean | false | - | | |||
| visible | Whether a specific checkbox appears in the form only, in the created issue only, or both. Valid options are "form" and "content". | Optional | String array | false | - | | |||
visible: Default is **[form, content]** | |||
## Syntax for issue config | |||
@@ -291,15 +314,15 @@ contact_links: | |||
### Possible Options | |||
| Key | Description | Type | Default | | |||
|----------------------|-------------------------------------------------------------------------------------------------------|--------------------|----------------| | |||
| blank_issues_enabled | If set to false, the User is forced to use a Template | Boolean | true | | |||
| contact_links | Custom Links to show in the Choose Box | Contact Link Array | Empty Array | | |||
| Key | Description | Type | Default | | |||
|----------------------|-------------------------------------------------------|--------------------|-------------| | |||
| blank_issues_enabled | If set to false, the User is forced to use a Template | Boolean | true | | |||
| contact_links | Custom Links to show in the Choose Box | Contact Link Array | Empty Array | | |||
### Contact Link | |||
| Key | Description | Type | Required | | |||
|----------------------|-------------------------------------------------------------------------------------------------------|---------|----------| | |||
| name | the name of your link | String | true | | |||
| url | The URL of your Link | String | true | | |||
| about | A short description of your Link | String | true | | |||
| Key | Description | Type | Required | | |||
|-------|----------------------------------|--------|----------| | |||
| name | the name of your link | String | true | | |||
| url | The URL of your Link | String | true | | |||
| about | A short description of your Link | String | true | |
@@ -102,7 +102,7 @@ DELETE https://gitea.example.com/api/packages/{owner}/alpine/{branch}/{repositor | |||
| `branch` | The branch to use. | | |||
| `repository` | The repository to use. | | |||
| `architecture` | The package architecture. | | |||
| `filename` | The file to delete. | |||
| `filename` | The file to delete. | | |||
Example request using HTTP Basic authentication: | |||
@@ -39,6 +39,16 @@ Images must follow this naming convention: | |||
`{registry}/{owner}/{image}` | |||
When building your docker image, using the naming convention above, this looks like: | |||
```shell | |||
# build an image with tag | |||
docker build -t {registry}/{owner}/{image}:{tag} . | |||
# name an existing image with tag | |||
docker tag {some-existing-image}:{tag} {registry}/{owner}/{image}:{tag} | |||
``` | |||
where your registry is the domain of your gitea instance (e.g. gitea.example.com). | |||
For example, these are all valid image names for the owner `testuser`: | |||
`gitea.example.com/testuser/myimage` |
@@ -42,7 +42,7 @@ The following package managers are currently supported: | |||
| [PyPI](usage/packages/pypi.md) | Python | `pip`, `twine` | | |||
| [RPM](usage/packages/rpm.md) | - | `yum`, `dnf`, `zypper` | | |||
| [RubyGems](usage/packages/rubygems.md) | Ruby | `gem`, `Bundler` | | |||
| [Swift](usage/packages/rubygems.md) | Swift | `swift` | | |||
| [Swift](usage/packages/swift.md) | Swift | `swift` | | |||
| [Vagrant](usage/packages/vagrant.md) | - | `vagrant` | | |||
**The following paragraphs only apply if Packages are not globally disabled!** |
@@ -24,16 +24,26 @@ The following examples use `dnf`. | |||
## Configuring the package registry | |||
To register the RPM registry add the url to the list of known apt sources: | |||
To register the RPM registry add the url to the list of known sources: | |||
```shell | |||
dnf config-manager --add-repo https://gitea.example.com/api/packages/{owner}/rpm/{group}.repo | |||
``` | |||
| Placeholder | Description | | |||
| ----------- |----------------------------------------------------| | |||
| `owner` | The owner of the package. | | |||
| `group` | Everything, e.g. `el7`, `rocky/el9` , `test/fc38`.| | |||
| Placeholder | Description | | |||
| ----------- | ----------- | | |||
| `owner` | The owner of the package. | | |||
| `group` | Optional: Everything, e.g. empty, `el7`, `rocky/el9`, `test/fc38`. | | |||
Example: | |||
```shell | |||
# without a group | |||
dnf config-manager --add-repo https://gitea.example.com/api/packages/testuser/rpm.repo | |||
# with the group 'centos/el7' | |||
dnf config-manager --add-repo https://gitea.example.com/api/packages/testuser/rpm/centos/el7.repo | |||
``` | |||
If the registry is private, provide credentials in the url. You can use a password or a [personal access token](development/api-usage.md#authentication): | |||
@@ -41,7 +51,7 @@ If the registry is private, provide credentials in the url. You can use a passwo | |||
dnf config-manager --add-repo https://{username}:{your_password_or_token}@gitea.example.com/api/packages/{owner}/rpm/{group}.repo | |||
``` | |||
You have to add the credentials to the urls in the `rpm.repo` file in `/etc/yum.repos.d` too. | |||
You have to add the credentials to the urls in the created `.repo` file in `/etc/yum.repos.d` too. | |||
## Publish a package | |||
@@ -54,11 +64,17 @@ PUT https://gitea.example.com/api/packages/{owner}/rpm/{group}/upload | |||
| Parameter | Description | | |||
| --------- | ----------- | | |||
| `owner` | The owner of the package. | | |||
| `group` | Everything, e.g. `el7`, `rocky/el9` , `test/fc38`.| | |||
| `group` | Optional: Everything, e.g. empty, `el7`, `rocky/el9`, `test/fc38`. | | |||
Example request using HTTP Basic authentication: | |||
```shell | |||
# without a group | |||
curl --user your_username:your_password_or_token \ | |||
--upload-file path/to/file.rpm \ | |||
https://gitea.example.com/api/packages/testuser/rpm/upload | |||
# with the group 'centos/el7' | |||
curl --user your_username:your_password_or_token \ | |||
--upload-file path/to/file.rpm \ | |||
https://gitea.example.com/api/packages/testuser/rpm/centos/el7/upload | |||
@@ -83,17 +99,22 @@ To delete an RPM package perform a HTTP DELETE operation. This will delete the p | |||
DELETE https://gitea.example.com/api/packages/{owner}/rpm/{group}/package/{package_name}/{package_version}/{architecture} | |||
``` | |||
| Parameter | Description | | |||
|-------------------|----------------------------| | |||
| `owner` | The owner of the package. | | |||
| `group` | The package group . | | |||
| `package_name` | The package name. | | |||
| `package_version` | The package version. | | |||
| `architecture` | The package architecture. | | |||
| Parameter | Description | | |||
| ----------------- | ----------- | | |||
| `owner` | The owner of the package. | | |||
| `group` | Optional: The package group. | | |||
| `package_name` | The package name. | | |||
| `package_version` | The package version. | | |||
| `architecture` | The package architecture. | | |||
Example request using HTTP Basic authentication: | |||
```shell | |||
# without a group | |||
curl --user your_username:your_token_or_password -X DELETE \ | |||
https://gitea.example.com/api/packages/testuser/rpm/package/test-package/1.0.0/x86_64 | |||
# with the group 'centos/el7' | |||
curl --user your_username:your_token_or_password -X DELETE \ | |||
https://gitea.example.com/api/packages/testuser/rpm/centos/el7/package/test-package/1.0.0/x86_64 | |||
``` |
@@ -26,7 +26,8 @@ To work with the Swift package registry, you need to use [swift](https://www.swi | |||
To register the package registry and provide credentials, execute: | |||
```shell | |||
swift package-registry set https://gitea.example.com/api/packages/{owner}/swift -login {username} -password {password} | |||
swift package-registry set https://gitea.example.com/api/packages/{owner}/swift | |||
swift package-registry login https://gitea.example.com/api/packages/{owner}/swift --username {username} --password {password} | |||
``` | |||
| Placeholder | Description | |
@@ -19,3 +19,7 @@ To display a Markdown file in your Gitea user or organization profile page, crea | |||
Gitea will automatically display the contents of the file on your profile, in a new "Overview" above your repositories. | |||
Making the `.profile` repository private will hide the Profile README. | |||
Example of user with `.profile/README.md`: | |||
![profile readme screenshot](/images/usage/profile-readme.png) |
@@ -15,6 +15,10 @@ menu: | |||
# 个人资料 README | |||
要在您的 Gitea 个人资料页面显示一个 Markdown 文件,只需创建一个名为 ".profile" 的仓库,并编辑其中的 README.md 文件。Gitea 将自动获取该文件并在您的仓库上方显示。 | |||
要在您的 Gitea 个人资料页面显示一个 Markdown 文件,只需创建一个名为 `.profile` 的仓库,并编辑其中的 `README.md` 文件。Gitea 将自动获取该文件并在您的仓库上方显示。 | |||
注意:您可以将此仓库设为私有。这样可以隐藏您的源文件,使其对公众不可见,并允许您将某些文件设为私有。但是,README.md 文件将是您个人资料上唯一存在的文件。如果您希望完全私有化 .profile 仓库,则需删除或重命名 README.md 文件。 | |||
用户示例 `.profile/README.md`: | |||
![个人资料自述文件截图](/images/usage/profile-readme.png) |
@@ -1,34 +0,0 @@ | |||
#!/usr/bin/env bash | |||
set -e | |||
# | |||
# This script is used to copy the en-US content to our available locales as a | |||
# fallback to always show all pages when displaying a specific locale that is | |||
# missing some documents to be translated. | |||
# | |||
# Just execute the script without any argument and you will get the missing | |||
# files copied into the content folder. We are calling this script within the CI | |||
# server simply by `make trans-copy`. | |||
# | |||
declare -a LOCALES=( | |||
"fr-fr" | |||
"nl-nl" | |||
"pt-br" | |||
"zh-cn" | |||
"zh-tw" | |||
) | |||
ROOT=$(realpath $(dirname $0)/..) | |||
for SOURCE in $(find ${ROOT}/content -type f -iname *.en-us.md); do | |||
for LOCALE in "${LOCALES[@]}"; do | |||
DEST="${SOURCE%.en-us.md}.${LOCALE}.md" | |||
if [[ ! -f ${DEST} ]]; then | |||
cp ${SOURCE} ${DEST} | |||
sed -i.bak "s/en\-us/${LOCALE}/g" ${DEST} | |||
rm ${DEST}.bak | |||
fi | |||
done | |||
done |
@@ -1,27 +1,27 @@ | |||
module code.gitea.io/gitea | |||
go 1.21 | |||
go 1.22 | |||
require ( | |||
code.gitea.io/actions-proto-go v0.3.1 | |||
code.gitea.io/actions-proto-go v0.4.0 | |||
code.gitea.io/gitea-vet v0.2.3 | |||
code.gitea.io/sdk/gitea v0.17.0 | |||
code.gitea.io/sdk/gitea v0.17.1 | |||
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570 | |||
gitea.com/go-chi/binding v0.0.0-20230415142243-04b515c6d669 | |||
connectrpc.com/connect v1.15.0 | |||
gitea.com/go-chi/binding v0.0.0-20240316035258-17450c5f3028 | |||
gitea.com/go-chi/cache v0.2.0 | |||
gitea.com/go-chi/captcha v0.0.0-20230415143339-2c0754df4384 | |||
gitea.com/go-chi/session v0.0.0-20230613035928-39541325faa3 | |||
gitea.com/go-chi/captcha v0.0.0-20240315150714-fb487f629098 | |||
gitea.com/go-chi/session v0.0.0-20240316035857-16768d98ec96 | |||
gitea.com/lunny/dingtalk_webhook v0.0.0-20171025031554-e3534c89ef96 | |||
gitea.com/lunny/levelqueue v0.4.2-0.20230414023320-3c0159fe0fe4 | |||
github.com/42wim/sshsig v0.0.0-20211121163825-841cf5bbc121 | |||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 | |||
github.com/NYTimes/gziphandler v1.1.1 | |||
github.com/PuerkitoBio/goquery v1.8.1 | |||
github.com/alecthomas/chroma/v2 v2.12.0 | |||
github.com/PuerkitoBio/goquery v1.9.1 | |||
github.com/alecthomas/chroma/v2 v2.13.0 | |||
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb | |||
github.com/blevesearch/bleve/v2 v2.3.10 | |||
github.com/bufbuild/connect-go v1.10.0 | |||
github.com/buildkite/terminal-to-html/v3 v3.10.0 | |||
github.com/buildkite/terminal-to-html/v3 v3.11.0 | |||
github.com/caddyserver/certmagic v0.20.0 | |||
github.com/chi-middleware/proxy v1.1.1 | |||
github.com/denisenkom/go-mssqldb v0.12.3 | |||
@@ -30,128 +30,127 @@ require ( | |||
github.com/djherbis/nio/v3 v3.0.1 | |||
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 | |||
github.com/dustin/go-humanize v1.0.1 | |||
github.com/editorconfig/editorconfig-core-go/v2 v2.6.0 | |||
github.com/editorconfig/editorconfig-core-go/v2 v2.6.1 | |||
github.com/emersion/go-imap v1.2.1 | |||
github.com/emirpasic/gods v1.18.1 | |||
github.com/ethantkoenig/rupture v1.0.1 | |||
github.com/felixge/fgprof v0.9.3 | |||
github.com/felixge/fgprof v0.9.4 | |||
github.com/fsnotify/fsnotify v1.7.0 | |||
github.com/gliderlabs/ssh v0.3.6-0.20230927171611-ece6c7995e46 | |||
github.com/go-ap/activitypub v0.0.0-20231114162308-e219254dc5c9 | |||
github.com/gliderlabs/ssh v0.3.6 | |||
github.com/go-ap/activitypub v0.0.0-20240316125321-b61fd6a83225 | |||
github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73 | |||
github.com/go-chi/chi/v5 v5.0.10 | |||
github.com/go-chi/chi/v5 v5.0.12 | |||
github.com/go-chi/cors v1.2.1 | |||
github.com/go-co-op/gocron v1.37.0 | |||
github.com/go-enry/go-enry/v2 v2.8.6 | |||
github.com/go-enry/go-enry/v2 v2.8.7 | |||
github.com/go-fed/httpsig v1.1.1-0.20201223112313-55836744818e | |||
github.com/go-git/go-billy/v5 v5.5.0 | |||
github.com/go-git/go-git/v5 v5.9.0 | |||
github.com/go-git/go-git/v5 v5.11.0 | |||
github.com/go-ldap/ldap/v3 v3.4.6 | |||
github.com/go-sql-driver/mysql v1.7.1 | |||
github.com/go-sql-driver/mysql v1.8.0 | |||
github.com/go-swagger/go-swagger v0.30.5 | |||
github.com/go-testfixtures/testfixtures/v3 v3.9.0 | |||
github.com/go-webauthn/webauthn v0.9.4 | |||
github.com/go-testfixtures/testfixtures/v3 v3.10.0 | |||
github.com/go-webauthn/webauthn v0.10.2 | |||
github.com/gobwas/glob v0.2.3 | |||
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f | |||
github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85 | |||
github.com/golang-jwt/jwt/v5 v5.2.0 | |||
github.com/golang-jwt/jwt/v5 v5.2.1 | |||
github.com/google/go-github/v57 v57.0.0 | |||
github.com/google/pprof v0.0.0-20231212022811-ec68065c825e | |||
github.com/google/uuid v1.5.0 | |||
github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7 | |||
github.com/google/uuid v1.6.0 | |||
github.com/gorilla/feeds v1.1.2 | |||
github.com/gorilla/sessions v1.2.2 | |||
github.com/hashicorp/go-version v1.6.0 | |||
github.com/hashicorp/golang-lru/v2 v2.0.7 | |||
github.com/huandu/xstrings v1.4.0 | |||
github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056 | |||
github.com/jhillyerd/enmime v1.1.0 | |||
github.com/jhillyerd/enmime v1.2.0 | |||
github.com/json-iterator/go v1.1.12 | |||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 | |||
github.com/keybase/go-crypto v0.0.0-20200123153347-de78d2cb44f4 | |||
github.com/klauspost/compress v1.17.4 | |||
github.com/klauspost/cpuid/v2 v2.2.6 | |||
github.com/klauspost/compress v1.17.7 | |||
github.com/klauspost/cpuid/v2 v2.2.7 | |||
github.com/lib/pq v1.10.9 | |||
github.com/markbates/goth v1.78.0 | |||
github.com/markbates/goth v1.79.0 | |||
github.com/mattn/go-isatty v0.0.20 | |||
github.com/mattn/go-sqlite3 v1.14.19 | |||
github.com/meilisearch/meilisearch-go v0.26.0 | |||
github.com/mattn/go-sqlite3 v1.14.22 | |||
github.com/meilisearch/meilisearch-go v0.26.2 | |||
github.com/mholt/archiver/v3 v3.5.1 | |||
github.com/microcosm-cc/bluemonday v1.0.26 | |||
github.com/minio/minio-go/v7 v7.0.66 | |||
github.com/minio/sha256-simd v1.0.1 | |||
github.com/minio/minio-go/v7 v7.0.69 | |||
github.com/msteinert/pam v1.2.0 | |||
github.com/nektos/act v0.2.52 | |||
github.com/niklasfasching/go-org v1.7.0 | |||
github.com/olivere/elastic/v7 v7.0.32 | |||
github.com/opencontainers/go-digest v1.0.0 | |||
github.com/opencontainers/image-spec v1.1.0-rc5 | |||
github.com/opencontainers/image-spec v1.1.0 | |||
github.com/pkg/errors v0.9.1 | |||
github.com/pquerna/otp v1.4.0 | |||
github.com/prometheus/client_golang v1.17.0 | |||
github.com/prometheus/client_golang v1.19.0 | |||
github.com/quasoft/websspi v1.1.2 | |||
github.com/redis/go-redis/v9 v9.3.0 | |||
github.com/redis/go-redis/v9 v9.5.1 | |||
github.com/robfig/cron/v3 v3.0.1 | |||
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 | |||
github.com/sassoftware/go-rpmutils v0.2.0 | |||
github.com/sassoftware/go-rpmutils v0.3.0 | |||
github.com/sergi/go-diff v1.3.1 | |||
github.com/shurcooL/vfsgen v0.0.0-20230704071429-0000e147ea92 | |||
github.com/stretchr/testify v1.8.4 | |||
github.com/stretchr/testify v1.9.0 | |||
github.com/syndtr/goleveldb v1.0.0 | |||
github.com/tstranex/u2f v1.0.0 | |||
github.com/ulikunitz/xz v0.5.11 | |||
github.com/urfave/cli/v2 v2.26.0 | |||
github.com/xanzy/go-gitlab v0.95.2 | |||
github.com/urfave/cli/v2 v2.27.1 | |||
github.com/xanzy/go-gitlab v0.100.0 | |||
github.com/xeipuuv/gojsonschema v1.2.0 | |||
github.com/yohcop/openid-go v1.0.1 | |||
github.com/yuin/goldmark v1.6.0 | |||
github.com/yuin/goldmark v1.7.0 | |||
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc | |||
github.com/yuin/goldmark-meta v1.1.0 | |||
golang.org/x/crypto v0.17.0 | |||
golang.org/x/image v0.14.0 | |||
golang.org/x/net v0.19.0 | |||
golang.org/x/oauth2 v0.15.0 | |||
golang.org/x/sys v0.15.0 | |||
golang.org/x/crypto v0.21.0 | |||
golang.org/x/image v0.15.0 | |||
golang.org/x/net v0.22.0 | |||
golang.org/x/oauth2 v0.18.0 | |||
golang.org/x/sys v0.18.0 | |||
golang.org/x/text v0.14.0 | |||
golang.org/x/tools v0.16.1 | |||
google.golang.org/grpc v1.60.0 | |||
google.golang.org/protobuf v1.31.0 | |||
golang.org/x/tools v0.19.0 | |||
google.golang.org/grpc v1.62.1 | |||
google.golang.org/protobuf v1.33.0 | |||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df | |||
gopkg.in/ini.v1 v1.67.0 | |||
gopkg.in/yaml.v3 v3.0.1 | |||
mvdan.cc/xurls/v2 v2.5.0 | |||
strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251 | |||
xorm.io/builder v0.3.13 | |||
xorm.io/xorm v1.3.7-0.20240101024435-4992cba040fe | |||
xorm.io/xorm v1.3.8 | |||
) | |||
require ( | |||
cloud.google.com/go/compute v1.23.3 // indirect | |||
cloud.google.com/go/compute v1.25.1 // indirect | |||
cloud.google.com/go/compute/metadata v0.2.3 // indirect | |||
dario.cat/mergo v1.0.0 // indirect | |||
filippo.io/edwards25519 v1.1.0 // indirect | |||
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078 // indirect | |||
github.com/ClickHouse/ch-go v0.61.0 // indirect | |||
github.com/ClickHouse/clickhouse-go/v2 v2.16.0 // indirect | |||
github.com/ClickHouse/ch-go v0.61.5 // indirect | |||
github.com/ClickHouse/clickhouse-go/v2 v2.22.0 // indirect | |||
github.com/DataDog/zstd v1.5.5 // indirect | |||
github.com/Masterminds/goutils v1.1.1 // indirect | |||
github.com/Masterminds/semver/v3 v3.2.1 // indirect | |||
github.com/Masterminds/sprig/v3 v3.2.3 // indirect | |||
github.com/Microsoft/go-winio v0.6.1 // indirect | |||
github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c // indirect | |||
github.com/RoaringBitmap/roaring v1.7.0 // indirect | |||
github.com/acomagu/bufpipe v1.0.4 // indirect | |||
github.com/andybalholm/brotli v1.0.6 // indirect | |||
github.com/ProtonMail/go-crypto v1.0.0 // indirect | |||
github.com/RoaringBitmap/roaring v1.9.0 // indirect | |||
github.com/andybalholm/brotli v1.1.0 // indirect | |||
github.com/andybalholm/cascadia v1.3.2 // indirect | |||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect | |||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect | |||
github.com/aymerick/douceur v0.2.0 // indirect | |||
github.com/beorn7/perks v1.0.1 // indirect | |||
github.com/bits-and-blooms/bitset v1.12.0 // indirect | |||
github.com/blevesearch/bleve_index_api v1.1.4 // indirect | |||
github.com/blevesearch/geo v0.1.18 // indirect | |||
github.com/bits-and-blooms/bitset v1.13.0 // indirect | |||
github.com/blevesearch/bleve_index_api v1.1.6 // indirect | |||
github.com/blevesearch/geo v0.1.20 // indirect | |||
github.com/blevesearch/go-porterstemmer v1.0.3 // indirect | |||
github.com/blevesearch/gtreap v0.1.1 // indirect | |||
github.com/blevesearch/mmap-go v1.0.4 // indirect | |||
github.com/blevesearch/scorch_segment_api/v2 v2.2.5 // indirect | |||
github.com/blevesearch/scorch_segment_api/v2 v2.2.8 // indirect | |||
github.com/blevesearch/segment v0.9.1 // indirect | |||
github.com/blevesearch/snowballstem v0.9.0 // indirect | |||
github.com/blevesearch/upsidedown_store_api v1.0.2 // indirect | |||
@@ -165,45 +164,45 @@ require ( | |||
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 // indirect | |||
github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a // indirect | |||
github.com/cespare/xxhash/v2 v2.2.0 // indirect | |||
github.com/cloudflare/circl v1.3.6 // indirect | |||
github.com/cloudflare/circl v1.3.7 // indirect | |||
github.com/couchbase/go-couchbase v0.1.1 // indirect | |||
github.com/couchbase/gomemcached v0.3.0 // indirect | |||
github.com/couchbase/gomemcached v0.3.1 // indirect | |||
github.com/couchbase/goutils v0.1.2 // indirect | |||
github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect | |||
github.com/cyphar/filepath-securejoin v0.2.4 // indirect | |||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect | |||
github.com/davidmz/go-pageant v1.0.2 // indirect | |||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect | |||
github.com/dlclark/regexp2 v1.10.0 // indirect | |||
github.com/dlclark/regexp2 v1.11.0 // indirect | |||
github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43 // indirect | |||
github.com/fatih/color v1.16.0 // indirect | |||
github.com/felixge/httpsnoop v1.0.4 // indirect | |||
github.com/fxamacker/cbor/v2 v2.5.0 // indirect | |||
github.com/go-ap/errors v0.0.0-20231003111023-183eef4b31b7 // indirect | |||
github.com/fxamacker/cbor/v2 v2.6.0 // indirect | |||
github.com/go-ap/errors v0.0.0-20240304112515-6077fa9c17b0 // indirect | |||
github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect | |||
github.com/go-enry/go-oniguruma v1.2.1 // indirect | |||
github.com/go-faster/city v1.0.1 // indirect | |||
github.com/go-faster/errors v0.7.1 // indirect | |||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect | |||
github.com/go-openapi/analysis v0.21.5 // indirect | |||
github.com/go-openapi/errors v0.21.0 // indirect | |||
github.com/go-openapi/inflect v0.19.0 // indirect | |||
github.com/go-openapi/jsonpointer v0.20.1 // indirect | |||
github.com/go-openapi/jsonreference v0.20.3 // indirect | |||
github.com/go-openapi/loads v0.21.3 // indirect | |||
github.com/go-openapi/runtime v0.26.2 // indirect | |||
github.com/go-openapi/spec v0.20.12 // indirect | |||
github.com/go-openapi/strfmt v0.21.10 // indirect | |||
github.com/go-openapi/swag v0.22.5 // indirect | |||
github.com/go-openapi/validate v0.22.4 // indirect | |||
github.com/go-webauthn/x v0.1.5 // indirect | |||
github.com/go-openapi/analysis v0.23.0 // indirect | |||
github.com/go-openapi/errors v0.22.0 // indirect | |||
github.com/go-openapi/inflect v0.21.0 // indirect | |||
github.com/go-openapi/jsonpointer v0.21.0 // indirect | |||
github.com/go-openapi/jsonreference v0.21.0 // indirect | |||
github.com/go-openapi/loads v0.22.0 // indirect | |||
github.com/go-openapi/runtime v0.28.0 // indirect | |||
github.com/go-openapi/spec v0.21.0 // indirect | |||
github.com/go-openapi/strfmt v0.23.0 // indirect | |||
github.com/go-openapi/swag v0.23.0 // indirect | |||
github.com/go-openapi/validate v0.24.0 // indirect | |||
github.com/go-webauthn/x v0.1.9 // indirect | |||
github.com/goccy/go-json v0.10.2 // indirect | |||
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect | |||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect | |||
github.com/golang-sql/sqlexp v0.1.0 // indirect | |||
github.com/golang/geo v0.0.0-20230421003525-6adc56603217 // indirect | |||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect | |||
github.com/golang/protobuf v1.5.3 // indirect | |||
github.com/golang/protobuf v1.5.4 // indirect | |||
github.com/golang/snappy v0.0.4 // indirect | |||
github.com/google/go-querystring v1.1.0 // indirect | |||
github.com/google/go-tpm v0.9.0 // indirect | |||
@@ -228,10 +227,10 @@ require ( | |||
github.com/markbates/going v1.0.3 // indirect | |||
github.com/mattn/go-colorable v0.1.13 // indirect | |||
github.com/mattn/go-runewidth v0.0.15 // indirect | |||
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect | |||
github.com/mholt/acmez v1.2.0 // indirect | |||
github.com/miekg/dns v1.1.57 // indirect | |||
github.com/miekg/dns v1.1.58 // indirect | |||
github.com/minio/md5-simd v1.1.2 // indirect | |||
github.com/minio/sha256-simd v1.0.1 // indirect | |||
github.com/mitchellh/copystructure v1.2.0 // indirect | |||
github.com/mitchellh/mapstructure v1.5.0 // indirect | |||
github.com/mitchellh/reflectwalk v1.0.2 // indirect | |||
@@ -243,16 +242,16 @@ require ( | |||
github.com/oklog/ulid v1.3.1 // indirect | |||
github.com/olekukonko/tablewriter v0.0.5 // indirect | |||
github.com/onsi/ginkgo v1.16.5 // indirect | |||
github.com/paulmach/orb v0.10.0 // indirect | |||
github.com/paulmach/orb v0.11.1 // indirect | |||
github.com/pelletier/go-toml/v2 v2.1.1 // indirect | |||
github.com/pierrec/lz4/v4 v4.1.19 // indirect | |||
github.com/pierrec/lz4/v4 v4.1.21 // indirect | |||
github.com/pjbgf/sha1cd v0.3.0 // indirect | |||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect | |||
github.com/prometheus/client_model v0.5.0 // indirect | |||
github.com/prometheus/common v0.45.0 // indirect | |||
github.com/prometheus/procfs v0.12.0 // indirect | |||
github.com/rhysd/actionlint v1.6.26 // indirect | |||
github.com/rivo/uniseg v0.4.4 // indirect | |||
github.com/prometheus/client_model v0.6.0 // indirect | |||
github.com/prometheus/common v0.50.0 // indirect | |||
github.com/prometheus/procfs v0.13.0 // indirect | |||
github.com/rhysd/actionlint v1.6.27 // indirect | |||
github.com/rivo/uniseg v0.4.7 // indirect | |||
github.com/rogpeppe/go-internal v1.12.0 // indirect | |||
github.com/rs/xid v1.5.0 // indirect | |||
github.com/russross/blackfriday/v2 v2.1.0 // indirect | |||
@@ -262,7 +261,7 @@ require ( | |||
github.com/shopspring/decimal v1.3.1 // indirect | |||
github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c // indirect | |||
github.com/sirupsen/logrus v1.9.3 // indirect | |||
github.com/skeema/knownhosts v1.2.1 // indirect | |||
github.com/skeema/knownhosts v1.2.2 // indirect | |||
github.com/sourcegraph/conc v0.3.0 // indirect | |||
github.com/spf13/afero v1.11.0 // indirect | |||
github.com/spf13/cast v1.6.0 // indirect | |||
@@ -273,28 +272,28 @@ require ( | |||
github.com/toqueteos/webbrowser v1.2.0 // indirect | |||
github.com/unknwon/com v1.0.1 // indirect | |||
github.com/valyala/bytebufferpool v1.0.0 // indirect | |||
github.com/valyala/fasthttp v1.51.0 // indirect | |||
github.com/valyala/fasthttp v1.52.0 // indirect | |||
github.com/valyala/fastjson v1.6.4 // indirect | |||
github.com/x448/float16 v0.8.4 // indirect | |||
github.com/xanzy/ssh-agent v0.3.3 // indirect | |||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect | |||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect | |||
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect | |||
github.com/xrash/smetrics v0.0.0-20231213231151-1d8dd44e695e // indirect | |||
github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 // indirect | |||
github.com/zeebo/blake3 v0.2.3 // indirect | |||
go.etcd.io/bbolt v1.3.8 // indirect | |||
go.mongodb.org/mongo-driver v1.13.1 // indirect | |||
go.opentelemetry.io/otel v1.21.0 // indirect | |||
go.opentelemetry.io/otel/trace v1.21.0 // indirect | |||
go.etcd.io/bbolt v1.3.9 // indirect | |||
go.mongodb.org/mongo-driver v1.14.0 // indirect | |||
go.opentelemetry.io/otel v1.24.0 // indirect | |||
go.opentelemetry.io/otel/trace v1.24.0 // indirect | |||
go.uber.org/atomic v1.11.0 // indirect | |||
go.uber.org/multierr v1.11.0 // indirect | |||
go.uber.org/zap v1.26.0 // indirect | |||
golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611 // indirect | |||
golang.org/x/mod v0.14.0 // indirect | |||
golang.org/x/sync v0.5.0 // indirect | |||
go.uber.org/zap v1.27.0 // indirect | |||
golang.org/x/exp v0.0.0-20240314144324-c7f7c6466f7f // indirect | |||
golang.org/x/mod v0.16.0 // indirect | |||
golang.org/x/sync v0.6.0 // indirect | |||
golang.org/x/time v0.5.0 // indirect | |||
google.golang.org/appengine v1.6.8 // indirect | |||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0 // indirect | |||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c // indirect | |||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect | |||
gopkg.in/warnings.v0 v0.1.2 // indirect | |||
gopkg.in/yaml.v2 v2.4.0 // indirect | |||
@@ -304,7 +303,9 @@ replace github.com/hashicorp/go-version => github.com/6543/go-version v1.3.1 | |||
replace github.com/shurcooL/vfsgen => github.com/lunny/vfsgen v0.0.0-20220105142115-2c99e1ffdfa0 | |||
replace github.com/nektos/act => gitea.com/gitea/act v0.2.51 | |||
replace github.com/nektos/act => gitea.com/gitea/act v0.259.1 | |||
replace github.com/gorilla/feeds => github.com/yardenshoham/feeds v0.0.0-20240110072658-f3d0c21c0bd5 | |||
exclude github.com/gofrs/uuid v3.2.0+incompatible | |||
@@ -26,6 +26,8 @@ const ( | |||
ArtifactStatusUploadConfirmed // 2, ArtifactStatusUploadConfirmed is the status of an artifact upload that is confirmed | |||
ArtifactStatusUploadError // 3, ArtifactStatusUploadError is the status of an artifact upload that is errored | |||
ArtifactStatusExpired // 4, ArtifactStatusExpired is the status of an artifact that is expired | |||
ArtifactStatusPendingDeletion // 5, ArtifactStatusPendingDeletion is the status of an artifact that is pending deletion | |||
ArtifactStatusDeleted // 6, ArtifactStatusDeleted is the status of an artifact that is deleted | |||
) | |||
func init() { | |||
@@ -147,8 +149,28 @@ func ListNeedExpiredArtifacts(ctx context.Context) ([]*ActionArtifact, error) { | |||
Where("expired_unix < ? AND status = ?", timeutil.TimeStamp(time.Now().Unix()), ArtifactStatusUploadConfirmed).Find(&arts) | |||
} | |||
// ListPendingDeleteArtifacts returns all artifacts in pending-delete status. | |||
// limit is the max number of artifacts to return. | |||
func ListPendingDeleteArtifacts(ctx context.Context, limit int) ([]*ActionArtifact, error) { | |||
arts := make([]*ActionArtifact, 0, limit) | |||
return arts, db.GetEngine(ctx). | |||
Where("status = ?", ArtifactStatusPendingDeletion).Limit(limit).Find(&arts) | |||
} | |||
// SetArtifactExpired sets an artifact to expired | |||
func SetArtifactExpired(ctx context.Context, artifactID int64) error { | |||
_, err := db.GetEngine(ctx).Where("id=? AND status = ?", artifactID, ArtifactStatusUploadConfirmed).Cols("status").Update(&ActionArtifact{Status: int64(ArtifactStatusExpired)}) | |||
return err | |||
} | |||
// SetArtifactNeedDelete sets an artifact to need-delete, cron job will delete it | |||
func SetArtifactNeedDelete(ctx context.Context, runID int64, name string) error { | |||
_, err := db.GetEngine(ctx).Where("run_id=? AND artifact_name=? AND status = ?", runID, name, ArtifactStatusUploadConfirmed).Cols("status").Update(&ActionArtifact{Status: int64(ArtifactStatusPendingDeletion)}) | |||
return err | |||
} | |||
// SetArtifactDeleted sets an artifact to deleted | |||
func SetArtifactDeleted(ctx context.Context, artifactID int64) error { | |||
_, err := db.GetEngine(ctx).ID(artifactID).Cols("status").Update(&ActionArtifact{Status: int64(ArtifactStatusDeleted)}) | |||
return err | |||
} |
@@ -46,10 +46,13 @@ type ActionRun struct { | |||
TriggerEvent string // the trigger event defined in the `on` configuration of the triggered workflow | |||
Status Status `xorm:"index"` | |||
Version int `xorm:"version default 0"` // Status could be updated concomitantly, so an optimistic lock is needed | |||
Started timeutil.TimeStamp | |||
Stopped timeutil.TimeStamp | |||
Created timeutil.TimeStamp `xorm:"created"` | |||
Updated timeutil.TimeStamp `xorm:"updated"` | |||
// Started and Stopped is used for recording last run time, if rerun happened, they will be reset to 0 | |||
Started timeutil.TimeStamp | |||
Stopped timeutil.TimeStamp | |||
// PreviousDuration is used for recording previous duration | |||
PreviousDuration time.Duration | |||
Created timeutil.TimeStamp `xorm:"created"` | |||
Updated timeutil.TimeStamp `xorm:"updated"` | |||
} | |||
func init() { | |||
@@ -118,7 +121,7 @@ func (run *ActionRun) LoadAttributes(ctx context.Context) error { | |||
} | |||
func (run *ActionRun) Duration() time.Duration { | |||
return calculateDuration(run.Started, run.Stopped, run.Status) | |||
return calculateDuration(run.Started, run.Stopped, run.Status) + run.PreviousDuration | |||
} | |||
func (run *ActionRun) GetPushEventPayload() (*api.PushPayload, error) { | |||
@@ -168,13 +171,14 @@ func updateRepoRunsNumbers(ctx context.Context, repo *repo_model.Repository) err | |||
} | |||
// CancelRunningJobs cancels all running and waiting jobs associated with a specific workflow. | |||
func CancelRunningJobs(ctx context.Context, repoID int64, ref, workflowID string) error { | |||
func CancelRunningJobs(ctx context.Context, repoID int64, ref, workflowID string, event webhook_module.HookEventType) error { | |||
// Find all runs in the specified repository, reference, and workflow with statuses 'Running' or 'Waiting'. | |||
runs, total, err := db.FindAndCount[ActionRun](ctx, FindRunOptions{ | |||
RepoID: repoID, | |||
Ref: ref, | |||
WorkflowID: workflowID, | |||
Status: []Status{StatusRunning, StatusWaiting}, | |||
RepoID: repoID, | |||
Ref: ref, | |||
WorkflowID: workflowID, | |||
TriggerEvent: event, | |||
Status: []Status{StatusRunning, StatusWaiting}, | |||
}) | |||
if err != nil { | |||
return err | |||
@@ -335,6 +339,23 @@ func GetRunByIndex(ctx context.Context, repoID, index int64) (*ActionRun, error) | |||
return run, nil | |||
} | |||
func GetWorkflowLatestRun(ctx context.Context, repoID int64, workflowFile, branch, event string) (*ActionRun, error) { | |||
var run ActionRun | |||
q := db.GetEngine(ctx).Where("repo_id=?", repoID). | |||
And("ref = ?", branch). | |||
And("workflow_id = ?", workflowFile) | |||
if event != "" { | |||
q.And("event = ?", event) | |||
} | |||
has, err := q.Desc("id").Get(&run) | |||
if err != nil { | |||
return nil, err | |||
} else if !has { | |||
return nil, util.NewNotExistErrorf("run with repo_id %d, ref %s, workflow_id %s", repoID, branch, workflowFile) | |||
} | |||
return &run, nil | |||
} | |||
// UpdateRun updates a run. | |||
// It requires the inputted run has Version set. | |||
// It will return error if the version is not matched (it means the run has been changed after loaded). |
@@ -10,6 +10,7 @@ import ( | |||
repo_model "code.gitea.io/gitea/models/repo" | |||
user_model "code.gitea.io/gitea/models/user" | |||
"code.gitea.io/gitea/modules/container" | |||
webhook_module "code.gitea.io/gitea/modules/webhook" | |||
"xorm.io/builder" | |||
) | |||
@@ -71,6 +72,7 @@ type FindRunOptions struct { | |||
WorkflowID string | |||
Ref string // the commit/tag/… that caused this workflow | |||
TriggerUserID int64 | |||
TriggerEvent webhook_module.HookEventType | |||
Approved bool // not util.OptionalBool, it works only when it's true | |||
Status []Status | |||
} | |||
@@ -98,6 +100,9 @@ func (opts FindRunOptions) ToConds() builder.Cond { | |||
if opts.Ref != "" { | |||
cond = cond.And(builder.Eq{"ref": opts.Ref}) | |||
} | |||
if opts.TriggerEvent != "" { | |||
cond = cond.And(builder.Eq{"trigger_event": opts.TriggerEvent}) | |||
} | |||
return cond | |||
} | |||
@@ -13,6 +13,7 @@ import ( | |||
repo_model "code.gitea.io/gitea/models/repo" | |||
"code.gitea.io/gitea/models/shared/types" | |||
user_model "code.gitea.io/gitea/models/user" | |||
"code.gitea.io/gitea/modules/optional" | |||
"code.gitea.io/gitea/modules/timeutil" | |||
"code.gitea.io/gitea/modules/translation" | |||
"code.gitea.io/gitea/modules/util" | |||
@@ -97,7 +98,7 @@ func (r *ActionRunner) StatusName() string { | |||
} | |||
func (r *ActionRunner) StatusLocaleName(lang translation.Locale) string { | |||
return lang.Tr("actions.runners.status." + r.StatusName()) | |||
return lang.TrString("actions.runners.status." + r.StatusName()) | |||
} | |||
func (r *ActionRunner) IsOnline() bool { | |||
@@ -159,7 +160,7 @@ type FindRunnerOptions struct { | |||
OwnerID int64 | |||
Sort string | |||
Filter string | |||
IsOnline util.OptionalBool | |||
IsOnline optional.Option[bool] | |||
WithAvailable bool // not only runners belong to, but also runners can be used | |||
} | |||
@@ -186,10 +187,12 @@ func (opts FindRunnerOptions) ToConds() builder.Cond { | |||
cond = cond.And(builder.Like{"name", opts.Filter}) | |||
} | |||
if opts.IsOnline.IsTrue() { | |||
cond = cond.And(builder.Gt{"last_online": time.Now().Add(-RunnerOfflineTime).Unix()}) | |||
} else if opts.IsOnline.IsFalse() { | |||
cond = cond.And(builder.Lte{"last_online": time.Now().Add(-RunnerOfflineTime).Unix()}) | |||
if opts.IsOnline.Has() { | |||
if opts.IsOnline.Value() { | |||
cond = cond.And(builder.Gt{"last_online": time.Now().Add(-RunnerOfflineTime).Unix()}) | |||
} else { | |||
cond = cond.And(builder.Lte{"last_online": time.Now().Add(-RunnerOfflineTime).Unix()}) | |||
} | |||
} | |||
return cond | |||
} |
@@ -5,6 +5,7 @@ package actions | |||
import ( | |||
"context" | |||
"fmt" | |||
"time" | |||
"code.gitea.io/gitea/models/db" | |||
@@ -118,3 +119,22 @@ func DeleteScheduleTaskByRepo(ctx context.Context, id int64) error { | |||
return committer.Commit() | |||
} | |||
func CleanRepoScheduleTasks(ctx context.Context, repo *repo_model.Repository) error { | |||
// If actions disabled when there is schedule task, this will remove the outdated schedule tasks | |||
// There is no other place we can do this because the app.ini will be changed manually | |||
if err := DeleteScheduleTaskByRepo(ctx, repo.ID); err != nil { | |||
return fmt.Errorf("DeleteCronTaskByRepo: %v", err) | |||
} | |||
// cancel running cron jobs of this repository and delete old schedules | |||
if err := CancelRunningJobs( | |||
ctx, | |||
repo.ID, | |||
repo.DefaultBranch, | |||
"", | |||
webhook_module.HookEventSchedule, | |||
); err != nil { | |||
return fmt.Errorf("CancelRunningJobs: %v", err) | |||
} | |||
return nil | |||
} |
@@ -41,7 +41,7 @@ func (s Status) String() string { | |||
// LocaleString returns the locale string name of the Status | |||
func (s Status) LocaleString(lang translation.Locale) string { | |||
return lang.Tr("actions.status." + s.String()) | |||
return lang.TrString("actions.status." + s.String()) | |||
} | |||
// IsDone returns whether the Status is final |
@@ -10,6 +10,7 @@ import ( | |||
"strings" | |||
"code.gitea.io/gitea/models/db" | |||
"code.gitea.io/gitea/modules/log" | |||
"code.gitea.io/gitea/modules/timeutil" | |||
"code.gitea.io/gitea/modules/util" | |||
@@ -82,3 +83,35 @@ func UpdateVariable(ctx context.Context, variable *ActionVariable) (bool, error) | |||
}) | |||
return count != 0, err | |||
} | |||
func GetVariablesOfRun(ctx context.Context, run *ActionRun) (map[string]string, error) { | |||
variables := map[string]string{} | |||
// Global | |||
globalVariables, err := db.Find[ActionVariable](ctx, FindVariablesOpts{}) | |||
if err != nil { | |||
log.Error("find global variables: %v", err) | |||
return nil, err | |||
} | |||
// Org / User level | |||
ownerVariables, err := db.Find[ActionVariable](ctx, FindVariablesOpts{OwnerID: run.Repo.OwnerID}) | |||
if err != nil { | |||
log.Error("find variables of org: %d, error: %v", run.Repo.OwnerID, err) | |||
return nil, err | |||
} | |||
// Repo level | |||
repoVariables, err := db.Find[ActionVariable](ctx, FindVariablesOpts{RepoID: run.RepoID}) | |||
if err != nil { | |||
log.Error("find variables of repo: %d, error: %v", run.RepoID, err) | |||
return nil, err | |||
} | |||
// Level precedence: Repo > Org / User > Global | |||
for _, v := range append(globalVariables, append(ownerVariables, repoVariables...)...) { | |||
variables[v.Name] = v.Data | |||
} | |||
return variables, nil | |||
} |
@@ -148,6 +148,7 @@ type Action struct { | |||
Repo *repo_model.Repository `xorm:"-"` | |||
CommentID int64 `xorm:"INDEX"` | |||
Comment *issues_model.Comment `xorm:"-"` | |||
Issue *issues_model.Issue `xorm:"-"` // get the issue id from content | |||
IsDeleted bool `xorm:"NOT NULL DEFAULT false"` | |||
RefName string | |||
IsPrivate bool `xorm:"NOT NULL DEFAULT false"` | |||
@@ -225,8 +226,8 @@ func (a *Action) ShortActUserName(ctx context.Context) string { | |||
return base.EllipsisString(a.GetActUserName(ctx), 20) | |||
} | |||
// GetDisplayName gets the action's display name based on DEFAULT_SHOW_FULL_NAME, or falls back to the username if it is blank. | |||
func (a *Action) GetDisplayName(ctx context.Context) string { | |||
// GetActDisplayName gets the action's display name based on DEFAULT_SHOW_FULL_NAME, or falls back to the username if it is blank. | |||
func (a *Action) GetActDisplayName(ctx context.Context) string { | |||
if setting.UI.DefaultShowFullName { | |||
trimmedFullName := strings.TrimSpace(a.GetActFullName(ctx)) | |||
if len(trimmedFullName) > 0 { | |||
@@ -236,8 +237,8 @@ func (a *Action) GetDisplayName(ctx context.Context) string { | |||
return a.ShortActUserName(ctx) | |||
} | |||
// GetDisplayNameTitle gets the action's display name used for the title (tooltip) based on DEFAULT_SHOW_FULL_NAME | |||
func (a *Action) GetDisplayNameTitle(ctx context.Context) string { | |||
// GetActDisplayNameTitle gets the action's display name used for the title (tooltip) based on DEFAULT_SHOW_FULL_NAME | |||
func (a *Action) GetActDisplayNameTitle(ctx context.Context) string { | |||
if setting.UI.DefaultShowFullName { | |||
return a.ShortActUserName(ctx) | |||
} | |||
@@ -290,11 +291,6 @@ func (a *Action) GetRepoAbsoluteLink(ctx context.Context) string { | |||
return setting.AppURL + url.PathEscape(a.GetRepoUserName(ctx)) + "/" + url.PathEscape(a.GetRepoName(ctx)) | |||
} | |||
// GetCommentHTMLURL returns link to action comment. | |||
func (a *Action) GetCommentHTMLURL(ctx context.Context) string { | |||
return a.getCommentHTMLURL(ctx) | |||
} | |||
func (a *Action) loadComment(ctx context.Context) (err error) { | |||
if a.CommentID == 0 || a.Comment != nil { | |||
return nil | |||
@@ -303,7 +299,8 @@ func (a *Action) loadComment(ctx context.Context) (err error) { | |||
return err | |||
} | |||
func (a *Action) getCommentHTMLURL(ctx context.Context) string { | |||
// GetCommentHTMLURL returns link to action comment. | |||
func (a *Action) GetCommentHTMLURL(ctx context.Context) string { | |||
if a == nil { | |||
return "#" | |||
} | |||
@@ -311,34 +308,19 @@ func (a *Action) getCommentHTMLURL(ctx context.Context) string { | |||
if a.Comment != nil { | |||
return a.Comment.HTMLURL(ctx) | |||
} | |||
if len(a.GetIssueInfos()) == 0 { | |||
return "#" | |||
} | |||
// Return link to issue | |||
issueIDString := a.GetIssueInfos()[0] | |||
issueID, err := strconv.ParseInt(issueIDString, 10, 64) | |||
if err != nil { | |||
return "#" | |||
} | |||
issue, err := issues_model.GetIssueByID(ctx, issueID) | |||
if err != nil { | |||
if err := a.LoadIssue(ctx); err != nil || a.Issue == nil { | |||
return "#" | |||
} | |||
if err = issue.LoadRepo(ctx); err != nil { | |||
if err := a.Issue.LoadRepo(ctx); err != nil { | |||
return "#" | |||
} | |||
return issue.HTMLURL() | |||
return a.Issue.HTMLURL() | |||
} | |||
// GetCommentLink returns link to action comment. | |||
func (a *Action) GetCommentLink(ctx context.Context) string { | |||
return a.getCommentLink(ctx) | |||
} | |||
func (a *Action) getCommentLink(ctx context.Context) string { | |||
if a == nil { | |||
return "#" | |||
} | |||
@@ -346,26 +328,15 @@ func (a *Action) getCommentLink(ctx context.Context) string { | |||
if a.Comment != nil { | |||
return a.Comment.Link(ctx) | |||
} | |||
if len(a.GetIssueInfos()) == 0 { | |||
return "#" | |||
} | |||
// Return link to issue | |||
issueIDString := a.GetIssueInfos()[0] | |||
issueID, err := strconv.ParseInt(issueIDString, 10, 64) | |||
if err != nil { | |||
return "#" | |||
} | |||
issue, err := issues_model.GetIssueByID(ctx, issueID) | |||
if err != nil { | |||
if err := a.LoadIssue(ctx); err != nil || a.Issue == nil { | |||
return "#" | |||
} | |||
if err = issue.LoadRepo(ctx); err != nil { | |||
if err := a.Issue.LoadRepo(ctx); err != nil { | |||
return "#" | |||
} | |||
return issue.Link() | |||
return a.Issue.Link() | |||
} | |||
// GetBranch returns the action's repository branch. | |||
@@ -393,33 +364,66 @@ func (a *Action) GetCreate() time.Time { | |||
return a.CreatedUnix.AsTime() | |||
} | |||
// GetIssueInfos returns a list of issues associated with | |||
// the action. | |||
func (a *Action) IsIssueEvent() bool { | |||
return a.OpType.InActions("comment_issue", "approve_pull_request", "reject_pull_request", "comment_pull", "merge_pull_request") | |||
} | |||
// GetIssueInfos returns a list of associated information with the action. | |||
func (a *Action) GetIssueInfos() []string { | |||
return strings.SplitN(a.Content, "|", 3) | |||
// make sure it always returns 3 elements, because there are some access to the a[1] and a[2] without checking the length | |||
ret := strings.SplitN(a.Content, "|", 3) | |||
for len(ret) < 3 { | |||
ret = append(ret, "") | |||
} | |||
return ret | |||
} | |||
func (a *Action) getIssueIndex() int64 { | |||
infos := a.GetIssueInfos() | |||
if len(infos) == 0 { | |||
return 0 | |||
} | |||
index, _ := strconv.ParseInt(infos[0], 10, 64) | |||
return index | |||
} | |||
func (a *Action) LoadIssue(ctx context.Context) error { | |||
if a.Issue != nil { | |||
return nil | |||
} | |||
if index := a.getIssueIndex(); index > 0 { | |||
issue, err := issues_model.GetIssueByIndex(ctx, a.RepoID, index) | |||
if err != nil { | |||
return err | |||
} | |||
a.Issue = issue | |||
a.Issue.Repo = a.Repo | |||
} | |||
return nil | |||
} | |||
// GetIssueTitle returns the title of first issue associated with the action. | |||
func (a *Action) GetIssueTitle(ctx context.Context) string { | |||
index, _ := strconv.ParseInt(a.GetIssueInfos()[0], 10, 64) | |||
issue, err := issues_model.GetIssueByIndex(ctx, a.RepoID, index) | |||
if err != nil { | |||
log.Error("GetIssueByIndex: %v", err) | |||
return "500 when get issue" | |||
if err := a.LoadIssue(ctx); err != nil { | |||
log.Error("LoadIssue: %v", err) | |||
return "<500 when get issue>" | |||
} | |||
if a.Issue == nil { | |||
return "<Issue not found>" | |||
} | |||
return issue.Title | |||
return a.Issue.Title | |||
} | |||
// GetIssueContent returns the content of first issue associated with | |||
// this action. | |||
// GetIssueContent returns the content of first issue associated with this action. | |||
func (a *Action) GetIssueContent(ctx context.Context) string { | |||
index, _ := strconv.ParseInt(a.GetIssueInfos()[0], 10, 64) | |||
issue, err := issues_model.GetIssueByIndex(ctx, a.RepoID, index) | |||
if err != nil { | |||
log.Error("GetIssueByIndex: %v", err) | |||
return "500 when get issue" | |||
if err := a.LoadIssue(ctx); err != nil { | |||
log.Error("LoadIssue: %v", err) | |||
return "<500 when get issue>" | |||
} | |||
if a.Issue == nil { | |||
return "<Content not found>" | |||
} | |||
return issue.Content | |||
return a.Issue.Content | |||
} | |||
// GetFeedsOptions options for retrieving feeds | |||
@@ -459,7 +463,7 @@ func GetFeeds(ctx context.Context, opts GetFeedsOptions) (ActionList, int64, err | |||
return nil, 0, fmt.Errorf("FindAndCount: %w", err) | |||
} | |||
if err := ActionList(actions).loadAttributes(ctx); err != nil { | |||
if err := ActionList(actions).LoadAttributes(ctx); err != nil { | |||
return nil, 0, fmt.Errorf("LoadAttributes: %w", err) | |||
} | |||
@@ -6,11 +6,16 @@ package activities | |||
import ( | |||
"context" | |||
"fmt" | |||
"strconv" | |||
"code.gitea.io/gitea/models/db" | |||
issues_model "code.gitea.io/gitea/models/issues" | |||
repo_model "code.gitea.io/gitea/models/repo" | |||
user_model "code.gitea.io/gitea/models/user" | |||
"code.gitea.io/gitea/modules/container" | |||
"code.gitea.io/gitea/modules/util" | |||
"xorm.io/builder" | |||
) | |||
// ActionList defines a list of actions | |||
@@ -24,7 +29,7 @@ func (actions ActionList) getUserIDs() []int64 { | |||
return userIDs.Values() | |||
} | |||
func (actions ActionList) loadUsers(ctx context.Context) (map[int64]*user_model.User, error) { | |||
func (actions ActionList) LoadActUsers(ctx context.Context) (map[int64]*user_model.User, error) { | |||
if len(actions) == 0 { | |||
return nil, nil | |||
} | |||
@@ -52,7 +57,7 @@ func (actions ActionList) getRepoIDs() []int64 { | |||
return repoIDs.Values() | |||
} | |||
func (actions ActionList) loadRepositories(ctx context.Context) error { | |||
func (actions ActionList) LoadRepositories(ctx context.Context) error { | |||
if len(actions) == 0 { | |||
return nil | |||
} | |||
@@ -63,11 +68,11 @@ func (actions ActionList) loadRepositories(ctx context.Context) error { | |||
if err != nil { | |||
return fmt.Errorf("find repository: %w", err) | |||
} | |||
for _, action := range actions { | |||
action.Repo = repoMaps[action.RepoID] | |||
} | |||
return nil | |||
repos := repo_model.RepositoryList(util.ValuesOfMap(repoMaps)) | |||
return repos.LoadUnits(ctx) | |||
} | |||
func (actions ActionList) loadRepoOwner(ctx context.Context, userMap map[int64]*user_model.User) (err error) { | |||
@@ -75,37 +80,124 @@ func (actions ActionList) loadRepoOwner(ctx context.Context, userMap map[int64]* | |||
userMap = make(map[int64]*user_model.User) | |||
} | |||
userSet := make(container.Set[int64], len(actions)) | |||
for _, action := range actions { | |||
if action.Repo == nil { | |||
continue | |||
} | |||
repoOwner, ok := userMap[action.Repo.OwnerID] | |||
if !ok { | |||
repoOwner, err = user_model.GetUserByID(ctx, action.Repo.OwnerID) | |||
if err != nil { | |||
if user_model.IsErrUserNotExist(err) { | |||
continue | |||
} | |||
return err | |||
} | |||
userMap[repoOwner.ID] = repoOwner | |||
if _, ok := userMap[action.Repo.OwnerID]; !ok { | |||
userSet.Add(action.Repo.OwnerID) | |||
} | |||
} | |||
if err := db.GetEngine(ctx). | |||
In("id", userSet.Values()). | |||
Find(&userMap); err != nil { | |||
return fmt.Errorf("find user: %w", err) | |||
} | |||
for _, action := range actions { | |||
if action.Repo != nil { | |||
action.Repo.Owner = userMap[action.Repo.OwnerID] | |||
} | |||
action.Repo.Owner = repoOwner | |||
} | |||
return nil | |||
} | |||
// loadAttributes loads all attributes | |||
func (actions ActionList) loadAttributes(ctx context.Context) error { | |||
userMap, err := actions.loadUsers(ctx) | |||
// LoadAttributes loads all attributes | |||
func (actions ActionList) LoadAttributes(ctx context.Context) error { | |||
// the load sequence cannot be changed because of the dependencies | |||
userMap, err := actions.LoadActUsers(ctx) | |||
if err != nil { | |||
return err | |||
} | |||
if err := actions.loadRepositories(ctx); err != nil { | |||
if err := actions.LoadRepositories(ctx); err != nil { | |||
return err | |||
} | |||
if err := actions.loadRepoOwner(ctx, userMap); err != nil { | |||
return err | |||
} | |||
if err := actions.LoadIssues(ctx); err != nil { | |||
return err | |||
} | |||
return actions.LoadComments(ctx) | |||
} | |||
func (actions ActionList) LoadComments(ctx context.Context) error { | |||
if len(actions) == 0 { | |||
return nil | |||
} | |||
commentIDs := make([]int64, 0, len(actions)) | |||
for _, action := range actions { | |||
if action.CommentID > 0 { | |||
commentIDs = append(commentIDs, action.CommentID) | |||
} | |||
} | |||
return actions.loadRepoOwner(ctx, userMap) | |||
commentsMap := make(map[int64]*issues_model.Comment, len(commentIDs)) | |||
if err := db.GetEngine(ctx).In("id", commentIDs).Find(&commentsMap); err != nil { | |||
return fmt.Errorf("find comment: %w", err) | |||
} | |||
for _, action := range actions { | |||
if action.CommentID > 0 { | |||
action.Comment = commentsMap[action.CommentID] | |||
if action.Comment != nil { | |||
action.Comment.Issue = action.Issue | |||
} | |||
} | |||
} | |||
return nil | |||
} | |||
func (actions ActionList) LoadIssues(ctx context.Context) error { | |||
if len(actions) == 0 { | |||
return nil | |||
} | |||
conditions := builder.NewCond() | |||
issueNum := 0 | |||
for _, action := range actions { | |||
if action.IsIssueEvent() { | |||
infos := action.GetIssueInfos() | |||
if len(infos) == 0 { | |||
continue | |||
} | |||
index, _ := strconv.ParseInt(infos[0], 10, 64) | |||
if index > 0 { | |||
conditions = conditions.Or(builder.Eq{ | |||
"repo_id": action.RepoID, | |||
"`index`": index, | |||
}) | |||
issueNum++ | |||
} | |||
} | |||
} | |||
if !conditions.IsValid() { | |||
return nil | |||
} | |||
issuesMap := make(map[string]*issues_model.Issue, issueNum) | |||
issues := make([]*issues_model.Issue, 0, issueNum) | |||
if err := db.GetEngine(ctx).Where(conditions).Find(&issues); err != nil { | |||
return fmt.Errorf("find issue: %w", err) | |||
} | |||
for _, issue := range issues { | |||
issuesMap[fmt.Sprintf("%d-%d", issue.RepoID, issue.Index)] = issue | |||
} | |||
for _, action := range actions { | |||
if !action.IsIssueEvent() { | |||
continue | |||
} | |||
if index := action.getIssueIndex(); index > 0 { | |||
if issue, ok := issuesMap[fmt.Sprintf("%d-%d", action.RepoID, index)]; ok { | |||
action.Issue = issue | |||
action.Issue.Repo = action.Repo | |||
} | |||
} | |||
} | |||
return nil | |||
} |
@@ -14,6 +14,7 @@ import ( | |||
repo_model "code.gitea.io/gitea/models/repo" | |||
user_model "code.gitea.io/gitea/models/user" | |||
"code.gitea.io/gitea/modules/git" | |||
"code.gitea.io/gitea/modules/gitrepo" | |||
"xorm.io/xorm" | |||
) | |||
@@ -65,7 +66,7 @@ func GetActivityStats(ctx context.Context, repo *repo_model.Repository, timeFrom | |||
return nil, fmt.Errorf("FillUnresolvedIssues: %w", err) | |||
} | |||
if code { | |||
gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, repo.RepoPath()) | |||
gitRepo, closer, err := gitrepo.RepositoryFromContextOrOpen(ctx, repo) | |||
if err != nil { | |||
return nil, fmt.Errorf("OpenRepository: %w", err) | |||
} | |||
@@ -82,7 +83,7 @@ func GetActivityStats(ctx context.Context, repo *repo_model.Repository, timeFrom | |||
// GetActivityStatsTopAuthors returns top author stats for git commits for all branches | |||
func GetActivityStatsTopAuthors(ctx context.Context, repo *repo_model.Repository, timeFrom time.Time, count int) ([]*ActivityAuthorData, error) { | |||
gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, repo.RepoPath()) | |||
gitRepo, closer, err := gitrepo.RepositoryFromContextOrOpen(ctx, repo) | |||
if err != nil { | |||
return nil, fmt.Errorf("OpenRepository: %w", err) | |||
} |
@@ -9,6 +9,7 @@ import ( | |||
asymkey_model "code.gitea.io/gitea/models/asymkey" | |||
"code.gitea.io/gitea/models/auth" | |||
"code.gitea.io/gitea/models/db" | |||
git_model "code.gitea.io/gitea/models/git" | |||
issues_model "code.gitea.io/gitea/models/issues" | |||
"code.gitea.io/gitea/models/organization" | |||
access_model "code.gitea.io/gitea/models/perm/access" | |||
@@ -29,7 +30,8 @@ type Statistic struct { | |||
Mirror, Release, AuthSource, Webhook, | |||
Milestone, Label, HookTask, | |||
Team, UpdateTask, Project, | |||
ProjectBoard, Attachment int64 | |||
ProjectBoard, Attachment, | |||
Branches, Tags, CommitStatus int64 | |||
IssueByLabel []IssueByLabelCount | |||
IssueByRepository []IssueByRepositoryCount | |||
} | |||
@@ -58,6 +60,9 @@ func GetStatistic(ctx context.Context) (stats Statistic) { | |||
stats.Counter.Watch, _ = e.Count(new(repo_model.Watch)) | |||
stats.Counter.Star, _ = e.Count(new(repo_model.Star)) | |||
stats.Counter.Access, _ = e.Count(new(access_model.Access)) | |||
stats.Counter.Branches, _ = e.Count(new(git_model.Branch)) | |||
stats.Counter.Tags, _ = e.Where("is_draft=?", false).Count(new(repo_model.Release)) | |||
stats.Counter.CommitStatus, _ = e.Count(new(git_model.CommitStatus)) | |||
type IssueCount struct { | |||
Count int64 |
@@ -11,21 +11,13 @@ import ( | |||
"code.gitea.io/gitea/models/db" | |||
user_model "code.gitea.io/gitea/models/user" | |||
"code.gitea.io/gitea/modules/log" | |||
"code.gitea.io/gitea/modules/timeutil" | |||
"github.com/keybase/go-crypto/openpgp" | |||
"github.com/keybase/go-crypto/openpgp/packet" | |||
"xorm.io/xorm" | |||
"xorm.io/builder" | |||
) | |||
// __________________ ________ ____ __. | |||
// / _____/\______ \/ _____/ | |/ _|____ ___.__. | |||
// / \ ___ | ___/ \ ___ | <_/ __ < | | | |||
// \ \_\ \| | \ \_\ \ | | \ ___/\___ | | |||
// \______ /|____| \______ / |____|__ \___ > ____| | |||
// \/ \/ \/ \/\/ | |||
// GPGKey represents a GPG key. | |||
type GPGKey struct { | |||
ID int64 `xorm:"pk autoincr"` | |||
@@ -54,12 +46,11 @@ func (key *GPGKey) BeforeInsert() { | |||
key.AddedUnix = timeutil.TimeStampNow() | |||
} | |||
// AfterLoad is invoked from XORM after setting the values of all fields of this object. | |||
func (key *GPGKey) AfterLoad(session *xorm.Session) { | |||
err := session.Where("primary_key_id=?", key.KeyID).Find(&key.SubsKey) | |||
if err != nil { | |||
log.Error("Find Sub GPGkeys[%s]: %v", key.KeyID, err) | |||
func (key *GPGKey) LoadSubKeys(ctx context.Context) error { | |||
if err := db.GetEngine(ctx).Where("primary_key_id=?", key.KeyID).Find(&key.SubsKey); err != nil { | |||
return fmt.Errorf("find Sub GPGkeys[%s]: %v", key.KeyID, err) | |||
} | |||
return nil | |||
} | |||
// PaddedKeyID show KeyID padded to 16 characters | |||
@@ -76,20 +67,26 @@ func PaddedKeyID(keyID string) string { | |||
return zeros[0:16-len(keyID)] + keyID | |||
} | |||
// ListGPGKeys returns a list of public keys belongs to given user. | |||
func ListGPGKeys(ctx context.Context, uid int64, listOptions db.ListOptions) ([]*GPGKey, error) { | |||
sess := db.GetEngine(ctx).Table(&GPGKey{}).Where("owner_id=? AND primary_key_id=''", uid) | |||
if listOptions.Page != 0 { | |||
sess = db.SetSessionPagination(sess, &listOptions) | |||
} | |||
keys := make([]*GPGKey, 0, 2) | |||
return keys, sess.Find(&keys) | |||
type FindGPGKeyOptions struct { | |||
db.ListOptions | |||
OwnerID int64 | |||
KeyID string | |||
IncludeSubKeys bool | |||
} | |||
// CountUserGPGKeys return number of gpg keys a user own | |||
func CountUserGPGKeys(ctx context.Context, userID int64) (int64, error) { | |||
return db.GetEngine(ctx).Where("owner_id=? AND primary_key_id=''", userID).Count(&GPGKey{}) | |||
func (opts FindGPGKeyOptions) ToConds() builder.Cond { | |||
cond := builder.NewCond() | |||
if !opts.IncludeSubKeys { | |||
cond = cond.And(builder.Eq{"primary_key_id": ""}) | |||
} | |||
if opts.OwnerID > 0 { | |||
cond = cond.And(builder.Eq{"owner_id": opts.OwnerID}) | |||
} | |||
if opts.KeyID != "" { | |||
cond = cond.And(builder.Eq{"key_id": opts.KeyID}) | |||
} | |||
return cond | |||
} | |||
func GetGPGKeyForUserByID(ctx context.Context, ownerID, keyID int64) (*GPGKey, error) { | |||
@@ -103,12 +100,6 @@ func GetGPGKeyForUserByID(ctx context.Context, ownerID, keyID int64) (*GPGKey, e | |||
return key, nil | |||
} | |||
// GetGPGKeysByKeyID returns public key by given ID. | |||
func GetGPGKeysByKeyID(ctx context.Context, keyID string) ([]*GPGKey, error) { | |||
keys := make([]*GPGKey, 0, 1) | |||
return keys, db.GetEngine(ctx).Where("key_id=?", keyID).Find(&keys) | |||
} | |||
// GPGKeyToEntity retrieve the imported key and the traducted entity | |||
func GPGKeyToEntity(ctx context.Context, k *GPGKey) (*openpgp.Entity, error) { | |||
impKey, err := GetGPGImportByKeyID(ctx, k.KeyID) |
@@ -166,7 +166,9 @@ func ParseCommitWithSignature(ctx context.Context, c *git.Commit) *CommitVerific | |||
// Now try to associate the signature with the committer, if present | |||
if committer.ID != 0 { | |||
keys, err := ListGPGKeys(ctx, committer.ID, db.ListOptions{}) | |||
keys, err := db.Find[GPGKey](ctx, FindGPGKeyOptions{ | |||
OwnerID: committer.ID, | |||
}) | |||
if err != nil { // Skipping failed to get gpg keys of user | |||
log.Error("ListGPGKeys: %v", err) | |||
return &CommitVerification{ | |||
@@ -176,6 +178,15 @@ func ParseCommitWithSignature(ctx context.Context, c *git.Commit) *CommitVerific | |||
} | |||
} | |||
if err := GPGKeyList(keys).LoadSubKeys(ctx); err != nil { | |||
log.Error("LoadSubKeys: %v", err) | |||
return &CommitVerification{ | |||
CommittingUser: committer, | |||
Verified: false, | |||
Reason: "gpg.error.failed_retrieval_gpg_keys", | |||
} | |||
} | |||
committerEmailAddresses, _ := user_model.GetEmailAddresses(ctx, committer.ID) | |||
activated := false | |||
for _, e := range committerEmailAddresses { | |||
@@ -392,7 +403,10 @@ func hashAndVerifyForKeyID(ctx context.Context, sig *packet.Signature, payload s | |||
if keyID == "" { | |||
return nil | |||
} | |||
keys, err := GetGPGKeysByKeyID(ctx, keyID) | |||
keys, err := db.Find[GPGKey](ctx, FindGPGKeyOptions{ | |||
KeyID: keyID, | |||
IncludeSubKeys: true, | |||
}) | |||
if err != nil { | |||
log.Error("GetGPGKeysByKeyID: %v", err) | |||
return &CommitVerification{ | |||
@@ -407,7 +421,10 @@ func hashAndVerifyForKeyID(ctx context.Context, sig *packet.Signature, payload s | |||
for _, key := range keys { | |||
var primaryKeys []*GPGKey | |||
if key.PrimaryKeyID != "" { | |||
primaryKeys, err = GetGPGKeysByKeyID(ctx, key.PrimaryKeyID) | |||
primaryKeys, err = db.Find[GPGKey](ctx, FindGPGKeyOptions{ | |||
KeyID: key.PrimaryKeyID, | |||
IncludeSubKeys: true, | |||
}) | |||
if err != nil { | |||
log.Error("GetGPGKeysByKeyID: %v", err) | |||
return &CommitVerification{ |
@@ -0,0 +1,38 @@ | |||
// Copyright 2023 The Gitea Authors. All rights reserved. | |||
// SPDX-License-Identifier: MIT | |||
package asymkey | |||
import ( | |||
"context" | |||
"code.gitea.io/gitea/models/db" | |||
) | |||
type GPGKeyList []*GPGKey | |||
func (keys GPGKeyList) keyIDs() []string { | |||
ids := make([]string, len(keys)) | |||
for i, key := range keys { | |||
ids[i] = key.KeyID | |||
} | |||
return ids | |||
} | |||
func (keys GPGKeyList) LoadSubKeys(ctx context.Context) error { | |||
subKeys := make([]*GPGKey, 0, len(keys)) | |||
if err := db.GetEngine(ctx).In("primary_key_id", keys.keyIDs()).Find(&subKeys); err != nil { | |||
return err | |||
} | |||
subKeysMap := make(map[string][]*GPGKey, len(subKeys)) | |||
for _, key := range subKeys { | |||
subKeysMap[key.PrimaryKeyID] = append(subKeysMap[key.PrimaryKeyID], key) | |||
} | |||
for _, key := range keys { | |||
if subKeys, ok := subKeysMap[key.KeyID]; ok { | |||
key.SubsKey = subKeys | |||
} | |||
} | |||
return nil | |||
} |
@@ -63,7 +63,6 @@ func VerifyGPGKey(ctx context.Context, ownerID int64, keyID, token, signature st | |||
} | |||
if signer == nil { | |||
signer, err = hashAndVerifyWithSubKeys(sig, token+"\n", key) | |||
if err != nil { | |||
return "", ErrGPGInvalidTokenSignature{ | |||
ID: key.KeyID, |
@@ -197,10 +197,10 @@ func (opts FindPublicKeyOptions) ToConds() builder.Cond { | |||
cond = cond.And(builder.Eq{"fingerprint": opts.Fingerprint}) | |||
} | |||
if len(opts.KeyTypes) > 0 { | |||
cond = cond.And(builder.In("type", opts.KeyTypes)) | |||
cond = cond.And(builder.In("`type`", opts.KeyTypes)) | |||
} | |||
if opts.NotKeytype > 0 { | |||
cond = cond.And(builder.Neq{"type": opts.NotKeytype}) | |||
cond = cond.And(builder.Neq{"`type`": opts.NotKeytype}) | |||
} | |||
if opts.LoginSourceID > 0 { | |||
cond = cond.And(builder.Eq{"login_source_id": opts.LoginSourceID}) |
@@ -12,7 +12,6 @@ import ( | |||
"path/filepath" | |||
"strings" | |||
"sync" | |||
"time" | |||
"code.gitea.io/gitea/models/db" | |||
"code.gitea.io/gitea/modules/log" | |||
@@ -44,6 +43,12 @@ const ( | |||
var sshOpLocker sync.Mutex | |||
func WithSSHOpLocker(f func() error) error { | |||
sshOpLocker.Lock() | |||
defer sshOpLocker.Unlock() | |||
return f() | |||
} | |||
// AuthorizedStringForKey creates the authorized keys string appropriate for the provided key | |||
func AuthorizedStringForKey(key *PublicKey) string { | |||
sb := &strings.Builder{} | |||
@@ -114,65 +119,6 @@ func appendAuthorizedKeysToFile(keys ...*PublicKey) error { | |||
return nil | |||
} | |||
// RewriteAllPublicKeys removes any authorized key and rewrite all keys from database again. | |||
// Note: db.GetEngine(ctx).Iterate does not get latest data after insert/delete, so we have to call this function | |||
// outside any session scope independently. | |||
func RewriteAllPublicKeys(ctx context.Context) error { | |||
// Don't rewrite key if internal server | |||
if setting.SSH.StartBuiltinServer || !setting.SSH.CreateAuthorizedKeysFile { | |||
return nil | |||
} | |||
sshOpLocker.Lock() | |||
defer sshOpLocker.Unlock() | |||
if setting.SSH.RootPath != "" { | |||
// First of ensure that the RootPath is present, and if not make it with 0700 permissions | |||
// This of course doesn't guarantee that this is the right directory for authorized_keys | |||
// but at least if it's supposed to be this directory and it doesn't exist and we're the | |||
// right user it will at least be created properly. | |||
err := os.MkdirAll(setting.SSH.RootPath, 0o700) | |||
if err != nil { | |||
log.Error("Unable to MkdirAll(%s): %v", setting.SSH.RootPath, err) | |||
return err | |||
} | |||
} | |||
fPath := filepath.Join(setting.SSH.RootPath, "authorized_keys") | |||
tmpPath := fPath + ".tmp" | |||
t, err := os.OpenFile(tmpPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0o600) | |||
if err != nil { | |||
return err | |||
} | |||
defer func() { | |||
t.Close() | |||
if err := util.Remove(tmpPath); err != nil { | |||
log.Warn("Unable to remove temporary authorized keys file: %s: Error: %v", tmpPath, err) | |||
} | |||
}() | |||
if setting.SSH.AuthorizedKeysBackup { | |||
isExist, err := util.IsExist(fPath) | |||
if err != nil { | |||
log.Error("Unable to check if %s exists. Error: %v", fPath, err) | |||
return err | |||
} | |||
if isExist { | |||
bakPath := fmt.Sprintf("%s_%d.gitea_bak", fPath, time.Now().Unix()) | |||
if err = util.CopyFile(fPath, bakPath); err != nil { | |||
return err | |||
} | |||
} | |||
} | |||
if err := RegeneratePublicKeys(ctx, t); err != nil { | |||
return err | |||
} | |||
t.Close() | |||
return util.Rename(tmpPath, fPath) | |||
} | |||
// RegeneratePublicKeys regenerates the authorized_keys file | |||
func RegeneratePublicKeys(ctx context.Context, t io.StringWriter) error { | |||
if err := db.GetEngine(ctx).Where("type != ?", KeyTypePrincipal).Iterate(new(PublicKey), func(idx int, bean any) (err error) { | |||
@@ -206,6 +152,10 @@ func RegeneratePublicKeys(ctx context.Context, t io.StringWriter) error { | |||
return err | |||
} | |||
} | |||
err = scanner.Err() | |||
if err != nil { | |||
return fmt.Errorf("scan: %w", err) | |||
} | |||
f.Close() | |||
} | |||
return nil |