1
1
mirror of https://github.com/go-gitea/gitea synced 2025-12-07 13:28:25 +00:00

Merge branch 'main' into allow-force-push-protected-branches

This commit is contained in:
Henry Goodman
2024-04-05 17:27:28 +11:00
committed by GitHub
1571 changed files with 39302 additions and 29654 deletions
+10 -1
View File
@@ -8,6 +8,15 @@ delay = 1000
include_ext = ["go", "tmpl"]
include_file = ["main.go"]
include_dir = ["cmd", "models", "modules", "options", "routers", "services"]
exclude_dir = ["modules/git/tests", "services/gitdiff/testdata", "modules/avatar/testdata", "models/fixtures", "models/migrations/fixtures", "modules/migration/file_format_testdata", "modules/avatar/identicon/testdata"]
exclude_dir = [
"models/fixtures",
"models/migrations/fixtures",
"modules/avatar/identicon/testdata",
"modules/avatar/testdata",
"modules/git/tests",
"modules/migration/file_format_testdata",
"routers/private/tests",
"services/gitdiff/testdata",
]
exclude_regex = ["_test.go$", "_gen.go$"]
stop_on_error = true
+5 -3
View File
@@ -4,11 +4,13 @@
"features": {
// installs nodejs into container
"ghcr.io/devcontainers/features/node:1": {
"version":"20"
"version": "20"
},
"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": {
@@ -22,7 +24,7 @@
"DavidAnson.vscode-markdownlint",
"Vue.volar",
"ms-azuretools.vscode-docker",
"zixuanchen.vitest-explorer",
"vitest.explorer",
"qwtel.sqlite-viewer",
"GitHub.vscode-pull-request-github"
]
+2 -3
View File
@@ -14,7 +14,7 @@ _test
# MS VSCode
.vscode
__debug_bin
__debug_bin*
# Architecture specific extensions/prefixes
*.[568vq]
@@ -62,7 +62,6 @@ cpu.out
/data
/indexers
/log
/public/img/avatar
/tests/integration/gitea-integration-*
/tests/integration/indexers-*
/tests/e2e/gitea-e2e-*
@@ -78,7 +77,7 @@ cpu.out
/public/assets/js
/public/assets/css
/public/assets/fonts
/public/assets/img/webpack
/public/assets/img/avatar
/vendor
/web_src/fomantic/node_modules
/web_src/fomantic/build/*
+22 -22
View File
@@ -3,6 +3,7 @@ reportUnusedDisableDirectives: true
ignorePatterns:
- /web_src/js/vendor
- /web_src/fomantic
parserOptions:
sourceType: module
@@ -42,10 +43,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]
@@ -123,7 +120,7 @@ rules:
"@stylistic/js/arrow-spacing": [2, {before: true, after: true}]
"@stylistic/js/block-spacing": [0]
"@stylistic/js/brace-style": [2, 1tbs, {allowSingleLine: true}]
"@stylistic/js/comma-dangle": [2, only-multiline]
"@stylistic/js/comma-dangle": [2, always-multiline]
"@stylistic/js/comma-spacing": [2, {before: false, after: true}]
"@stylistic/js/comma-style": [2, last]
"@stylistic/js/computed-property-spacing": [2, never]
@@ -171,7 +168,7 @@ rules:
"@stylistic/js/semi-spacing": [2, {before: false, after: true}]
"@stylistic/js/semi-style": [2, last]
"@stylistic/js/space-before-blocks": [2, always]
"@stylistic/js/space-before-function-paren": [0]
"@stylistic/js/space-before-function-paren": [2, {anonymous: ignore, named: never, asyncArrow: always}]
"@stylistic/js/space-in-parens": [2, never]
"@stylistic/js/space-infix-ops": [2]
"@stylistic/js/space-unary-ops": [2]
@@ -283,20 +280,20 @@ 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-attr: [2]
jquery/no-bind: [2]
jquery/no-class: [0]
jquery/no-clone: [2]
jquery/no-closest: [0]
jquery/no-css: [0]
jquery/no-css: [2]
jquery/no-data: [0]
jquery/no-deferred: [2]
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]
@@ -307,15 +304,15 @@ rules:
jquery/no-in-array: [2]
jquery/no-is-array: [2]
jquery/no-is-function: [2]
jquery/no-is: [0]
jquery/no-is: [2]
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]
@@ -396,12 +393,12 @@ 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-attr: [0]
no-jquery/no-append-html: [2]
no-jquery/no-attr: [2]
no-jquery/no-bind: [2]
no-jquery/no-box-model: [2]
no-jquery/no-browser: [2]
@@ -413,7 +410,7 @@ rules:
no-jquery/no-constructor-attributes: [2]
no-jquery/no-contains: [2]
no-jquery/no-context-prop: [2]
no-jquery/no-css: [0]
no-jquery/no-css: [2]
no-jquery/no-data: [0]
no-jquery/no-deferred: [2]
no-jquery/no-delegate: [2]
@@ -444,14 +441,14 @@ rules:
no-jquery/no-is-numeric: [2]
no-jquery/no-is-plain-object: [2]
no-jquery/no-is-window: [2]
no-jquery/no-is: [0]
no-jquery/no-is: [2]
no-jquery/no-jquery-constructor: [0]
no-jquery/no-live: [2]
no-jquery/no-load-shorthand: [2]
no-jquery/no-load: [2]
no-jquery/no-map-collection: [0]
no-jquery/no-map-util: [2]
no-jquery/no-map: [0]
no-jquery/no-map: [2]
no-jquery/no-merge: [2]
no-jquery/no-node-name: [2]
no-jquery/no-noop: [2]
@@ -466,7 +463,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]
@@ -487,7 +484,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]
@@ -540,7 +537,7 @@ rules:
no-underscore-dangle: [0]
no-unexpected-multiline: [2]
no-unmodified-loop-condition: [2]
no-unneeded-ternary: [0]
no-unneeded-ternary: [2]
no-unreachable-loop: [2]
no-unreachable: [2]
no-unsafe-finally: [2]
@@ -719,12 +716,14 @@ rules:
unicorn/import-style: [0]
unicorn/new-for-builtins: [2]
unicorn/no-abusive-eslint-disable: [0]
unicorn/no-anonymous-default-export: [0]
unicorn/no-array-callback-reference: [0]
unicorn/no-array-for-each: [2]
unicorn/no-array-method-this-argument: [2]
unicorn/no-array-push-push: [2]
unicorn/no-array-reduce: [2]
unicorn/no-await-expression-member: [0]
unicorn/no-await-in-promise-methods: [2]
unicorn/no-console-spaces: [0]
unicorn/no-document-cookie: [2]
unicorn/no-empty-file: [2]
@@ -741,6 +740,7 @@ rules:
unicorn/no-null: [0]
unicorn/no-object-as-default-parameter: [0]
unicorn/no-process-exit: [0]
unicorn/no-single-promise-in-promise-methods: [2]
unicorn/no-static-only-class: [2]
unicorn/no-thenable: [2]
unicorn/no-this-assignment: [2]
-1
View File
@@ -1,2 +1 @@
open_collective: gitea
custom: https://www.bountysource.com/teams/gitea
+64 -23
View File
@@ -1,36 +1,77 @@
modifies/docs:
- "**/*.md"
- "docs/**"
modifies/frontend:
- "web_src/**/*"
- changed-files:
- any-glob-to-any-file:
- "**/*.md"
- "docs/**"
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"
- "stylelint.config.js"
- ".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"
-22
View File
@@ -1,22 +0,0 @@
name: cron-lock
on:
schedule:
- cron: "0 0 * * *" # every day at 00:00 UTC
workflow_dispatch:
permissions:
issues: write
pull-requests: write
concurrency:
group: lock
jobs:
action:
runs-on: ubuntu-latest
if: github.repository == 'go-gitea/gitea'
steps:
- uses: dessant/lock-threads@v5
with:
issue-inactive-days: 45
+11 -22
View File
@@ -11,14 +11,19 @@ jobs:
if: github.repository == 'go-gitea/gitea'
steps:
- uses: actions/checkout@v4
- name: download from crowdin
uses: docker://jonasfranz/crowdin
- uses: crowdin/github-action@v1
with:
upload_sources: true
upload_translations: false
download_sources: false
download_translations: true
push_translations: false
push_sources: false
create_pull_request: false
config: crowdin.yml
env:
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
CROWDIN_KEY: ${{ secrets.CROWDIN_KEY }}
PLUGIN_DOWNLOAD: true
PLUGIN_EXPORT_DIR: options/locale/
PLUGIN_IGNORE_BRANCH: true
PLUGIN_PROJECT_IDENTIFIER: gitea
- name: update locales
run: ./build/update-locales.sh
- name: push translations to repo
@@ -31,19 +36,3 @@ jobs:
commit_message: "[skip ci] Updated translations via Crowdin"
remote: "git@github.com:go-gitea/gitea.git"
ssh_key: ${{ secrets.DEPLOY_KEY }}
crowdin-push:
runs-on: ubuntu-latest
if: github.repository == 'go-gitea/gitea'
steps:
- uses: actions/checkout@v4
- name: push translations to crowdin
uses: docker://jonasfranz/crowdin
env:
CROWDIN_KEY: ${{ secrets.CROWDIN_KEY }}
PLUGIN_UPLOAD: true
PLUGIN_EXPORT_DIR: options/locale/
PLUGIN_IGNORE_BRANCH: true
PLUGIN_PROJECT_IDENTIFIER: gitea
PLUGIN_FILES: |
locale_en-US.ini: options/locale/locale_en-US.ini
PLUGIN_BRANCH: main
+3 -1
View File
@@ -48,6 +48,7 @@ jobs:
- "Makefile"
- ".golangci.yml"
- ".editorconfig"
- "options/locale/locale_en-US.ini"
frontend:
- "**/*.js"
@@ -57,7 +58,7 @@ jobs:
- "package-lock.json"
- "Makefile"
- ".eslintrc.yaml"
- ".stylelintrc.yaml"
- "stylelint.config.js"
- ".npmrc"
docs:
@@ -72,6 +73,7 @@ jobs:
- "Makefile"
templates:
- "tools/lint-templates-*.js"
- "templates/**/*.tmpl"
- "pyproject.toml"
- "poetry.lock"
+8 -4
View File
@@ -32,11 +32,15 @@ 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"
- uses: actions/setup-node@v4
with:
node-version: 20
- run: pip install poetry
- run: make deps-py
- run: make deps-frontend
- run: make lint-templates
lint-yaml:
@@ -45,9 +49,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
+14 -4
View File
@@ -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
+3 -3
View File
@@ -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
+2 -3
View File
@@ -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-*
@@ -77,7 +77,6 @@ cpu.out
/public/assets/css
/public/assets/fonts
/public/assets/licenses.txt
/public/assets/img/webpack
/vendor
/web_src/fomantic/node_modules
/web_src/fomantic/build/*
+1 -1
View File
@@ -42,7 +42,7 @@ vscode:
- DavidAnson.vscode-markdownlint
- Vue.volar
- ms-azuretools.vscode-docker
- zixuanchen.vitest-explorer
- vitest.explorer
- qwtel.sqlite-viewer
- GitHub.vscode-pull-request-github
+3 -1
View File
@@ -4,6 +4,8 @@
/modules/options/bindata.go
/modules/public/bindata.go
/modules/templates/bindata.go
/vendor
/options/gitignore
/options/license
/public/assets
/vendor
node_modules
-2
View File
@@ -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
-221
View File
@@ -1,221 +0,0 @@
plugins:
- stylelint-declaration-strict-value
- stylelint-declaration-block-no-ignored-properties
- "@stylistic/stylelint-plugin"
ignoreFiles:
- "**/*.go"
overrides:
- files: ["**/chroma/*", "**/codemirror/*", "**/standalone/*", "**/console.css", "font_i18n.css"]
rules:
scale-unlimited/declaration-strict-value: null
- files: ["**/chroma/*", "**/codemirror/*"]
rules:
block-no-empty: null
- files: ["**/*.vue"]
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/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-vendor-prefix: true
at-rule-property-required-list: null
block-no-empty: true
color-function-notation: null
color-hex-alpha: null
color-hex-length: null
color-named: null
color-no-hex: null
color-no-invalid-hex: true
comment-empty-line-before: null
comment-no-empty: true
comment-pattern: null
comment-whitespace-inside: null
comment-word-disallowed-list: null
custom-media-pattern: null
custom-property-empty-line-before: null
custom-property-no-missing-var-function: true
custom-property-pattern: null
declaration-block-no-duplicate-custom-properties: true
declaration-block-no-duplicate-properties: [true, {ignore: [consecutive-duplicates-with-different-values]}]
declaration-block-no-redundant-longhand-properties: null
declaration-block-no-shorthand-property-overrides: null
declaration-block-single-line-max-declarations: null
declaration-empty-line-before: null
declaration-no-important: null
declaration-property-max-values: null
declaration-property-unit-allowed-list: null
declaration-property-unit-disallowed-list: {line-height: [em]}
declaration-property-value-allowed-list: null
declaration-property-value-disallowed-list: null
declaration-property-value-no-unknown: true
font-family-name-quotes: always-where-recommended
font-family-no-duplicate-names: true
font-family-no-missing-generic-family-keyword: true
font-weight-notation: null
function-allowed-list: null
function-calc-no-unspaced-operator: true
function-disallowed-list: null
function-linear-gradient-no-nonstandard-direction: true
function-name-case: lower
function-no-unknown: null
function-url-no-scheme-relative: null
function-url-quotes: always
function-url-scheme-allowed-list: null
function-url-scheme-disallowed-list: null
hue-degree-notation: null
import-notation: string
keyframe-block-no-duplicate-selectors: true
keyframe-declaration-no-important: true
keyframe-selector-notation: null
keyframes-name-pattern: null
length-zero-no-unit: [true, ignore: [custom-properties], ignoreFunctions: [var]]
max-nesting-depth: null
media-feature-name-allowed-list: null
media-feature-name-disallowed-list: null
media-feature-name-no-unknown: true
media-feature-name-no-vendor-prefix: true
media-feature-name-unit-allowed-list: null
media-feature-name-value-allowed-list: null
media-feature-name-value-no-unknown: true
media-feature-range-notation: null
media-query-no-invalid: true
named-grid-areas-no-invalid: true
no-descending-specificity: null
no-duplicate-at-import-rules: true
no-duplicate-selectors: true
no-empty-source: true
no-invalid-double-slash-comments: true
no-invalid-position-at-import-rule: null
no-irregular-whitespace: true
no-unknown-animations: null
no-unknown-custom-properties: null
number-max-precision: null
plugin/declaration-block-no-ignored-properties: true
property-allowed-list: null
property-disallowed-list: null
property-no-unknown: true
property-no-vendor-prefix: null
rule-empty-line-before: null
rule-selector-property-disallowed-list: null
scale-unlimited/declaration-strict-value: [[/color$/, font-weight], {ignoreValues: /^(inherit|transparent|unset|initial|currentcolor|none)$/, ignoreFunctions: false, disableFix: true, expandShorthand: true}]
selector-attribute-name-disallowed-list: null
selector-attribute-operator-allowed-list: null
selector-attribute-operator-disallowed-list: null
selector-attribute-quotes: always
selector-class-pattern: null
selector-combinator-allowed-list: null
selector-combinator-disallowed-list: null
selector-disallowed-list: null
selector-id-pattern: null
selector-max-attribute: null
selector-max-class: null
selector-max-combinators: null
selector-max-compound-selectors: null
selector-max-id: null
selector-max-pseudo-class: null
selector-max-specificity: null
selector-max-type: null
selector-max-universal: null
selector-nested-pattern: null
selector-no-qualifying-type: null
selector-no-vendor-prefix: true
selector-not-notation: null
selector-pseudo-class-allowed-list: null
selector-pseudo-class-disallowed-list: null
selector-pseudo-class-no-unknown: true
selector-pseudo-element-allowed-list: null
selector-pseudo-element-colon-notation: double
selector-pseudo-element-disallowed-list: null
selector-pseudo-element-no-unknown: true
selector-type-case: lower
selector-type-no-unknown: [true, {ignore: [custom-elements]}]
shorthand-property-no-redundant-values: true
string-no-newline: true
time-min-milliseconds: null
unit-allowed-list: null
unit-disallowed-list: null
unit-no-unknown: true
value-keyword-case: null
value-no-vendor-prefix: [true, {ignoreValues: [box, inline-box]}]
+234
View File
@@ -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
+9 -1
View File
@@ -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)
@@ -103,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).
@@ -456,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.
+2
View File
@@ -59,3 +59,5 @@ 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)
Yu Liu <1240335630@qq.com> (@HEREYUA)
+26 -37
View File
@@ -31,7 +31,7 @@ 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/golangci/misspell/cmd/misspell@v0.4.1
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.30.5
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.3
@@ -42,9 +42,6 @@ DOCKER_TAG ?= latest
DOCKER_REF := $(DOCKER_IMAGE):$(DOCKER_TAG)
ifeq ($(HAS_GO), yes)
GOPATH ?= $(shell $(GO) env GOPATH)
export PATH := $(GOPATH)/bin:$(PATH)
CGO_EXTRA_CFLAGS := -DSQLITE_MAX_VARIABLE_NUMBER=32766
CGO_CFLAGS ?= $(shell $(GO) env CGO_CFLAGS) $(CGO_EXTRA_CFLAGS)
endif
@@ -115,13 +112,14 @@ 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
WEBPACK_DEST_ENTRIES := public/assets/js public/assets/css public/assets/fonts
BINDATA_DEST := modules/public/bindata.go modules/options/bindata.go modules/templates/bindata.go
BINDATA_HASH := $(addsuffix .hash,$(BINDATA_DEST))
@@ -146,7 +144,10 @@ 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)
@@ -164,8 +165,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\'
@@ -373,19 +374,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
@@ -426,14 +427,15 @@ 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:
$(GO) run $(ACTIONLINT_PACKAGE)
.PHONY: lint-templates
lint-templates: .venv
lint-templates: .venv node_modules
@node tools/lint-templates-svg.js
@poetry run djlint $(shell find templates -type f -iname '*.tmpl')
.PHONY: lint-yaml
@@ -442,7 +444,7 @@ lint-yaml: .venv
.PHONY: watch
watch:
@bash build/watch.sh
@bash tools/watch.sh
.PHONY: watch-frontend
watch-frontend: node-check node_modules
@@ -602,8 +604,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%
@@ -710,9 +711,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
@@ -720,20 +719,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
@@ -741,9 +735,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
@@ -847,10 +839,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
@@ -909,6 +897,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
@@ -927,7 +916,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
@@ -970,8 +959,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-beta20 imagemin-zopfli@7
node tools/generate-images.js $(TAGS)
.PHONY: generate-manpage
generate-manpage:
+13 -53
View File
@@ -1,58 +1,18 @@
<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>
# Gitea
<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>
[![](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://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")
<p align="center">
<a href="README_ZH.md">View this document in Chinese</a>
</p>
[View this document in Chinese](./README_ZH.md)
## Purpose
+13 -53
View File
@@ -1,58 +1,18 @@
<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>
# Gitea
<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>
[![](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://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")
<p align="center">
<a href="README.md">View this document in English</a>
</p>
[View this document in English](./README.md)
## 目标
+13 -8
View File
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -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 -4
View File
@@ -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,
}
+68 -228
View File
@@ -6,14 +6,13 @@ package cmd
import (
"fmt"
"io"
"os"
"path"
"path/filepath"
"strings"
"time"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/dump"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
@@ -25,89 +24,17 @@ import (
"github.com/urfave/cli/v2"
)
func addReader(w archiver.Writer, r io.ReadCloser, info os.FileInfo, customName string, verbose bool) error {
if verbose {
log.Info("Adding file %s", customName)
}
return w.Write(archiver.File{
FileInfo: archiver.FileInfo{
FileInfo: info,
CustomName: customName,
},
ReadCloser: r,
})
}
func addFile(w archiver.Writer, filePath, absPath string, verbose bool) error {
file, err := os.Open(absPath)
if err != nil {
return err
}
defer file.Close()
fileInfo, err := file.Stat()
if err != nil {
return err
}
return addReader(w, file, fileInfo, filePath, verbose)
}
func isSubdir(upper, lower string) (bool, error) {
if relPath, err := filepath.Rel(upper, lower); err != nil {
return false, err
} else if relPath == "." || !strings.HasPrefix(relPath, ".") {
return true, nil
}
return false, nil
}
type outputType struct {
Enum []string
Default string
selected string
}
func (o outputType) Join() string {
return strings.Join(o.Enum, ", ")
}
func (o *outputType) Set(value string) error {
for _, enum := range o.Enum {
if enum == value {
o.selected = value
return nil
}
}
return fmt.Errorf("allowed values are %s", o.Join())
}
func (o outputType) String() string {
if o.selected == "" {
return o.Default
}
return o.selected
}
var outputTypeEnum = &outputType{
Enum: []string{"zip", "tar", "tar.sz", "tar.gz", "tar.xz", "tar.bz2", "tar.br", "tar.lz4", "tar.zst"},
Default: "zip",
}
// CmdDump represents the available dump sub-command.
var CmdDump = &cli.Command{
Name: "dump",
Usage: "Dump Gitea files and database",
Description: `Dump compresses all related files and database into zip file.
It can be used for backup and capture Gitea server image to send to maintainer`,
Action: runDump,
Name: "dump",
Usage: "Dump Gitea files and database",
Description: `Dump compresses all related files and database into zip file. It can be used for backup and capture Gitea server image to send to maintainer`,
Action: runDump,
Flags: []cli.Flag{
&cli.StringFlag{
Name: "file",
Aliases: []string{"f"},
Value: fmt.Sprintf("gitea-dump-%d.zip", time.Now().Unix()),
Usage: "Name of the dump file which will be created. Supply '-' for stdout. See type for available types.",
Usage: `Name of the dump file which will be created, default to "gitea-dump-{time}.zip". Supply '-' for stdout. See type for available types.`,
},
&cli.BoolFlag{
Name: "verbose",
@@ -160,64 +87,52 @@ It can be used for backup and capture Gitea server image to send to maintainer`,
Name: "skip-index",
Usage: "Skip bleve index data",
},
&cli.GenericFlag{
&cli.StringFlag{
Name: "type",
Value: outputTypeEnum,
Usage: fmt.Sprintf("Dump output format: %s", outputTypeEnum.Join()),
Usage: fmt.Sprintf(`Dump output format, default to "zip", supported types: %s`, strings.Join(dump.SupportedOutputTypes, ", ")),
},
},
}
func fatal(format string, args ...any) {
fmt.Fprintf(os.Stderr, format+"\n", args...)
log.Fatal(format, args...)
}
func runDump(ctx *cli.Context) error {
var file *os.File
fileName := ctx.String("file")
outType := ctx.String("type")
if fileName == "-" {
file = os.Stdout
setupConsoleLogger(log.FATAL, log.CanColorStderr, os.Stderr)
} else {
for _, suffix := range outputTypeEnum.Enum {
if strings.HasSuffix(fileName, "."+suffix) {
fileName = strings.TrimSuffix(fileName, "."+suffix)
break
}
}
fileName += "." + outType
}
setting.MustInstalled()
// make sure we are logging to the console no matter what the configuration tells us do to
// FIXME: don't use CfgProvider directly
if _, err := setting.CfgProvider.Section("log").NewKey("MODE", "console"); err != nil {
fatal("Setting logging mode to console failed: %v", err)
}
if _, err := setting.CfgProvider.Section("log.console").NewKey("STDERR", "true"); err != nil {
fatal("Setting console logger to stderr failed: %v", err)
}
// Set loglevel to Warn if quiet-mode is requested
if ctx.Bool("quiet") {
if _, err := setting.CfgProvider.Section("log.console").NewKey("LEVEL", "Warn"); err != nil {
fatal("Setting console log-level failed: %v", err)
}
}
if !setting.InstallLock {
log.Error("Is '%s' really the right config path?\n", setting.CustomConf)
return fmt.Errorf("gitea is not initialized")
}
setting.LoadSettings() // cannot access session settings otherwise
quite := ctx.Bool("quiet")
verbose := ctx.Bool("verbose")
if verbose && ctx.Bool("quiet") {
return fmt.Errorf("--quiet and --verbose cannot both be set")
if verbose && quite {
fatal("Option --quiet and --verbose cannot both be set")
}
// outFileName is either "-" or a file name (will be made absolute)
outFileName, outType := dump.PrepareFileNameAndType(ctx.String("file"), ctx.String("type"))
if outType == "" {
fatal("Invalid output type")
}
outFile := os.Stdout
if outFileName != "-" {
var err error
if outFileName, err = filepath.Abs(outFileName); err != nil {
fatal("Unable to get absolute path of dump file: %v", err)
}
if exist, _ := util.IsExist(outFileName); exist {
fatal("Dump file %q exists", outFileName)
}
if outFile, err = os.Create(outFileName); err != nil {
fatal("Unable to create dump file %q: %v", outFileName, err)
}
defer outFile.Close()
}
setupConsoleLogger(util.Iif(quite, log.WARN, log.INFO), log.CanColorStderr, os.Stderr)
setting.DisableLoggerInit()
setting.LoadSettings() // cannot access session settings otherwise
stdCtx, cancel := installSignals()
defer cancel()
@@ -226,44 +141,32 @@ func runDump(ctx *cli.Context) error {
return err
}
if err := storage.Init(); err != nil {
if err = storage.Init(); err != nil {
return err
}
if file == nil {
file, err = os.Create(fileName)
if err != nil {
fatal("Unable to open %s: %v", fileName, err)
}
}
defer file.Close()
absFileName, err := filepath.Abs(fileName)
if err != nil {
return err
}
var iface any
if fileName == "-" {
iface, err = archiver.ByExtension(fmt.Sprintf(".%s", outType))
} else {
iface, err = archiver.ByExtension(fileName)
}
archiverGeneric, err := archiver.ByExtension("." + outType)
if err != nil {
fatal("Unable to get archiver for extension: %v", err)
}
w, _ := iface.(archiver.Writer)
if err := w.Create(file); err != nil {
archiverWriter := archiverGeneric.(archiver.Writer)
if err := archiverWriter.Create(outFile); err != nil {
fatal("Creating archiver.Writer failed: %v", err)
}
defer w.Close()
defer archiverWriter.Close()
dumper := &dump.Dumper{
Writer: archiverWriter,
Verbose: verbose,
}
dumper.GlobalExcludeAbsPath(outFileName)
if ctx.IsSet("skip-repository") && ctx.Bool("skip-repository") {
log.Info("Skip dumping local repositories")
} else {
log.Info("Dumping local repositories... %s", setting.RepoRootPath)
if err := addRecursiveExclude(w, "repos", setting.RepoRootPath, []string{absFileName}, verbose); err != nil {
if err := dumper.AddRecursiveExclude("repos", setting.RepoRootPath, nil); err != nil {
fatal("Failed to include repositories: %v", err)
}
@@ -276,8 +179,7 @@ func runDump(ctx *cli.Context) error {
if err != nil {
return err
}
return addReader(w, object, info, path.Join("data", "lfs", objPath), verbose)
return dumper.AddReader(object, info, path.Join("data", "lfs", objPath))
}); err != nil {
fatal("Failed to dump LFS objects: %v", err)
}
@@ -310,15 +212,13 @@ func runDump(ctx *cli.Context) error {
fatal("Failed to dump database: %v", err)
}
if err := addFile(w, "gitea-db.sql", dbDump.Name(), verbose); err != nil {
if err = dumper.AddFile("gitea-db.sql", dbDump.Name()); err != nil {
fatal("Failed to include gitea-db.sql: %v", err)
}
if len(setting.CustomConf) > 0 {
log.Info("Adding custom configuration file from %s", setting.CustomConf)
if err := addFile(w, "app.ini", setting.CustomConf, verbose); err != nil {
fatal("Failed to include specified app.ini: %v", err)
}
log.Info("Adding custom configuration file from %s", setting.CustomConf)
if err = dumper.AddFile("app.ini", setting.CustomConf); err != nil {
fatal("Failed to include specified app.ini: %v", err)
}
if ctx.IsSet("skip-custom-dir") && ctx.Bool("skip-custom-dir") {
@@ -326,8 +226,8 @@ func runDump(ctx *cli.Context) error {
} else {
customDir, err := os.Stat(setting.CustomPath)
if err == nil && customDir.IsDir() {
if is, _ := isSubdir(setting.AppDataPath, setting.CustomPath); !is {
if err := addRecursiveExclude(w, "custom", setting.CustomPath, []string{absFileName}, verbose); err != nil {
if is, _ := dump.IsSubdir(setting.AppDataPath, setting.CustomPath); !is {
if err := dumper.AddRecursiveExclude("custom", setting.CustomPath, nil); err != nil {
fatal("Failed to include custom: %v", err)
}
} else {
@@ -364,8 +264,7 @@ func runDump(ctx *cli.Context) error {
excludes = append(excludes, setting.Attachment.Storage.Path)
excludes = append(excludes, setting.Packages.Storage.Path)
excludes = append(excludes, setting.Log.RootPath)
excludes = append(excludes, absFileName)
if err := addRecursiveExclude(w, "data", setting.AppDataPath, excludes, verbose); err != nil {
if err := dumper.AddRecursiveExclude("data", setting.AppDataPath, excludes); err != nil {
fatal("Failed to include data directory: %v", err)
}
}
@@ -377,8 +276,7 @@ func runDump(ctx *cli.Context) error {
if err != nil {
return err
}
return addReader(w, object, info, path.Join("data", "attachments", objPath), verbose)
return dumper.AddReader(object, info, path.Join("data", "attachments", objPath))
}); err != nil {
fatal("Failed to dump attachments: %v", err)
}
@@ -392,8 +290,7 @@ func runDump(ctx *cli.Context) error {
if err != nil {
return err
}
return addReader(w, object, info, path.Join("data", "packages", objPath), verbose)
return dumper.AddReader(object, info, path.Join("data", "packages", objPath))
}); err != nil {
fatal("Failed to dump packages: %v", err)
}
@@ -409,80 +306,23 @@ func runDump(ctx *cli.Context) error {
log.Error("Unable to check if %s exists. Error: %v", setting.Log.RootPath, err)
}
if isExist {
if err := addRecursiveExclude(w, "log", setting.Log.RootPath, []string{absFileName}, verbose); err != nil {
if err := dumper.AddRecursiveExclude("log", setting.Log.RootPath, nil); err != nil {
fatal("Failed to include log: %v", err)
}
}
}
if fileName != "-" {
if err = w.Close(); err != nil {
_ = util.Remove(fileName)
fatal("Failed to save %s: %v", fileName, err)
if outFileName == "-" {
log.Info("Finish dumping to stdout")
} else {
if err = archiverWriter.Close(); err != nil {
_ = os.Remove(outFileName)
fatal("Failed to save %q: %v", outFileName, err)
}
if err := os.Chmod(fileName, 0o600); err != nil {
if err = os.Chmod(outFileName, 0o600); err != nil {
log.Info("Can't change file access permissions mask to 0600: %v", err)
}
}
if fileName != "-" {
log.Info("Finish dumping in file %s", fileName)
} else {
log.Info("Finish dumping to stdout")
}
return nil
}
// addRecursiveExclude zips absPath to specified insidePath inside writer excluding excludeAbsPath
func addRecursiveExclude(w archiver.Writer, insidePath, absPath string, excludeAbsPath []string, verbose bool) error {
absPath, err := filepath.Abs(absPath)
if err != nil {
return err
}
dir, err := os.Open(absPath)
if err != nil {
return err
}
defer dir.Close()
files, err := dir.Readdir(0)
if err != nil {
return err
}
for _, file := range files {
currentAbsPath := filepath.Join(absPath, file.Name())
currentInsidePath := path.Join(insidePath, file.Name())
if file.IsDir() {
if !util.SliceContainsString(excludeAbsPath, currentAbsPath) {
if err := addFile(w, currentInsidePath, currentAbsPath, false); err != nil {
return err
}
if err = addRecursiveExclude(w, currentInsidePath, currentAbsPath, excludeAbsPath, verbose); err != nil {
return err
}
}
} else {
// only copy regular files and symlink regular files, skip non-regular files like socket/pipe/...
shouldAdd := file.Mode().IsRegular()
if !shouldAdd && file.Mode()&os.ModeSymlink == os.ModeSymlink {
target, err := filepath.EvalSymlinks(currentAbsPath)
if err != nil {
return err
}
targetStat, err := os.Stat(target)
if err != nil {
return err
}
shouldAdd = targetStat.Mode().IsRegular()
}
if shouldAdd {
if err = addFile(w, currentInsidePath, currentAbsPath, verbose); err != nil {
return err
}
}
}
log.Info("Finish dumping in file %s", outFileName)
}
return nil
}
+1 -1
View File
@@ -71,7 +71,7 @@ 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
+1 -12
View File
@@ -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)
}
-1
View File
@@ -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
+12
View File
@@ -0,0 +1,12 @@
project_id_env: CROWDIN_PROJECT_ID
api_token_env: CROWDIN_KEY
base_path: "."
base_url: "https://api.crowdin.com"
preserve_hierarchy: true
files:
- source: "/options/locale/locale_en-US.ini"
translation: "/options/locale/locale_%locale%.ini"
type: "ini"
skip_untranslated_strings: true
export_only_approved: true
update_option: "update_as_unapproved"
+24 -2
View File
@@ -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
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -437,7 +441,7 @@ INTERNAL_TOKEN =
;INTERNAL_TOKEN_URI = file:/etc/gitea/internal_token
;;
;; How long to remember that a user is logged in before requiring relogin (in days)
;LOGIN_REMEMBER_DAYS = 7
;LOGIN_REMEMBER_DAYS = 31
;;
;; Name of the cookie used to store the current username.
;COOKIE_USERNAME = gitea_awesome
@@ -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 =
;;
@@ -1470,6 +1480,16 @@ 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 =
;; Comma separated list of disabled features ONLY if the user has an external login type (eg. LDAP, Oauth, etc.), could be `deletion`, `manage_ssh_keys`, `manage_gpg_keys`. This setting is independent from `USER_DISABLED_FEATURES` and supplements its behavior.
;; - 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
;;EXTERNAL_USER_DISABLE_FEATURES =
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -2295,6 +2315,8 @@ LEVEL = Info
;SHOW_FOOTER_VERSION = true
;; Show template execution time in the footer
;SHOW_FOOTER_TEMPLATE_LOAD_TIME = true
;; Show the "powered by" text in the footer
;SHOW_FOOTER_POWERED_BY = true
;; Generate sitemap. Defaults to `true`.
;ENABLE_SITEMAP = true
;; Enable/Disable RSS/Atom feed
@@ -2593,7 +2615,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.
@@ -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
@@ -458,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.
@@ -517,13 +518,21 @@ 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.
- `EXTERNAL_USER_DISABLE_FEATURES`: **_empty_**: Comma separated list of disabled features ONLY if the user has an external login type (eg. LDAP, Oauth, etc.), could be `deletion`, `manage_ssh_keys`, `manage_gpg_keys`. This setting is independent from `USER_DISABLED_FEATURES` and supplements its behavior.
- `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`)
- `INSTALL_LOCK`: **false**: Controls access to the installation page. When set to "true", the installation page is not accessible.
- `SECRET_KEY`: **\<random at every install\>**: Global secret key. This key is VERY IMPORTANT, if you lost it, the data encrypted by it (like 2FA secret) can't be decrypted anymore.
- `SECRET_KEY_URI`: **_empty_**: Instead of defining SECRET_KEY, this option can be used to use the key stored in a file (example value: `file:/etc/gitea/secret_key`). It shouldn't be lost like SECRET_KEY.
- `LOGIN_REMEMBER_DAYS`: **7**: Cookie lifetime, in days.
- `LOGIN_REMEMBER_DAYS`: **31**: How long to remember that a user is logged in before requiring relogin (in days).
- `COOKIE_REMEMBER_NAME`: **gitea\_incredible**: Name of cookie used to store authentication
information.
- `REVERSE_PROXY_AUTHENTICATION_USER`: **X-WEBAUTH-USER**: Header name for reverse proxy
@@ -585,7 +594,7 @@ And the following unique queues:
## OpenID (`openid`)
- `ENABLE_OPENID_SIGNIN`: **false**: Allow authentication in via OpenID.
- `ENABLE_OPENID_SIGNIN`: **true**: Allow authentication in via OpenID.
- `ENABLE_OPENID_SIGNUP`: **! DISABLE\_REGISTRATION**: Allow registering via OpenID.
- `WHITELISTED_URIS`: **_empty_**: If non-empty, list of POSIX regex patterns matching
OpenID URI's to permit.
@@ -827,7 +836,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]`
@@ -1401,7 +1410,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`.
@@ -1420,5 +1429,6 @@ Like `uses: https://gitea.com/actions/checkout@v4` or `uses: http://your-git-ser
- `SHOW_FOOTER_VERSION`: **true**: Show Gitea and Go version information in the footer.
- `SHOW_FOOTER_TEMPLATE_LOAD_TIME`: **true**: Show time of template execution in the footer.
- `SHOW_FOOTER_POWERED_BY`: **true**: Show the "powered by" text in the footer.
- `ENABLE_SITEMAP`: **true**: Generate sitemap.
- `ENABLE_FEED`: **true**: Enable/Disable RSS/Atom feed.
@@ -497,13 +497,17 @@ 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`)
- `INSTALL_LOCK`: **false**:控制是否能够访问安装向导页面,设置为 `true` 则禁止访问安装向导页面。
- `SECRET_KEY`: **\<每次安装时随机生成\>**:全局服务器安全密钥。这个密钥非常重要,如果丢失将无法解密加密的数据(例如 2FA)。
- `SECRET_KEY_URI`: **_empty_**:与定义 `SECRET_KEY` 不同,此选项可用于使用存储在文件中的密钥(示例值:`file:/etc/gitea/secret_key`)。它不应该像 `SECRET_KEY` 一样容易丢失。
- `LOGIN_REMEMBER_DAYS`: **7**Cookie 保存时间,单位为天
- `LOGIN_REMEMBER_DAYS`: **31**在要求重新登录之前,记住用户的登录状态多长时间(以天为单位)
- `COOKIE_REMEMBER_NAME`: **gitea\_incredible**:保存自动登录信息的 Cookie 名称。
- `REVERSE_PROXY_AUTHENTICATION_USER`: **X-WEBAUTH-USER**:反向代理认证的 HTTP 头部名称,用于提供用户信息。
- `REVERSE_PROXY_AUTHENTICATION_EMAIL`: **X-WEBAUTH-EMAIL**:反向代理认证的 HTTP 头部名称,用于提供邮箱信息。
@@ -558,7 +562,7 @@ Gitea 创建以下非唯一队列:
## OpenID (`openid`)
- `ENABLE_OPENID_SIGNIN`: **false**:允许通过OpenID进行身份验证。
- `ENABLE_OPENID_SIGNIN`: **true**:允许通过OpenID进行身份验证。
- `ENABLE_OPENID_SIGNUP`: **! DISABLE\_REGISTRATION**:允许通过OpenID进行注册。
- `WHITELISTED_URIS`: **_empty_**:如果非空,是一组匹配OpenID URI的POSIX正则表达式模式,用于允许访问。
- `BLACKLISTED_URIS`: **_empty_**:如果非空,是一组匹配OpenID URI的POSIX正则表达式模式,用于阻止访问。
@@ -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]` 中定义的名称。
@@ -1349,5 +1353,6 @@ PROXY_HOSTS = *.github.com
- `SHOW_FOOTER_VERSION`: **true**: 在页面底部显示Gitea的版本。
- `SHOW_FOOTER_TEMPLATE_LOAD_TIME`: **true**: 在页脚显示模板执行的时间。
- `SHOW_FOOTER_POWERED_BY`: **true**: 在页脚显示“由...提供动力”的文本。
- `ENABLE_SITEMAP`: **true**: 生成sitemap.
- `ENABLE_FEED`: **true**: 是否启用RSS/Atom
@@ -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`.
@@ -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.
@@ -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}}
```
@@ -207,7 +207,7 @@ _主题_ 和 _邮件正文_ 由 [Golang的模板引擎](https://go.dev/pkg/text/
{{if not (eq .Body "")}}
<h3>消息内容:</h3>
<hr>
{{.Body | Str2html}}
{{.Body}}
{{end}}
</p>
<hr>
@@ -228,7 +228,7 @@ _主题_ 和 _邮件正文_ 由 [Golang的模板引擎](https://go.dev/pkg/text/
> [@rhonda](#)Rhonda Myers)更新了 [mike/stuff#38](#)。
>
> #### 消息内容
> #### 消息内容
>
> \_********************************\_********************************
>
@@ -242,20 +242,20 @@ _主题_ 和 _邮件正文_ 由 [Golang的模板引擎](https://go.dev/pkg/text/
模板系统包含一些函数,可用于进一步处理和格式化消息。以下是其中一些函数的列表:
| 函数名 | 参数 | 可用于 | 用法 |
| ----------------- | ----------- | ------------ | --------------------------------------------------------------------------------- |
| `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}}
```
@@ -17,6 +17,12 @@ menu:
# Repository indexer
## Builtin repository code search without indexer
Users could do repository-level code search without setting up a repository indexer.
The builtin code search is based on the `git grep` command, which is fast and efficient for small repositories.
Better code search support could be achieved by setting up the repository indexer.
## Setting up the repository indexer
Gitea can search through the files of the repositories by enabling this function in your [`app.ini`](administration/config-cheat-sheet.md):
@@ -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-word-break`), 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
@@ -118,7 +118,7 @@ However, there are still some special cases, so the current guideline is:
### Show/Hide Elements
* Vue components are recommended to use `v-if` and `v-show` to show/hide elements.
* Go template code should use Gitea's `.gt-hidden` and `showElem()/hideElem()/toggleElem()`, see more details in `.gt-hidden`'s comment.
* Go template code should use `.tw-hidden` and `showElem()/hideElem()/toggleElem()`, see more details in `.tw-hidden`'s comment.
### Styles and Attributes in Go HTML Template
@@ -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,13 +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-word-break`),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`),
但仍然存在许多问题需要大量的工作和时间来修复。
### 框架使用
@@ -117,7 +117,7 @@ Gitea使用一些补丁使Fomantic UI更具可访问性(参见`aria.js`和`ari
### 显示/隐藏元素
* 推荐在Vue组件中使用`v-if``v-show`来显示/隐藏元素。
* Go 模板代码应使用 Gitea 的 `.gt-hidden``showElem()/hideElem()/toggleElem()` 来显示/隐藏元素,请参阅`.gt-hidden`的注释以获取更多详细信息。
* Go 模板代码应使用 `.tw-hidden``showElem()/hideElem()/toggleElem()` 来显示/隐藏元素,请参阅`.tw-hidden`的注释以获取更多详细信息。
### Go HTML 模板中的样式和属性
+1 -1
View File
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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`。查看
+4 -2
View File
@@ -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`
+4 -2
View File
@@ -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`
@@ -87,6 +87,9 @@ _Symbols used in table:_
| Git Blame | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Visual comparison of image changes | ✓ | ✘ | ✓ | ? | ? | ? | ✘ | ✘ |
- Gitea has builtin repository-level code search
- Better code search support could be achieved by [using a repository indexer](administration/repo-indexer.md)
## Issue Tracker
| Feature | Gitea | Gogs | GitHub EE | GitLab CE | GitLab EE | BitBucket | RhodeCode CE | RhodeCode EE |
@@ -304,7 +304,8 @@ services:
- GITEA__mailer__ENABLED=true
- GITEA__mailer__FROM=${GITEA__mailer__FROM:?GITEA__mailer__FROM not set}
- GITEA__mailer__PROTOCOL=smtps
- GITEA__mailer__HOST=${GITEA__mailer__HOST:?GITEA__mailer__HOST not set}
- GITEA__mailer__SMTP_ADDR=${GITEA__mailer__SMTP_ADDR:?GITEA__mailer__SMTP_ADDR not set}
- GITEA__mailer__SMTP_PORT=${GITEA__mailer__SMTP_PORT:?GITEA__mailer__SMTP_PORT not set}
- GITEA__mailer__USER=${GITEA__mailer__USER:-apikey}
- GITEA__mailer__PASSWD="""${GITEA__mailer__PASSWD:?GITEA__mailer__PASSWD not set}"""
```
@@ -545,7 +546,7 @@ In this option, the idea is that the host SSH uses an `AuthorizedKeysCommand` in
```bash
cat <<"EOF" | sudo tee /home/git/docker-shell
#!/bin/sh
/usr/bin/docker exec -i --env SSH_ORIGINAL_COMMAND="$SSH_ORIGINAL_COMMAND" gitea sh "$@"
/usr/bin/docker exec -i -u git --env SSH_ORIGINAL_COMMAND="$SSH_ORIGINAL_COMMAND" gitea sh "$@"
EOF
sudo chmod +x /home/git/docker-shell
sudo usermod -s /home/git/docker-shell git
@@ -560,7 +561,7 @@ Add the following block to `/etc/ssh/sshd_config`, on the host:
```bash
Match User git
AuthorizedKeysCommandUser git
AuthorizedKeysCommand /usr/bin/docker exec -i gitea /usr/local/bin/gitea keys -c /data/gitea/conf/app.ini -e git -u %u -t %t -k %k
AuthorizedKeysCommand /usr/bin/docker exec -i -u git gitea /usr/local/bin/gitea keys -c /data/gitea/conf/app.ini -e git -u %u -t %t -k %k
```
(From 1.16.0 you will not need to set the `-c /data/gitea/conf/app.ini` option.)
@@ -95,12 +95,6 @@ Gitea Actions目前不支持此功能,如果使用它,结果将始终为空
## 缺失的功能
### 变量
请参阅[变量](https://docs.github.com/zh/actions/learn-github-actions/variables)。
目前变量功能正在开发中。
### 问题匹配器
问题匹配器是一种扫描Actions输出以查找指定正则表达式模式并在用户界面中突出显示该信息的方法。
+7 -8
View File
@@ -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?
+8 -8
View File
@@ -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的权限?
+37
View File
@@ -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 |
-34
View File
@@ -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
+86 -85
View File
@@ -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.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.1
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,114 +30,114 @@ 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
github.com/go-ap/activitypub v0.0.0-20231114162308-e219254dc5c9
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.11
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.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.10.0
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-20240117000934-35fc243c5815
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.1
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-rc6
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.18.0
github.com/prometheus/client_golang v1.19.0
github.com/quasoft/websspi v1.1.2
github.com/redis/go-redis/v9 v9.4.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.1-0.20240124161140-277b154961dd
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.27.1
github.com/xanzy/go-gitlab v0.96.0
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.18.0
golang.org/x/crypto v0.22.0
golang.org/x/image v0.15.0
golang.org/x/net v0.20.0
golang.org/x/oauth2 v0.16.0
golang.org/x/sys v0.16.0
golang.org/x/net v0.24.0
golang.org/x/oauth2 v0.18.0
golang.org/x/sys v0.19.0
golang.org/x/text v0.14.0
golang.org/x/tools v0.17.0
google.golang.org/grpc v1.60.1
google.golang.org/protobuf v1.32.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
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.1 // indirect
github.com/ClickHouse/clickhouse-go/v2 v2.17.1 // 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 v1.0.0 // indirect
github.com/RoaringBitmap/roaring v1.7.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
@@ -145,12 +145,12 @@ require (
github.com/aymerick/douceur v0.2.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bits-and-blooms/bitset v1.13.0 // indirect
github.com/blevesearch/bleve_index_api v1.1.5 // indirect
github.com/blevesearch/geo v0.1.19 // 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.6 // 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
@@ -166,43 +166,43 @@ require (
github.com/cespare/xxhash/v2 v2.2.0 // 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.22.2 // 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.2 // indirect
github.com/go-openapi/jsonreference v0.20.4 // indirect
github.com/go-openapi/loads v0.21.5 // indirect
github.com/go-openapi/runtime v0.26.2 // indirect
github.com/go-openapi/spec v0.20.14 // indirect
github.com/go-openapi/strfmt v0.22.0 // indirect
github.com/go-openapi/swag v0.22.7 // indirect
github.com/go-openapi/validate v0.22.6 // indirect
github.com/go-webauthn/x v0.1.6 // 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
@@ -230,6 +230,7 @@ require (
github.com/mholt/acmez v1.2.0 // 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
@@ -241,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.11.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.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.46.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
@@ -260,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
@@ -271,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.22.0 // indirect
go.opentelemetry.io/otel/trace v1.22.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-20240119083558-1b970713d09a // indirect
golang.org/x/mod v0.14.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-20240116215550-a9fa1716bcac // 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
@@ -302,7 +303,7 @@ 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
+189 -514
View File
File diff suppressed because it is too large Load Diff
+22
View File
@@ -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
}
+22 -4
View File
@@ -170,15 +170,16 @@ func updateRepoRunsNumbers(ctx context.Context, repo *repo_model.Repository) err
return err
}
// CancelRunningJobs cancels all running and waiting jobs associated with a specific workflow.
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'.
// CancelPreviousJobs cancels all previous jobs of the same repository, reference, workflow, and event.
// It's useful when a new run is triggered, and all previous runs needn't be continued anymore.
func CancelPreviousJobs(ctx context.Context, repoID int64, ref, workflowID string, event webhook_module.HookEventType) error {
// Find all runs in the specified repository, reference, and workflow with non-final status
runs, total, err := db.FindAndCount[ActionRun](ctx, FindRunOptions{
RepoID: repoID,
Ref: ref,
WorkflowID: workflowID,
TriggerEvent: event,
Status: []Status{StatusRunning, StatusWaiting},
Status: []Status{StatusRunning, StatusWaiting, StatusBlocked},
})
if err != nil {
return err
@@ -339,6 +340,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).
+8 -5
View File
@@ -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"
@@ -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
}
+2 -2
View File
@@ -127,14 +127,14 @@ func CleanRepoScheduleTasks(ctx context.Context, repo *repo_model.Repository) er
return fmt.Errorf("DeleteCronTaskByRepo: %v", err)
}
// cancel running cron jobs of this repository and delete old schedules
if err := CancelRunningJobs(
if err := CancelPreviousJobs(
ctx,
repo.ID,
repo.DefaultBranch,
"",
webhook_module.HookEventSchedule,
); err != nil {
return fmt.Errorf("CancelRunningJobs: %v", err)
return fmt.Errorf("CancelPreviousJobs: %v", err)
}
return nil
}
+49 -11
View File
@@ -6,12 +6,11 @@ package actions
import (
"context"
"errors"
"fmt"
"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"
"xorm.io/builder"
)
@@ -54,24 +53,24 @@ type FindVariablesOpts struct {
db.ListOptions
OwnerID int64
RepoID int64
Name string
}
func (opts FindVariablesOpts) ToConds() builder.Cond {
cond := builder.NewCond()
// Since we now support instance-level variables,
// there is no need to check for null values for `owner_id` and `repo_id`
cond = cond.And(builder.Eq{"owner_id": opts.OwnerID})
cond = cond.And(builder.Eq{"repo_id": opts.RepoID})
if opts.Name != "" {
cond = cond.And(builder.Eq{"name": strings.ToUpper(opts.Name)})
}
return cond
}
func GetVariableByID(ctx context.Context, variableID int64) (*ActionVariable, error) {
var variable ActionVariable
has, err := db.GetEngine(ctx).Where("id=?", variableID).Get(&variable)
if err != nil {
return nil, err
} else if !has {
return nil, fmt.Errorf("variable with id %d: %w", variableID, util.ErrNotExist)
}
return &variable, nil
func FindVariables(ctx context.Context, opts FindVariablesOpts) ([]*ActionVariable, error) {
return db.Find[ActionVariable](ctx, opts)
}
func UpdateVariable(ctx context.Context, variable *ActionVariable) (bool, error) {
@@ -82,3 +81,42 @@ func UpdateVariable(ctx context.Context, variable *ActionVariable) (bool, error)
})
return count != 0, err
}
func DeleteVariable(ctx context.Context, id int64) error {
if _, err := db.DeleteByID[ActionVariable](ctx, id); err != nil {
return err
}
return nil
}
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
}
+66 -62
View File
@@ -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 {
if err := a.LoadIssue(ctx); err != nil || a.Issue == nil {
return "#"
}
// Return link to issue
issueIDString := a.GetIssueInfos()[0]
issueID, err := strconv.ParseInt(issueIDString, 10, 64)
if err != nil {
if err := a.Issue.LoadRepo(ctx); err != nil {
return "#"
}
issue, err := issues_model.GetIssueByID(ctx, issueID)
if err != nil {
return "#"
}
if err = 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 {
if err := a.LoadIssue(ctx); err != nil || a.Issue == nil {
return "#"
}
// Return link to issue
issueIDString := a.GetIssueInfos()[0]
issueID, err := strconv.ParseInt(issueIDString, 10, 64)
if err != nil {
if err := a.Issue.LoadRepo(ctx); err != nil {
return "#"
}
issue, err := issues_model.GetIssueByID(ctx, issueID)
if err != nil {
return "#"
}
if err = 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>"
}
return issue.Title
if a.Issue == nil {
return "<Issue not found>"
}
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>"
}
return issue.Content
if a.Issue == nil {
return "<Content not found>"
}
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)
}
+114 -22
View File
@@ -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
}
return actions.loadRepoOwner(ctx, userMap)
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)
}
}
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
}
-457
View File
@@ -12,12 +12,8 @@ import (
"code.gitea.io/gitea/models/db"
issues_model "code.gitea.io/gitea/models/issues"
"code.gitea.io/gitea/models/organization"
access_model "code.gitea.io/gitea/models/perm/access"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/container"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/timeutil"
@@ -79,53 +75,6 @@ func init() {
db.RegisterModel(new(Notification))
}
// FindNotificationOptions represent the filters for notifications. If an ID is 0 it will be ignored.
type FindNotificationOptions struct {
db.ListOptions
UserID int64
RepoID int64
IssueID int64
Status []NotificationStatus
Source []NotificationSource
UpdatedAfterUnix int64
UpdatedBeforeUnix int64
}
// ToCond will convert each condition into a xorm-Cond
func (opts FindNotificationOptions) ToConds() builder.Cond {
cond := builder.NewCond()
if opts.UserID != 0 {
cond = cond.And(builder.Eq{"notification.user_id": opts.UserID})
}
if opts.RepoID != 0 {
cond = cond.And(builder.Eq{"notification.repo_id": opts.RepoID})
}
if opts.IssueID != 0 {
cond = cond.And(builder.Eq{"notification.issue_id": opts.IssueID})
}
if len(opts.Status) > 0 {
if len(opts.Status) == 1 {
cond = cond.And(builder.Eq{"notification.status": opts.Status[0]})
} else {
cond = cond.And(builder.In("notification.status", opts.Status))
}
}
if len(opts.Source) > 0 {
cond = cond.And(builder.In("notification.source", opts.Source))
}
if opts.UpdatedAfterUnix != 0 {
cond = cond.And(builder.Gte{"notification.updated_unix": opts.UpdatedAfterUnix})
}
if opts.UpdatedBeforeUnix != 0 {
cond = cond.And(builder.Lte{"notification.updated_unix": opts.UpdatedBeforeUnix})
}
return cond
}
func (opts FindNotificationOptions) ToOrders() string {
return "notification.updated_unix DESC"
}
// CreateRepoTransferNotification creates notification for the user a repository was transferred to
func CreateRepoTransferNotification(ctx context.Context, doer, newOwner *user_model.User, repo *repo_model.Repository) error {
return db.WithTx(ctx, func(ctx context.Context) error {
@@ -159,109 +108,6 @@ func CreateRepoTransferNotification(ctx context.Context, doer, newOwner *user_mo
})
}
// CreateOrUpdateIssueNotifications creates an issue notification
// for each watcher, or updates it if already exists
// receiverID > 0 just send to receiver, else send to all watcher
func CreateOrUpdateIssueNotifications(ctx context.Context, issueID, commentID, notificationAuthorID, receiverID int64) error {
ctx, committer, err := db.TxContext(ctx)
if err != nil {
return err
}
defer committer.Close()
if err := createOrUpdateIssueNotifications(ctx, issueID, commentID, notificationAuthorID, receiverID); err != nil {
return err
}
return committer.Commit()
}
func createOrUpdateIssueNotifications(ctx context.Context, issueID, commentID, notificationAuthorID, receiverID int64) error {
// init
var toNotify container.Set[int64]
notifications, err := db.Find[Notification](ctx, FindNotificationOptions{
IssueID: issueID,
})
if err != nil {
return err
}
issue, err := issues_model.GetIssueByID(ctx, issueID)
if err != nil {
return err
}
if receiverID > 0 {
toNotify = make(container.Set[int64], 1)
toNotify.Add(receiverID)
} else {
toNotify = make(container.Set[int64], 32)
issueWatches, err := issues_model.GetIssueWatchersIDs(ctx, issueID, true)
if err != nil {
return err
}
toNotify.AddMultiple(issueWatches...)
if !(issue.IsPull && issues_model.HasWorkInProgressPrefix(issue.Title)) {
repoWatches, err := repo_model.GetRepoWatchersIDs(ctx, issue.RepoID)
if err != nil {
return err
}
toNotify.AddMultiple(repoWatches...)
}
issueParticipants, err := issue.GetParticipantIDsByIssue(ctx)
if err != nil {
return err
}
toNotify.AddMultiple(issueParticipants...)
// dont notify user who cause notification
delete(toNotify, notificationAuthorID)
// explicit unwatch on issue
issueUnWatches, err := issues_model.GetIssueWatchersIDs(ctx, issueID, false)
if err != nil {
return err
}
for _, id := range issueUnWatches {
toNotify.Remove(id)
}
}
err = issue.LoadRepo(ctx)
if err != nil {
return err
}
// notify
for userID := range toNotify {
issue.Repo.Units = nil
user, err := user_model.GetUserByID(ctx, userID)
if err != nil {
if user_model.IsErrUserNotExist(err) {
continue
}
return err
}
if issue.IsPull && !access_model.CheckRepoUnitUser(ctx, issue.Repo, user, unit.TypePullRequests) {
continue
}
if !issue.IsPull && !access_model.CheckRepoUnitUser(ctx, issue.Repo, user, unit.TypeIssues) {
continue
}
if notificationExists(notifications, issue.ID, userID) {
if err = updateIssueNotification(ctx, userID, issue.ID, commentID, notificationAuthorID); err != nil {
return err
}
continue
}
if err = createIssueNotification(ctx, userID, issue, commentID, notificationAuthorID); err != nil {
return err
}
}
return nil
}
func createIssueNotification(ctx context.Context, userID int64, issue *issues_model.Issue, commentID, updatedByID int64) error {
notification := &Notification{
UserID: userID,
@@ -449,309 +295,6 @@ func GetUIDsAndNotificationCounts(ctx context.Context, since, until timeutil.Tim
return res, db.GetEngine(ctx).SQL(sql, since, until, NotificationStatusUnread).Find(&res)
}
// NotificationList contains a list of notifications
type NotificationList []*Notification
// LoadAttributes load Repo Issue User and Comment if not loaded
func (nl NotificationList) LoadAttributes(ctx context.Context) error {
if _, _, err := nl.LoadRepos(ctx); err != nil {
return err
}
if _, err := nl.LoadIssues(ctx); err != nil {
return err
}
if _, err := nl.LoadUsers(ctx); err != nil {
return err
}
if _, err := nl.LoadComments(ctx); err != nil {
return err
}
return nil
}
func (nl NotificationList) getPendingRepoIDs() []int64 {
ids := make(container.Set[int64], len(nl))
for _, notification := range nl {
if notification.Repository != nil {
continue
}
ids.Add(notification.RepoID)
}
return ids.Values()
}
// LoadRepos loads repositories from database
func (nl NotificationList) LoadRepos(ctx context.Context) (repo_model.RepositoryList, []int, error) {
if len(nl) == 0 {
return repo_model.RepositoryList{}, []int{}, nil
}
repoIDs := nl.getPendingRepoIDs()
repos := make(map[int64]*repo_model.Repository, len(repoIDs))
left := len(repoIDs)
for left > 0 {
limit := db.DefaultMaxInSize
if left < limit {
limit = left
}
rows, err := db.GetEngine(ctx).
In("id", repoIDs[:limit]).
Rows(new(repo_model.Repository))
if err != nil {
return nil, nil, err
}
for rows.Next() {
var repo repo_model.Repository
err = rows.Scan(&repo)
if err != nil {
rows.Close()
return nil, nil, err
}
repos[repo.ID] = &repo
}
_ = rows.Close()
left -= limit
repoIDs = repoIDs[limit:]
}
failed := []int{}
reposList := make(repo_model.RepositoryList, 0, len(repoIDs))
for i, notification := range nl {
if notification.Repository == nil {
notification.Repository = repos[notification.RepoID]
}
if notification.Repository == nil {
log.Error("Notification[%d]: RepoID: %d not found", notification.ID, notification.RepoID)
failed = append(failed, i)
continue
}
var found bool
for _, r := range reposList {
if r.ID == notification.RepoID {
found = true
break
}
}
if !found {
reposList = append(reposList, notification.Repository)
}
}
return reposList, failed, nil
}
func (nl NotificationList) getPendingIssueIDs() []int64 {
ids := make(container.Set[int64], len(nl))
for _, notification := range nl {
if notification.Issue != nil {
continue
}
ids.Add(notification.IssueID)
}
return ids.Values()
}
// LoadIssues loads issues from database
func (nl NotificationList) LoadIssues(ctx context.Context) ([]int, error) {
if len(nl) == 0 {
return []int{}, nil
}
issueIDs := nl.getPendingIssueIDs()
issues := make(map[int64]*issues_model.Issue, len(issueIDs))
left := len(issueIDs)
for left > 0 {
limit := db.DefaultMaxInSize
if left < limit {
limit = left
}
rows, err := db.GetEngine(ctx).
In("id", issueIDs[:limit]).
Rows(new(issues_model.Issue))
if err != nil {
return nil, err
}
for rows.Next() {
var issue issues_model.Issue
err = rows.Scan(&issue)
if err != nil {
rows.Close()
return nil, err
}
issues[issue.ID] = &issue
}
_ = rows.Close()
left -= limit
issueIDs = issueIDs[limit:]
}
failures := []int{}
for i, notification := range nl {
if notification.Issue == nil {
notification.Issue = issues[notification.IssueID]
if notification.Issue == nil {
if notification.IssueID != 0 {
log.Error("Notification[%d]: IssueID: %d Not Found", notification.ID, notification.IssueID)
failures = append(failures, i)
}
continue
}
notification.Issue.Repo = notification.Repository
}
}
return failures, nil
}
// Without returns the notification list without the failures
func (nl NotificationList) Without(failures []int) NotificationList {
if len(failures) == 0 {
return nl
}
remaining := make([]*Notification, 0, len(nl))
last := -1
var i int
for _, i = range failures {
remaining = append(remaining, nl[last+1:i]...)
last = i
}
if len(nl) > i {
remaining = append(remaining, nl[i+1:]...)
}
return remaining
}
func (nl NotificationList) getPendingCommentIDs() []int64 {
ids := make(container.Set[int64], len(nl))
for _, notification := range nl {
if notification.CommentID == 0 || notification.Comment != nil {
continue
}
ids.Add(notification.CommentID)
}
return ids.Values()
}
func (nl NotificationList) getUserIDs() []int64 {
ids := make(container.Set[int64], len(nl))
for _, notification := range nl {
if notification.UserID == 0 || notification.User != nil {
continue
}
ids.Add(notification.UserID)
}
return ids.Values()
}
// LoadUsers loads users from database
func (nl NotificationList) LoadUsers(ctx context.Context) ([]int, error) {
if len(nl) == 0 {
return []int{}, nil
}
userIDs := nl.getUserIDs()
users := make(map[int64]*user_model.User, len(userIDs))
left := len(userIDs)
for left > 0 {
limit := db.DefaultMaxInSize
if left < limit {
limit = left
}
rows, err := db.GetEngine(ctx).
In("id", userIDs[:limit]).
Rows(new(user_model.User))
if err != nil {
return nil, err
}
for rows.Next() {
var user user_model.User
err = rows.Scan(&user)
if err != nil {
rows.Close()
return nil, err
}
users[user.ID] = &user
}
_ = rows.Close()
left -= limit
userIDs = userIDs[limit:]
}
failures := []int{}
for i, notification := range nl {
if notification.UserID > 0 && notification.User == nil && users[notification.UserID] != nil {
notification.User = users[notification.UserID]
if notification.User == nil {
log.Error("Notification[%d]: UserID[%d] failed to load", notification.ID, notification.UserID)
failures = append(failures, i)
continue
}
}
}
return failures, nil
}
// LoadComments loads comments from database
func (nl NotificationList) LoadComments(ctx context.Context) ([]int, error) {
if len(nl) == 0 {
return []int{}, nil
}
commentIDs := nl.getPendingCommentIDs()
comments := make(map[int64]*issues_model.Comment, len(commentIDs))
left := len(commentIDs)
for left > 0 {
limit := db.DefaultMaxInSize
if left < limit {
limit = left
}
rows, err := db.GetEngine(ctx).
In("id", commentIDs[:limit]).
Rows(new(issues_model.Comment))
if err != nil {
return nil, err
}
for rows.Next() {
var comment issues_model.Comment
err = rows.Scan(&comment)
if err != nil {
rows.Close()
return nil, err
}
comments[comment.ID] = &comment
}
_ = rows.Close()
left -= limit
commentIDs = commentIDs[limit:]
}
failures := []int{}
for i, notification := range nl {
if notification.CommentID > 0 && notification.Comment == nil && comments[notification.CommentID] != nil {
notification.Comment = comments[notification.CommentID]
if notification.Comment == nil {
log.Error("Notification[%d]: CommentID[%d] failed to load", notification.ID, notification.CommentID)
failures = append(failures, i)
continue
}
notification.Comment.Issue = notification.Issue
}
}
return failures, nil
}
// SetIssueReadBy sets issue to be read by given user.
func SetIssueReadBy(ctx context.Context, issueID, userID int64) error {
if err := issues_model.UpdateIssueUserByRead(ctx, userID, issueID); err != nil {
+501
View File
@@ -0,0 +1,501 @@
// Copyright 2024 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package activities
import (
"context"
"code.gitea.io/gitea/models/db"
issues_model "code.gitea.io/gitea/models/issues"
access_model "code.gitea.io/gitea/models/perm/access"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/container"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/util"
"xorm.io/builder"
)
// FindNotificationOptions represent the filters for notifications. If an ID is 0 it will be ignored.
type FindNotificationOptions struct {
db.ListOptions
UserID int64
RepoID int64
IssueID int64
Status []NotificationStatus
Source []NotificationSource
UpdatedAfterUnix int64
UpdatedBeforeUnix int64
}
// ToCond will convert each condition into a xorm-Cond
func (opts FindNotificationOptions) ToConds() builder.Cond {
cond := builder.NewCond()
if opts.UserID != 0 {
cond = cond.And(builder.Eq{"notification.user_id": opts.UserID})
}
if opts.RepoID != 0 {
cond = cond.And(builder.Eq{"notification.repo_id": opts.RepoID})
}
if opts.IssueID != 0 {
cond = cond.And(builder.Eq{"notification.issue_id": opts.IssueID})
}
if len(opts.Status) > 0 {
if len(opts.Status) == 1 {
cond = cond.And(builder.Eq{"notification.status": opts.Status[0]})
} else {
cond = cond.And(builder.In("notification.status", opts.Status))
}
}
if len(opts.Source) > 0 {
cond = cond.And(builder.In("notification.source", opts.Source))
}
if opts.UpdatedAfterUnix != 0 {
cond = cond.And(builder.Gte{"notification.updated_unix": opts.UpdatedAfterUnix})
}
if opts.UpdatedBeforeUnix != 0 {
cond = cond.And(builder.Lte{"notification.updated_unix": opts.UpdatedBeforeUnix})
}
return cond
}
func (opts FindNotificationOptions) ToOrders() string {
return "notification.updated_unix DESC"
}
// CreateOrUpdateIssueNotifications creates an issue notification
// for each watcher, or updates it if already exists
// receiverID > 0 just send to receiver, else send to all watcher
func CreateOrUpdateIssueNotifications(ctx context.Context, issueID, commentID, notificationAuthorID, receiverID int64) error {
ctx, committer, err := db.TxContext(ctx)
if err != nil {
return err
}
defer committer.Close()
if err := createOrUpdateIssueNotifications(ctx, issueID, commentID, notificationAuthorID, receiverID); err != nil {
return err
}
return committer.Commit()
}
func createOrUpdateIssueNotifications(ctx context.Context, issueID, commentID, notificationAuthorID, receiverID int64) error {
// init
var toNotify container.Set[int64]
notifications, err := db.Find[Notification](ctx, FindNotificationOptions{
IssueID: issueID,
})
if err != nil {
return err
}
issue, err := issues_model.GetIssueByID(ctx, issueID)
if err != nil {
return err
}
if receiverID > 0 {
toNotify = make(container.Set[int64], 1)
toNotify.Add(receiverID)
} else {
toNotify = make(container.Set[int64], 32)
issueWatches, err := issues_model.GetIssueWatchersIDs(ctx, issueID, true)
if err != nil {
return err
}
toNotify.AddMultiple(issueWatches...)
if !(issue.IsPull && issues_model.HasWorkInProgressPrefix(issue.Title)) {
repoWatches, err := repo_model.GetRepoWatchersIDs(ctx, issue.RepoID)
if err != nil {
return err
}
toNotify.AddMultiple(repoWatches...)
}
issueParticipants, err := issue.GetParticipantIDsByIssue(ctx)
if err != nil {
return err
}
toNotify.AddMultiple(issueParticipants...)
// dont notify user who cause notification
delete(toNotify, notificationAuthorID)
// explicit unwatch on issue
issueUnWatches, err := issues_model.GetIssueWatchersIDs(ctx, issueID, false)
if err != nil {
return err
}
for _, id := range issueUnWatches {
toNotify.Remove(id)
}
}
err = issue.LoadRepo(ctx)
if err != nil {
return err
}
// notify
for userID := range toNotify {
issue.Repo.Units = nil
user, err := user_model.GetUserByID(ctx, userID)
if err != nil {
if user_model.IsErrUserNotExist(err) {
continue
}
return err
}
if issue.IsPull && !access_model.CheckRepoUnitUser(ctx, issue.Repo, user, unit.TypePullRequests) {
continue
}
if !issue.IsPull && !access_model.CheckRepoUnitUser(ctx, issue.Repo, user, unit.TypeIssues) {
continue
}
if notificationExists(notifications, issue.ID, userID) {
if err = updateIssueNotification(ctx, userID, issue.ID, commentID, notificationAuthorID); err != nil {
return err
}
continue
}
if err = createIssueNotification(ctx, userID, issue, commentID, notificationAuthorID); err != nil {
return err
}
}
return nil
}
// NotificationList contains a list of notifications
type NotificationList []*Notification
// LoadAttributes load Repo Issue User and Comment if not loaded
func (nl NotificationList) LoadAttributes(ctx context.Context) error {
if _, _, err := nl.LoadRepos(ctx); err != nil {
return err
}
if _, err := nl.LoadIssues(ctx); err != nil {
return err
}
if _, err := nl.LoadUsers(ctx); err != nil {
return err
}
if _, err := nl.LoadComments(ctx); err != nil {
return err
}
return nil
}
func (nl NotificationList) getPendingRepoIDs() []int64 {
ids := make(container.Set[int64], len(nl))
for _, notification := range nl {
if notification.Repository != nil {
continue
}
ids.Add(notification.RepoID)
}
return ids.Values()
}
// LoadRepos loads repositories from database
func (nl NotificationList) LoadRepos(ctx context.Context) (repo_model.RepositoryList, []int, error) {
if len(nl) == 0 {
return repo_model.RepositoryList{}, []int{}, nil
}
repoIDs := nl.getPendingRepoIDs()
repos := make(map[int64]*repo_model.Repository, len(repoIDs))
left := len(repoIDs)
for left > 0 {
limit := db.DefaultMaxInSize
if left < limit {
limit = left
}
rows, err := db.GetEngine(ctx).
In("id", repoIDs[:limit]).
Rows(new(repo_model.Repository))
if err != nil {
return nil, nil, err
}
for rows.Next() {
var repo repo_model.Repository
err = rows.Scan(&repo)
if err != nil {
rows.Close()
return nil, nil, err
}
repos[repo.ID] = &repo
}
_ = rows.Close()
left -= limit
repoIDs = repoIDs[limit:]
}
failed := []int{}
reposList := make(repo_model.RepositoryList, 0, len(repoIDs))
for i, notification := range nl {
if notification.Repository == nil {
notification.Repository = repos[notification.RepoID]
}
if notification.Repository == nil {
log.Error("Notification[%d]: RepoID: %d not found", notification.ID, notification.RepoID)
failed = append(failed, i)
continue
}
var found bool
for _, r := range reposList {
if r.ID == notification.RepoID {
found = true
break
}
}
if !found {
reposList = append(reposList, notification.Repository)
}
}
return reposList, failed, nil
}
func (nl NotificationList) getPendingIssueIDs() []int64 {
ids := make(container.Set[int64], len(nl))
for _, notification := range nl {
if notification.Issue != nil {
continue
}
ids.Add(notification.IssueID)
}
return ids.Values()
}
// LoadIssues loads issues from database
func (nl NotificationList) LoadIssues(ctx context.Context) ([]int, error) {
if len(nl) == 0 {
return []int{}, nil
}
issueIDs := nl.getPendingIssueIDs()
issues := make(map[int64]*issues_model.Issue, len(issueIDs))
left := len(issueIDs)
for left > 0 {
limit := db.DefaultMaxInSize
if left < limit {
limit = left
}
rows, err := db.GetEngine(ctx).
In("id", issueIDs[:limit]).
Rows(new(issues_model.Issue))
if err != nil {
return nil, err
}
for rows.Next() {
var issue issues_model.Issue
err = rows.Scan(&issue)
if err != nil {
rows.Close()
return nil, err
}
issues[issue.ID] = &issue
}
_ = rows.Close()
left -= limit
issueIDs = issueIDs[limit:]
}
failures := []int{}
for i, notification := range nl {
if notification.Issue == nil {
notification.Issue = issues[notification.IssueID]
if notification.Issue == nil {
if notification.IssueID != 0 {
log.Error("Notification[%d]: IssueID: %d Not Found", notification.ID, notification.IssueID)
failures = append(failures, i)
}
continue
}
notification.Issue.Repo = notification.Repository
}
}
return failures, nil
}
// Without returns the notification list without the failures
func (nl NotificationList) Without(failures []int) NotificationList {
if len(failures) == 0 {
return nl
}
remaining := make([]*Notification, 0, len(nl))
last := -1
var i int
for _, i = range failures {
remaining = append(remaining, nl[last+1:i]...)
last = i
}
if len(nl) > i {
remaining = append(remaining, nl[i+1:]...)
}
return remaining
}
func (nl NotificationList) getPendingCommentIDs() []int64 {
ids := make(container.Set[int64], len(nl))
for _, notification := range nl {
if notification.CommentID == 0 || notification.Comment != nil {
continue
}
ids.Add(notification.CommentID)
}
return ids.Values()
}
func (nl NotificationList) getUserIDs() []int64 {
ids := make(container.Set[int64], len(nl))
for _, notification := range nl {
if notification.UserID == 0 || notification.User != nil {
continue
}
ids.Add(notification.UserID)
}
return ids.Values()
}
// LoadUsers loads users from database
func (nl NotificationList) LoadUsers(ctx context.Context) ([]int, error) {
if len(nl) == 0 {
return []int{}, nil
}
userIDs := nl.getUserIDs()
users := make(map[int64]*user_model.User, len(userIDs))
left := len(userIDs)
for left > 0 {
limit := db.DefaultMaxInSize
if left < limit {
limit = left
}
rows, err := db.GetEngine(ctx).
In("id", userIDs[:limit]).
Rows(new(user_model.User))
if err != nil {
return nil, err
}
for rows.Next() {
var user user_model.User
err = rows.Scan(&user)
if err != nil {
rows.Close()
return nil, err
}
users[user.ID] = &user
}
_ = rows.Close()
left -= limit
userIDs = userIDs[limit:]
}
failures := []int{}
for i, notification := range nl {
if notification.UserID > 0 && notification.User == nil && users[notification.UserID] != nil {
notification.User = users[notification.UserID]
if notification.User == nil {
log.Error("Notification[%d]: UserID[%d] failed to load", notification.ID, notification.UserID)
failures = append(failures, i)
continue
}
}
}
return failures, nil
}
// LoadComments loads comments from database
func (nl NotificationList) LoadComments(ctx context.Context) ([]int, error) {
if len(nl) == 0 {
return []int{}, nil
}
commentIDs := nl.getPendingCommentIDs()
comments := make(map[int64]*issues_model.Comment, len(commentIDs))
left := len(commentIDs)
for left > 0 {
limit := db.DefaultMaxInSize
if left < limit {
limit = left
}
rows, err := db.GetEngine(ctx).
In("id", commentIDs[:limit]).
Rows(new(issues_model.Comment))
if err != nil {
return nil, err
}
for rows.Next() {
var comment issues_model.Comment
err = rows.Scan(&comment)
if err != nil {
rows.Close()
return nil, err
}
comments[comment.ID] = &comment
}
_ = rows.Close()
left -= limit
commentIDs = commentIDs[limit:]
}
failures := []int{}
for i, notification := range nl {
if notification.CommentID > 0 && notification.Comment == nil && comments[notification.CommentID] != nil {
notification.Comment = comments[notification.CommentID]
if notification.Comment == nil {
log.Error("Notification[%d]: CommentID[%d] failed to load", notification.ID, notification.CommentID)
failures = append(failures, i)
continue
}
notification.Comment.Issue = notification.Issue
}
}
return failures, nil
}
// LoadIssuePullRequests loads all issues' pull requests if possible
func (nl NotificationList) LoadIssuePullRequests(ctx context.Context) error {
issues := make(map[int64]*issues_model.Issue, len(nl))
for _, notification := range nl {
if notification.Issue != nil && notification.Issue.IsPull && notification.Issue.PullRequest == nil {
issues[notification.Issue.ID] = notification.Issue
}
}
if len(issues) == 0 {
return nil
}
pulls, err := issues_model.GetPullRequestByIssueIDs(ctx, util.KeysOfMap(issues))
if err != nil {
return err
}
for _, pull := range pulls {
if issue := issues[pull.IssueID]; issue != nil {
issue.PullRequest = pull
issue.PullRequest.Issue = issue
}
}
return nil
}
+6 -1
View File
@@ -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
@@ -139,13 +139,7 @@ func ParseCommitWithSignature(ctx context.Context, c *git.Commit) *CommitVerific
}
}
keyID := ""
if sig.IssuerKeyId != nil && (*sig.IssuerKeyId) != 0 {
keyID = fmt.Sprintf("%X", *sig.IssuerKeyId)
}
if keyID == "" && sig.IssuerFingerprint != nil && len(sig.IssuerFingerprint) > 0 {
keyID = fmt.Sprintf("%X", sig.IssuerFingerprint[12:20])
}
keyID := tryGetKeyIDFromSignature(sig)
defaultReason := NoKeyFound
// First check if the sig has a keyID and if so just look at that
+10
View File
@@ -134,3 +134,13 @@ func extractSignature(s string) (*packet.Signature, error) {
}
return sig, nil
}
func tryGetKeyIDFromSignature(sig *packet.Signature) string {
if sig.IssuerKeyId != nil && (*sig.IssuerKeyId) != 0 {
return fmt.Sprintf("%016X", *sig.IssuerKeyId)
}
if sig.IssuerFingerprint != nil && len(sig.IssuerFingerprint) > 0 {
return fmt.Sprintf("%016X", sig.IssuerFingerprint[12:20])
}
return ""
}
+12
View File
@@ -11,7 +11,9 @@ import (
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
"github.com/keybase/go-crypto/openpgp/packet"
"github.com/stretchr/testify/assert"
)
@@ -391,3 +393,13 @@ epiDVQ==
assert.Equal(t, time.Unix(1586105389, 0), expire)
}
}
func TestTryGetKeyIDFromSignature(t *testing.T) {
assert.Empty(t, tryGetKeyIDFromSignature(&packet.Signature{}))
assert.Equal(t, "038D1A3EADDBEA9C", tryGetKeyIDFromSignature(&packet.Signature{
IssuerKeyId: util.ToPointer(uint64(0x38D1A3EADDBEA9C)),
}))
assert.Equal(t, "038D1A3EADDBEA9C", tryGetKeyIDFromSignature(&packet.Signature{
IssuerFingerprint: []uint8{0xb, 0x23, 0x24, 0xc7, 0xe6, 0xfe, 0x4f, 0x3a, 0x6, 0x26, 0xc1, 0x21, 0x3, 0x8d, 0x1a, 0x3e, 0xad, 0xdb, 0xea, 0x9c},
}))
}
+4
View File
@@ -46,6 +46,10 @@ func VerifyGPGKey(ctx context.Context, ownerID int64, keyID, token, signature st
return "", ErrGPGKeyNotExist{}
}
if err := key.LoadSubKeys(ctx); err != nil {
return "", err
}
sig, err := extractSignature(signature)
if err != nil {
return "", ErrGPGInvalidTokenSignature{
+11 -62
View File
@@ -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) {
@@ -193,6 +139,8 @@ func RegeneratePublicKeys(ctx context.Context, t io.StringWriter) error {
if err != nil {
return err
}
defer f.Close()
scanner := bufio.NewScanner(f)
for scanner.Scan() {
line := scanner.Text()
@@ -202,11 +150,12 @@ func RegeneratePublicKeys(ctx context.Context, t io.StringWriter) error {
}
_, err = t.WriteString(line + "\n")
if err != nil {
f.Close()
return err
}
}
f.Close()
if err = scanner.Err(); err != nil {
return fmt.Errorf("RegeneratePublicKeys scan: %w", err)
}
}
return nil
}
-40
View File
@@ -9,51 +9,11 @@ import (
"strings"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/perm"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
)
// AddPrincipalKey adds new principal to database and authorized_principals file.
func AddPrincipalKey(ctx context.Context, ownerID int64, content string, authSourceID int64) (*PublicKey, error) {
dbCtx, committer, err := db.TxContext(ctx)
if err != nil {
return nil, err
}
defer committer.Close()
// Principals cannot be duplicated.
has, err := db.GetEngine(dbCtx).
Where("content = ? AND type = ?", content, KeyTypePrincipal).
Get(new(PublicKey))
if err != nil {
return nil, err
} else if has {
return nil, ErrKeyAlreadyExist{0, "", content}
}
key := &PublicKey{
OwnerID: ownerID,
Name: content,
Content: content,
Mode: perm.AccessModeWrite,
Type: KeyTypePrincipal,
LoginSourceID: authSourceID,
}
if err = db.Insert(dbCtx, key); err != nil {
return nil, fmt.Errorf("addKey: %w", err)
}
if err = committer.Commit(); err != nil {
return nil, err
}
committer.Close()
return key, RewriteAllPrincipalKeys(ctx)
}
// CheckPrincipalKeyString strips spaces and returns an error if the given principal contains newlines
func CheckPrincipalKeyString(ctx context.Context, user *user_model.User, content string) (_ string, err error) {
if setting.SSH.Disabled {
+5 -4
View File
@@ -11,6 +11,7 @@ import (
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
@@ -243,14 +244,14 @@ func CreateSource(ctx context.Context, source *Source) error {
type FindSourcesOptions struct {
db.ListOptions
IsActive util.OptionalBool
IsActive optional.Option[bool]
LoginType Type
}
func (opts FindSourcesOptions) ToConds() builder.Cond {
conds := builder.NewCond()
if !opts.IsActive.IsNone() {
conds = conds.And(builder.Eq{"is_active": opts.IsActive.IsTrue()})
if opts.IsActive.Has() {
conds = conds.And(builder.Eq{"is_active": opts.IsActive.Value()})
}
if opts.LoginType != NoType {
conds = conds.And(builder.Eq{"`type`": opts.LoginType})
@@ -262,7 +263,7 @@ func (opts FindSourcesOptions) ToConds() builder.Cond {
// source of type LoginSSPI
func IsSSPIEnabled(ctx context.Context) bool {
exist, err := db.Exist[Source](ctx, FindSourcesOptions{
IsActive: util.OptionalBoolTrue,
IsActive: optional.Some(true),
LoginType: SSPI,
}.ToConds())
if err != nil {
+1 -1
View File
@@ -6,6 +6,7 @@ package auth
import (
"context"
"crypto/md5"
"crypto/sha256"
"crypto/subtle"
"encoding/base32"
"encoding/base64"
@@ -18,7 +19,6 @@ import (
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
"github.com/minio/sha256-simd"
"github.com/pquerna/otp/totp"
"golang.org/x/crypto/pbkdf2"
)
+1 -1
View File
@@ -24,7 +24,7 @@ import (
const (
// DefaultAvatarClass is the default class of a rendered avatar
DefaultAvatarClass = "ui avatar gt-vm"
DefaultAvatarClass = "ui avatar tw-align-middle"
// DefaultAvatarPixelSize is the default size in pixels of a rendered avatar
DefaultAvatarPixelSize = 28
)
+1 -2
View File
@@ -166,8 +166,7 @@ func preprocessDatabaseCollation(x *xorm.Engine) {
// try to alter database collation to expected if the database is empty, it might fail in some cases (and it isn't necessary to succeed)
// at the moment, there is no "altering" solution for MSSQL, site admin should manually change the database collation
// and there is a bug https://github.com/go-testfixtures/testfixtures/pull/182 mssql: Invalid object name 'information_schema.tables'.
if !r.CollationEquals(r.DatabaseCollation, r.ExpectedCollation) && r.ExistingTableNumber == 0 && x.Dialect().URI().DBType == schemas.MYSQL {
if !r.CollationEquals(r.DatabaseCollation, r.ExpectedCollation) && r.ExistingTableNumber == 0 {
if err = alterDatabaseCollation(x, r.ExpectedCollation); err != nil {
log.Error("Failed to change database collation to %q: %v", r.ExpectedCollation, err)
} else {
+10
View File
@@ -120,6 +120,16 @@ func (c *halfCommitter) Close() error {
// TxContext represents a transaction Context,
// it will reuse the existing transaction in the parent context or create a new one.
// Some tips to use:
//
// 1 It's always recommended to use `WithTx` in new code instead of `TxContext`, since `WithTx` will handle the transaction automatically.
// 2. To maintain the old code which uses `TxContext`:
// a. Always call `Close()` before returning regardless of whether `Commit()` has been called.
// b. Always call `Commit()` before returning if there are no errors, even if the code did not change any data.
// c. Remember the `Committer` will be a halfCommitter when a transaction is being reused.
// So calling `Commit()` will do nothing, but calling `Close()` without calling `Commit()` will rollback the transaction.
// And all operations submitted by the caller stack will be rollbacked as well, not only the operations in the current function.
// d. It doesn't mean rollback is forbidden, but always do it only when there is an error, and you do want to rollback.
func TxContext(parentCtx context.Context) (*Context, Committer, error) {
if sess, ok := inTransaction(parentCtx); ok {
return newContext(parentCtx, sess, true), &halfCommitter{committer: sess}, nil
+31
View File
@@ -11,10 +11,13 @@ import (
"io"
"reflect"
"strings"
"time"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"xorm.io/xorm"
"xorm.io/xorm/contexts"
"xorm.io/xorm/names"
"xorm.io/xorm/schemas"
@@ -143,6 +146,13 @@ func InitEngine(ctx context.Context) error {
xormEngine.SetConnMaxLifetime(setting.Database.ConnMaxLifetime)
xormEngine.SetDefaultContext(ctx)
if setting.Database.SlowQueryThreshold > 0 {
xormEngine.AddHook(&SlowQueryHook{
Threshold: setting.Database.SlowQueryThreshold,
Logger: log.GetLogger("xorm"),
})
}
SetDefaultEngine(ctx, xormEngine)
return nil
}
@@ -298,3 +308,24 @@ func SetLogSQL(ctx context.Context, on bool) {
sess.Engine().ShowSQL(on)
}
}
type SlowQueryHook struct {
Threshold time.Duration
Logger log.Logger
}
var _ contexts.Hook = &SlowQueryHook{}
func (SlowQueryHook) BeforeProcess(c *contexts.ContextHook) (context.Context, error) {
return c.Ctx, nil
}
func (h *SlowQueryHook) AfterProcess(c *contexts.ContextHook) error {
if c.ExecuteTime >= h.Threshold {
// 8 is the amount of skips passed to runtime.Caller, so that in the log the correct function
// is being displayed (the function that ultimately wants to execute the query in the code)
// instead of the function of the slow query hook being called.
h.Logger.Log(8, log.WARN, "[Slow SQL Query] %s %v - %v", c.SQL, c.Args, c.ExecuteTime)
}
return nil
}
+52 -16
View File
@@ -42,96 +42,132 @@
-
id: 8
user_id: 15
user_id: 10
repo_id: 21
mode: 2
-
id: 9
user_id: 15
repo_id: 22
user_id: 10
repo_id: 32
mode: 2
-
id: 10
user_id: 15
repo_id: 21
mode: 2
-
id: 11
user_id: 15
repo_id: 22
mode: 2
-
id: 12
user_id: 15
repo_id: 23
mode: 4
-
id: 11
id: 13
user_id: 15
repo_id: 24
mode: 4
-
id: 12
id: 14
user_id: 15
repo_id: 32
mode: 2
-
id: 13
id: 15
user_id: 18
repo_id: 21
mode: 2
-
id: 14
id: 16
user_id: 18
repo_id: 22
mode: 2
-
id: 15
id: 17
user_id: 18
repo_id: 23
mode: 4
-
id: 16
id: 18
user_id: 18
repo_id: 24
mode: 4
-
id: 17
id: 19
user_id: 20
repo_id: 24
mode: 1
-
id: 18
id: 20
user_id: 20
repo_id: 27
mode: 4
-
id: 19
id: 21
user_id: 20
repo_id: 28
mode: 4
-
id: 20
id: 22
user_id: 29
repo_id: 4
mode: 2
-
id: 21
id: 23
user_id: 29
repo_id: 24
mode: 1
-
id: 22
id: 24
user_id: 31
repo_id: 27
mode: 4
-
id: 23
id: 25
user_id: 31
repo_id: 28
mode: 4
-
id: 26
user_id: 38
repo_id: 60
mode: 2
-
id: 27
user_id: 38
repo_id: 61
mode: 1
-
id: 28
user_id: 39
repo_id: 61
mode: 1
-
id: 29
user_id: 40
repo_id: 61
mode: 4
+19
View File
@@ -17,3 +17,22 @@
updated: 1683636626
need_approval: 0
approved_by: 0
-
id: 792
title: "update actions"
repo_id: 4
owner_id: 1
workflow_id: "artifact.yaml"
index: 188
trigger_user_id: 1
ref: "refs/heads/master"
commit_sha: "c2d72f548424103f01ee1dc02889c1e2bff816b0"
event: "push"
is_fork_pull_request: 0
status: 1
started: 1683636528
stopped: 1683636626
created: 1683636108
updated: 1683636626
need_approval: 0
approved_by: 0
+14
View File
@@ -12,3 +12,17 @@
status: 1
started: 1683636528
stopped: 1683636626
-
id: 193
run_id: 792
repo_id: 4
owner_id: 1
commit_sha: c2d72f548424103f01ee1dc02889c1e2bff816b0
is_fork_pull_request: 0
name: job_2
attempt: 1
job_id: job_2
task_id: 48
status: 1
started: 1683636528
stopped: 1683636626
+20
View File
@@ -18,3 +18,23 @@
log_length: 707
log_size: 90179
log_expired: 0
-
id: 48
job_id: 193
attempt: 1
runner_id: 1
status: 6 # 6 is the status code for "running", running task can upload artifacts
started: 1683636528
stopped: 1683636626
repo_id: 4
owner_id: 1
commit_sha: c2d72f548424103f01ee1dc02889c1e2bff816b0
is_fork_pull_request: 0
token_hash: ffffcfffffffbffffffffffffffffefffffffafffffffffffffffffffffffffffffdffffffffffffffffffffffffffffffff
token_salt: ffffffffff
token_last_eight: ffffffff
log_filename: artifact-test2/2f/47.log
log_in_storage: 1
log_length: 707
log_size: 90179
log_expired: 0
+18
View File
@@ -45,3 +45,21 @@
repo_id: 22
user_id: 18
mode: 2 # write
-
id: 9
repo_id: 60
user_id: 38
mode: 2 # write
-
id: 10
repo_id: 21
user_id: 10
mode: 2 # write
-
id: 11
repo_id: 32
user_id: 10
mode: 2 # write
+8
View File
@@ -75,3 +75,11 @@
content: "comment in private pository"
created_unix: 946684811
updated_unix: 946684811
-
id: 9
type: 22 # review
poster_id: 2
issue_id: 2 # in repo_id 1
review_id: 20
created_unix: 946684810
+24
View File
@@ -293,3 +293,27 @@
lower_email: user37@example.com
is_activated: true
is_primary: true
-
id: 38
uid: 38
email: user38@example.com
lower_email: user38@example.com
is_activated: true
is_primary: true
-
id: 39
uid: 39
email: user39@example.com
lower_email: user39@example.com
is_activated: true
is_primary: true
-
id: 40
uid: 40
email: user40@example.com
lower_email: user40@example.com
is_activated: true
is_primary: true
+32
View File
@@ -3,3 +3,35 @@
hook_id: 1
uuid: uuid1
is_delivered: true
is_succeed: false
request_content: >
{
"url": "/matrix-delivered",
"http_method":"PUT",
"headers": {
"X-Head": "42"
},
"body": "{}"
}
-
id: 2
hook_id: 1
uuid: uuid2
is_delivered: false
-
id: 3
hook_id: 1
uuid: uuid3
is_delivered: true
is_succeed: true
payload_content: '{"key":"value"}' # legacy task, payload saved in payload_content (and not in request_content)
request_content: >
{
"url": "/matrix-success",
"http_method":"PUT",
"headers": {
"X-Head": "42"
}
}
+34
View File
@@ -338,3 +338,37 @@
created_unix: 978307210
updated_unix: 978307210
is_locked: false
-
id: 21
repo_id: 60
index: 1
poster_id: 39
original_author_id: 0
name: repo60 pull1
content: content for the 1st issue
milestone_id: 0
priority: 0
is_closed: false
is_pull: true
num_comments: 0
created_unix: 1707270422
updated_unix: 1707270422
is_locked: false
-
id: 22
repo_id: 61
index: 1
poster_id: 40
original_author_id: 0
name: repo61 pull1
content: content for the 1st issue
milestone_id: 0
priority: 0
is_closed: false
is_pull: true
num_comments: 0
created_unix: 1707270422
updated_unix: 1707270422
is_locked: false
+4
View File
@@ -14,3 +14,7 @@
id: 4
assignee_id: 2
issue_id: 17
-
id: 5
assignee_id: 10
issue_id: 6
+18
View File
@@ -99,3 +99,21 @@
uid: 5
org_id: 36
is_public: true
-
id: 18
uid: 38
org_id: 41
is_public: true
-
id: 19
uid: 39
org_id: 41
is_public: true
-
id: 20
uid: 40
org_id: 41
is_public: true
+24
View File
@@ -45,3 +45,27 @@
type: 2
created_unix: 1688973000
updated_unix: 1688973000
-
id: 5
title: project without default column
owner_id: 2
repo_id: 0
is_closed: false
creator_id: 2
board_type: 1
type: 2
created_unix: 1688973000
updated_unix: 1688973000
-
id: 6
title: project with multiple default columns
owner_id: 2
repo_id: 0
is_closed: false
creator_id: 2
board_type: 1
type: 2
created_unix: 1688973000
updated_unix: 1688973000
+46
View File
@@ -3,6 +3,7 @@
project_id: 1
title: To Do
creator_id: 2
default: true
created_unix: 1588117528
updated_unix: 1588117528
@@ -29,3 +30,48 @@
creator_id: 2
created_unix: 1588117528
updated_unix: 1588117528
-
id: 5
project_id: 2
title: Backlog
creator_id: 2
default: true
created_unix: 1588117528
updated_unix: 1588117528
-
id: 6
project_id: 4
title: Backlog
creator_id: 2
default: true
created_unix: 1588117528
updated_unix: 1588117528
-
id: 7
project_id: 5
title: Done
creator_id: 2
default: false
created_unix: 1588117528
updated_unix: 1588117528
-
id: 8
project_id: 6
title: Backlog
creator_id: 2
default: true
created_unix: 1588117528
updated_unix: 1588117528
-
id: 9
project_id: 6
title: Uncategorized
creator_id: 2
default: true
created_unix: 1588117528
updated_unix: 1588117528
+19
View File
@@ -9,6 +9,7 @@
head_branch: branch1
base_branch: master
merge_base: 4a357436d925b5c974181ff12a994538ddc5a269
merged_commit_id: 1a8823cd1a9549fde083f992f6b9b87a7ab74fb3
has_merged: true
merger_id: 2
@@ -98,3 +99,21 @@
index: 1
head_repo_id: 23
base_repo_id: 23
-
id: 9
type: 0 # gitea pull request
status: 2 # mergable
issue_id: 21
index: 1
head_repo_id: 60
base_repo_id: 60
-
id: 10
type: 0 # gitea pull request
status: 2 # mergable
issue_id: 22
index: 1
head_repo_id: 61
base_repo_id: 61
+16
View File
@@ -5,3 +5,19 @@
repo_id: 3
created_unix: 1553610671
updated_unix: 1553610671
-
id: 2
doer_id: 16
recipient_id: 10
repo_id: 21
created_unix: 1553610671
updated_unix: 1553610671
-
id: 3
doer_id: 3
recipient_id: 10
repo_id: 32
created_unix: 1553610671
updated_unix: 1553610671
+42 -6
View File
@@ -650,12 +650,6 @@
type: 2
created_unix: 946684810
-
id: 98
repo_id: 1
type: 8
created_unix: 946684810
-
id: 99
repo_id: 1
@@ -676,3 +670,45 @@
type: 1
config: "{}"
created_unix: 946684810
-
id: 102
repo_id: 60
type: 1
config: "{}"
created_unix: 946684810
-
id: 103
repo_id: 60
type: 2
config: "{\"EnableTimetracker\":true,\"AllowOnlyContributorsToTrackTime\":true}"
created_unix: 946684810
-
id: 104
repo_id: 60
type: 3
config: "{\"IgnoreWhitespaceConflicts\":false,\"AllowMerge\":true,\"AllowRebase\":true,\"AllowRebaseMerge\":true,\"AllowSquash\":true}"
created_unix: 946684810
-
id: 105
repo_id: 61
type: 1
config: "{}"
created_unix: 946684810
-
id: 106
repo_id: 61
type: 2
config: "{\"EnableTimetracker\":true,\"AllowOnlyContributorsToTrackTime\":true}"
created_unix: 946684810
-
id: 107
repo_id: 61
type: 3
config: "{\"IgnoreWhitespaceConflicts\":false,\"AllowMerge\":true,\"AllowRebase\":true,\"AllowRebaseMerge\":true,\"AllowSquash\":true}"
created_unix: 946684810
+66 -4
View File
@@ -614,8 +614,8 @@
owner_name: user16
lower_name: big_test_public_3
name: big_test_public_3
num_watches: 0
num_stars: 0
num_watches: 1
num_stars: 1
num_forks: 0
num_issues: 0
num_closed_issues: 0
@@ -945,8 +945,8 @@
owner_name: org3
lower_name: repo21
name: repo21
num_watches: 0
num_stars: 0
num_watches: 1
num_stars: 1
num_forks: 0
num_issues: 2
num_closed_issues: 0
@@ -1706,3 +1706,65 @@
is_private: true
status: 0
num_issues: 0
-
id: 60
owner_id: 40
owner_name: user40
lower_name: repo60
name: repo60
default_branch: main
num_watches: 0
num_stars: 0
num_forks: 0
num_issues: 0
num_closed_issues: 0
num_pulls: 1
num_closed_pulls: 0
num_milestones: 0
num_closed_milestones: 0
num_projects: 0
num_closed_projects: 0
is_private: false
is_empty: false
is_archived: false
is_mirror: false
status: 0
is_fork: false
fork_id: 0
is_template: false
template_id: 0
size: 0
is_fsck_enabled: true
close_issues_via_commit_in_any_branch: false
-
id: 61
owner_id: 41
owner_name: org41
lower_name: repo61
name: repo61
default_branch: main
num_watches: 0
num_stars: 0
num_forks: 0
num_issues: 0
num_closed_issues: 0
num_pulls: 1
num_closed_pulls: 0
num_milestones: 0
num_closed_milestones: 0
num_projects: 0
num_closed_projects: 0
is_private: false
is_empty: false
is_archived: false
is_mirror: false
status: 0
is_fork: false
fork_id: 0
is_template: false
template_id: 0
size: 0
is_fsck_enabled: true
close_issues_via_commit_in_any_branch: false
+9
View File
@@ -170,3 +170,12 @@
content: "review request for user15"
updated_unix: 946684835
created_unix: 946684835
-
id: 20
type: 22
reviewer_id: 1
issue_id: 2
content: "Review Comment"
updated_unix: 946684810
created_unix: 946684810

Some files were not shown because too many files have changed in this diff Show More