Template
1
0
Fork 0
mirror of https://codeberg.org/forgejo/forgejo synced 2024-11-21 17:34:24 +01:00

Merge branch 'forgejo' into federation-in-combination-with-whitelists-#5379

This commit is contained in:
Michael Jerger 2024-11-18 09:02:45 +01:00
commit bc088cc989
777 changed files with 26037 additions and 12103 deletions

View file

@ -137,9 +137,6 @@ code.gitea.io/gitea/modules/git
AddChangesWithArgs
CommitChanges
CommitChangesWithArgs
IsErrExecTimeout
ErrExecTimeout.Error
ErrUnsupportedVersion.Error
SetUpdateHook
openRepositoryWithDefaultContext
IsTagExist
@ -250,6 +247,9 @@ code.gitea.io/gitea/modules/translation
MockLocale.TrSize
MockLocale.PrettyNumber
code.gitea.io/gitea/modules/util
OptionalArg
code.gitea.io/gitea/modules/util/filebuffer
CreateFromReader

View file

@ -6,7 +6,7 @@
"ghcr.io/devcontainers/features/node:1": {
"version": "20"
},
"ghcr.io/devcontainers/features/git-lfs:1.2.1": {},
"ghcr.io/devcontainers/features/git-lfs:1.2.3": {},
"ghcr.io/devcontainers-contrib/features/poetry:2": {},
"ghcr.io/devcontainers/features/python:1": {
"version": "3.12"

View file

@ -1,803 +0,0 @@
root: true
reportUnusedDisableDirectives: true
ignorePatterns:
- /web_src/js/vendor
- /web_src/fomantic
- /public/assets/js
parserOptions:
sourceType: module
ecmaVersion: latest
plugins:
- "@eslint-community/eslint-plugin-eslint-comments"
- "@stylistic/eslint-plugin-js"
- eslint-plugin-array-func
- eslint-plugin-github
- eslint-plugin-i
- eslint-plugin-no-jquery
- eslint-plugin-no-use-extend-native
- eslint-plugin-regexp
- eslint-plugin-sonarjs
- eslint-plugin-unicorn
- eslint-plugin-vitest
- eslint-plugin-vitest-globals
- eslint-plugin-wc
env:
es2024: true
node: true
overrides:
- files: ["web_src/**/*"]
globals:
__webpack_public_path__: true
process: false # https://github.com/webpack/webpack/issues/15833
- files: ["web_src/**/*", "docs/**/*"]
env:
browser: true
node: false
- files: ["web_src/**/*worker.*"]
env:
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: ["*.config.*"]
rules:
i/no-unused-modules: [0]
- files: ["**/*.test.*", "web_src/js/test/setup.js"]
env:
vitest-globals/env: true
rules:
vitest/consistent-test-filename: [0]
vitest/consistent-test-it: [0]
vitest/expect-expect: [0]
vitest/max-expects: [0]
vitest/max-nested-describe: [0]
vitest/no-alias-methods: [0]
vitest/no-commented-out-tests: [0]
vitest/no-conditional-expect: [0]
vitest/no-conditional-in-test: [0]
vitest/no-conditional-tests: [0]
vitest/no-disabled-tests: [0]
vitest/no-done-callback: [0]
vitest/no-duplicate-hooks: [0]
vitest/no-focused-tests: [0]
vitest/no-hooks: [0]
vitest/no-identical-title: [2]
vitest/no-interpolation-in-snapshots: [0]
vitest/no-large-snapshots: [0]
vitest/no-mocks-import: [0]
vitest/no-restricted-matchers: [0]
vitest/no-restricted-vi-methods: [0]
vitest/no-standalone-expect: [0]
vitest/no-test-prefixes: [0]
vitest/no-test-return-statement: [0]
vitest/prefer-called-with: [0]
vitest/prefer-comparison-matcher: [0]
vitest/prefer-each: [0]
vitest/prefer-equality-matcher: [0]
vitest/prefer-expect-resolves: [0]
vitest/prefer-hooks-in-order: [0]
vitest/prefer-hooks-on-top: [2]
vitest/prefer-lowercase-title: [0]
vitest/prefer-mock-promise-shorthand: [0]
vitest/prefer-snapshot-hint: [0]
vitest/prefer-spy-on: [0]
vitest/prefer-strict-equal: [0]
vitest/prefer-to-be: [0]
vitest/prefer-to-be-falsy: [0]
vitest/prefer-to-be-object: [0]
vitest/prefer-to-be-truthy: [0]
vitest/prefer-to-contain: [0]
vitest/prefer-to-have-length: [0]
vitest/prefer-todo: [0]
vitest/require-hook: [0]
vitest/require-to-throw-message: [0]
vitest/require-top-level-describe: [0]
vitest/valid-describe-callback: [2]
vitest/valid-expect: [2]
vitest/valid-title: [2]
- files: ["web_src/js/modules/fetch.js", "web_src/js/standalone/**/*"]
rules:
no-restricted-syntax: [2, WithStatement, ForInStatement, LabeledStatement, SequenceExpression]
rules:
"@eslint-community/eslint-comments/disable-enable-pair": [2]
"@eslint-community/eslint-comments/no-aggregating-enable": [2]
"@eslint-community/eslint-comments/no-duplicate-disable": [2]
"@eslint-community/eslint-comments/no-restricted-disable": [0]
"@eslint-community/eslint-comments/no-unlimited-disable": [2]
"@eslint-community/eslint-comments/no-unused-disable": [2]
"@eslint-community/eslint-comments/no-unused-enable": [2]
"@eslint-community/eslint-comments/no-use": [0]
"@eslint-community/eslint-comments/require-description": [0]
"@stylistic/js/array-bracket-newline": [0]
"@stylistic/js/array-bracket-spacing": [2, never]
"@stylistic/js/array-element-newline": [0]
"@stylistic/js/arrow-parens": [2, always]
"@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, always-multiline]
"@stylistic/js/comma-spacing": [2, {before: false, after: true}]
"@stylistic/js/comma-style": [2, last]
"@stylistic/js/computed-property-spacing": [2, never]
"@stylistic/js/dot-location": [2, property]
"@stylistic/js/eol-last": [2]
"@stylistic/js/function-call-spacing": [2, never]
"@stylistic/js/function-call-argument-newline": [0]
"@stylistic/js/function-paren-newline": [0]
"@stylistic/js/generator-star-spacing": [0]
"@stylistic/js/implicit-arrow-linebreak": [0]
"@stylistic/js/indent": [2, 2, {ignoreComments: true, SwitchCase: 1}]
"@stylistic/js/key-spacing": [2]
"@stylistic/js/keyword-spacing": [2]
"@stylistic/js/linebreak-style": [2, unix]
"@stylistic/js/lines-around-comment": [0]
"@stylistic/js/lines-between-class-members": [0]
"@stylistic/js/max-len": [0]
"@stylistic/js/max-statements-per-line": [0]
"@stylistic/js/multiline-ternary": [0]
"@stylistic/js/new-parens": [2]
"@stylistic/js/newline-per-chained-call": [0]
"@stylistic/js/no-confusing-arrow": [0]
"@stylistic/js/no-extra-parens": [0]
"@stylistic/js/no-extra-semi": [2]
"@stylistic/js/no-floating-decimal": [0]
"@stylistic/js/no-mixed-operators": [0]
"@stylistic/js/no-mixed-spaces-and-tabs": [2]
"@stylistic/js/no-multi-spaces": [2, {ignoreEOLComments: true, exceptions: {Property: true}}]
"@stylistic/js/no-multiple-empty-lines": [2, {max: 1, maxEOF: 0, maxBOF: 0}]
"@stylistic/js/no-tabs": [2]
"@stylistic/js/no-trailing-spaces": [2]
"@stylistic/js/no-whitespace-before-property": [2]
"@stylistic/js/nonblock-statement-body-position": [2]
"@stylistic/js/object-curly-newline": [0]
"@stylistic/js/object-curly-spacing": [2, never]
"@stylistic/js/object-property-newline": [0]
"@stylistic/js/one-var-declaration-per-line": [0]
"@stylistic/js/operator-linebreak": [2, after]
"@stylistic/js/padded-blocks": [2, never]
"@stylistic/js/padding-line-between-statements": [0]
"@stylistic/js/quote-props": [0]
"@stylistic/js/quotes": [2, single, {avoidEscape: true, allowTemplateLiterals: true}]
"@stylistic/js/rest-spread-spacing": [2, never]
"@stylistic/js/semi": [2, always, {omitLastInOneLineBlock: true}]
"@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": [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]
"@stylistic/js/spaced-comment": [2, always]
"@stylistic/js/switch-colon-spacing": [2]
"@stylistic/js/template-curly-spacing": [2, never]
"@stylistic/js/template-tag-spacing": [2, never]
"@stylistic/js/wrap-iife": [2, inside]
"@stylistic/js/wrap-regex": [0]
"@stylistic/js/yield-star-spacing": [2, after]
accessor-pairs: [2]
array-callback-return: [2, {checkForEach: true}]
array-func/avoid-reverse: [2]
array-func/from-map: [2]
array-func/no-unnecessary-this-arg: [2]
array-func/prefer-array-from: [2]
array-func/prefer-flat-map: [0] # handled by unicorn/prefer-array-flat-map
array-func/prefer-flat: [0] # handled by unicorn/prefer-array-flat
arrow-body-style: [0]
block-scoped-var: [2]
camelcase: [0]
capitalized-comments: [0]
class-methods-use-this: [0]
complexity: [0]
consistent-return: [0]
consistent-this: [0]
constructor-super: [2]
curly: [0]
default-case-last: [2]
default-case: [0]
default-param-last: [0]
dot-notation: [0]
eqeqeq: [2]
for-direction: [2]
func-name-matching: [2]
func-names: [0]
func-style: [0]
getter-return: [2]
github/a11y-aria-label-is-well-formatted: [0]
github/a11y-no-title-attribute: [0]
github/a11y-no-visually-hidden-interactive-element: [0]
github/a11y-role-supports-aria-props: [0]
github/a11y-svg-has-accessible-name: [0]
github/array-foreach: [0]
github/async-currenttarget: [2]
github/async-preventdefault: [2]
github/authenticity-token: [0]
github/get-attribute: [0]
github/js-class-name: [0]
github/no-blur: [0]
github/no-d-none: [0]
github/no-dataset: [2]
github/no-dynamic-script-tag: [2]
github/no-implicit-buggy-globals: [2]
github/no-inner-html: [0]
github/no-innerText: [2]
github/no-then: [2]
github/no-useless-passive: [2]
github/prefer-observers: [2]
github/require-passive-events: [2]
github/unescaped-html-literal: [0]
grouped-accessor-pairs: [2]
guard-for-in: [0]
id-blacklist: [0]
id-length: [0]
id-match: [0]
i/consistent-type-specifier-style: [0]
i/default: [0]
i/dynamic-import-chunkname: [0]
i/export: [2]
i/exports-last: [0]
i/extensions: [2, always, {ignorePackages: true}]
i/first: [2]
i/group-exports: [0]
i/max-dependencies: [0]
i/named: [2]
i/namespace: [0]
i/newline-after-import: [0]
i/no-absolute-path: [0]
i/no-amd: [2]
i/no-anonymous-default-export: [0]
i/no-commonjs: [2]
i/no-cycle: [2, {ignoreExternal: true, maxDepth: 1}]
i/no-default-export: [0]
i/no-deprecated: [0]
i/no-dynamic-require: [0]
i/no-empty-named-blocks: [2]
i/no-extraneous-dependencies: [2]
i/no-import-module-exports: [0]
i/no-internal-modules: [0]
i/no-mutable-exports: [0]
i/no-named-as-default-member: [0]
i/no-named-as-default: [2]
i/no-named-default: [0]
i/no-named-export: [0]
i/no-namespace: [0]
i/no-nodejs-modules: [0]
i/no-relative-packages: [0]
i/no-relative-parent-imports: [0]
i/no-restricted-paths: [0]
i/no-self-import: [2]
i/no-unassigned-import: [0]
i/no-unresolved: [2, {commonjs: true, ignore: ["\\?.+$", ^vitest/]}]
i/no-unused-modules: [2, {unusedExports: true}]
i/no-useless-path-segments: [2, {commonjs: true}]
i/no-webpack-loader-syntax: [2]
i/order: [0]
i/prefer-default-export: [0]
i/unambiguous: [0]
init-declarations: [0]
line-comment-position: [0]
logical-assignment-operators: [0]
max-classes-per-file: [0]
max-depth: [0]
max-lines-per-function: [0]
max-lines: [0]
max-nested-callbacks: [0]
max-params: [0]
max-statements: [0]
multiline-comment-style: [2, separate-lines]
new-cap: [0]
no-alert: [0]
no-array-constructor: [2]
no-async-promise-executor: [0]
no-await-in-loop: [0]
no-bitwise: [0]
no-buffer-constructor: [0]
no-caller: [2]
no-case-declarations: [2]
no-class-assign: [2]
no-compare-neg-zero: [2]
no-cond-assign: [2, except-parens]
no-console: [1, {allow: [debug, info, warn, error]}]
no-const-assign: [2]
no-constant-binary-expression: [2]
no-constant-condition: [0]
no-constructor-return: [2]
no-continue: [0]
no-control-regex: [0]
no-debugger: [1]
no-delete-var: [2]
no-div-regex: [0]
no-dupe-args: [2]
no-dupe-class-members: [2]
no-dupe-else-if: [2]
no-dupe-keys: [2]
no-duplicate-case: [2]
no-duplicate-imports: [2]
no-else-return: [2]
no-empty-character-class: [2]
no-empty-function: [0]
no-empty-pattern: [2]
no-empty-static-block: [2]
no-empty: [2, {allowEmptyCatch: true}]
no-eq-null: [2]
no-eval: [2]
no-ex-assign: [2]
no-extend-native: [2]
no-extra-bind: [2]
no-extra-boolean-cast: [2]
no-extra-label: [0]
no-fallthrough: [2]
no-func-assign: [2]
no-global-assign: [2]
no-implicit-coercion: [2]
no-implicit-globals: [0]
no-implied-eval: [2]
no-import-assign: [2]
no-inline-comments: [0]
no-inner-declarations: [2]
no-invalid-regexp: [2]
no-invalid-this: [0]
no-irregular-whitespace: [2]
no-iterator: [2]
no-jquery/no-ajax-events: [2]
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: [2]
no-jquery/no-attr: [2]
no-jquery/no-bind: [2]
no-jquery/no-box-model: [2]
no-jquery/no-browser: [2]
no-jquery/no-camel-case: [2]
no-jquery/no-class-state: [2]
no-jquery/no-class: [0]
no-jquery/no-clone: [2]
no-jquery/no-closest: [0]
no-jquery/no-constructor-attributes: [2]
no-jquery/no-contains: [2]
no-jquery/no-context-prop: [2]
no-jquery/no-css: [2]
no-jquery/no-data: [0]
no-jquery/no-deferred: [2]
no-jquery/no-delegate: [2]
no-jquery/no-each-collection: [0]
no-jquery/no-each-util: [0]
no-jquery/no-each: [0]
no-jquery/no-error-shorthand: [2]
no-jquery/no-error: [2]
no-jquery/no-escape-selector: [2]
no-jquery/no-event-shorthand: [2]
no-jquery/no-extend: [2]
no-jquery/no-fade: [2]
no-jquery/no-filter: [0]
no-jquery/no-find-collection: [0]
no-jquery/no-find-util: [2]
no-jquery/no-find: [0]
no-jquery/no-fx-interval: [2]
no-jquery/no-global-eval: [2]
no-jquery/no-global-selector: [0]
no-jquery/no-grep: [2]
no-jquery/no-has: [2]
no-jquery/no-hold-ready: [2]
no-jquery/no-html: [0]
no-jquery/no-in-array: [2]
no-jquery/no-is-array: [2]
no-jquery/no-is-empty-object: [2]
no-jquery/no-is-function: [2]
no-jquery/no-is-numeric: [2]
no-jquery/no-is-plain-object: [2]
no-jquery/no-is-window: [2]
no-jquery/no-is: [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: [2]
no-jquery/no-merge: [2]
no-jquery/no-node-name: [2]
no-jquery/no-noop: [2]
no-jquery/no-now: [2]
no-jquery/no-on-ready: [2]
no-jquery/no-other-methods: [0]
no-jquery/no-other-utils: [2]
no-jquery/no-param: [2]
no-jquery/no-parent: [0]
no-jquery/no-parents: [2]
no-jquery/no-parse-html-literal: [2]
no-jquery/no-parse-html: [2]
no-jquery/no-parse-json: [2]
no-jquery/no-parse-xml: [2]
no-jquery/no-prop: [2]
no-jquery/no-proxy: [2]
no-jquery/no-ready-shorthand: [2]
no-jquery/no-ready: [2]
no-jquery/no-selector-prop: [2]
no-jquery/no-serialize: [2]
no-jquery/no-size: [2]
no-jquery/no-sizzle: [0]
no-jquery/no-slide: [2]
no-jquery/no-sub: [2]
no-jquery/no-support: [2]
no-jquery/no-text: [0]
no-jquery/no-trigger: [0]
no-jquery/no-trim: [2]
no-jquery/no-type: [2]
no-jquery/no-unique: [2]
no-jquery/no-unload-shorthand: [2]
no-jquery/no-val: [0]
no-jquery/no-visibility: [2]
no-jquery/no-when: [2]
no-jquery/no-wrap: [2]
no-jquery/variable-pattern: [2]
no-label-var: [2]
no-labels: [0] # handled by no-restricted-syntax
no-lone-blocks: [2]
no-lonely-if: [0]
no-loop-func: [0]
no-loss-of-precision: [2]
no-magic-numbers: [0]
no-misleading-character-class: [2]
no-multi-assign: [0]
no-multi-str: [2]
no-negated-condition: [0]
no-nested-ternary: [0]
no-new-func: [2]
no-new-native-nonconstructor: [2]
no-new-object: [2]
no-new-symbol: [2]
no-new-wrappers: [2]
no-new: [0]
no-nonoctal-decimal-escape: [2]
no-obj-calls: [2]
no-octal-escape: [2]
no-octal: [2]
no-param-reassign: [0]
no-plusplus: [0]
no-promise-executor-return: [0]
no-proto: [2]
no-prototype-builtins: [2]
no-redeclare: [2]
no-regex-spaces: [2]
no-restricted-exports: [0]
no-restricted-globals: [2, addEventListener, blur, close, closed, confirm, defaultStatus, defaultstatus, error, event, external, find, focus, frameElement, frames, history, innerHeight, innerWidth, isFinite, isNaN, length, location, 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, self, status, statusbar, stop, toolbar, top, __dirname, __filename]
no-restricted-imports: [0]
no-restricted-syntax: [2, WithStatement, ForInStatement, LabeledStatement, SequenceExpression, {selector: "CallExpression[callee.name='fetch']", message: "use modules/fetch.js instead"}]
no-return-assign: [0]
no-script-url: [2]
no-self-assign: [2, {props: true}]
no-self-compare: [2]
no-sequences: [2]
no-setter-return: [2]
no-shadow-restricted-names: [2]
no-shadow: [0]
no-sparse-arrays: [2]
no-template-curly-in-string: [2]
no-ternary: [0]
no-this-before-super: [2]
no-throw-literal: [2]
no-undef-init: [2]
no-undef: [2, {typeof: true}]
no-undefined: [0]
no-underscore-dangle: [0]
no-unexpected-multiline: [2]
no-unmodified-loop-condition: [2]
no-unneeded-ternary: [2]
no-unreachable-loop: [2]
no-unreachable: [2]
no-unsafe-finally: [2]
no-unsafe-negation: [2]
no-unused-expressions: [2]
no-unused-labels: [2]
no-unused-private-class-members: [2]
no-unused-vars: [2, {args: all, argsIgnorePattern: ^_, varsIgnorePattern: ^_, caughtErrorsIgnorePattern: ^_, destructuredArrayIgnorePattern: ^_, ignoreRestSiblings: false}]
no-use-before-define: [2, {functions: false, classes: true, variables: true, allowNamedExports: true}]
no-use-extend-native/no-use-extend-native: [2]
no-useless-backreference: [2]
no-useless-call: [2]
no-useless-catch: [2]
no-useless-computed-key: [2]
no-useless-concat: [2]
no-useless-constructor: [2]
no-useless-escape: [2]
no-useless-rename: [2]
no-useless-return: [2]
no-var: [2]
no-void: [2]
no-warning-comments: [0]
no-with: [0] # handled by no-restricted-syntax
object-shorthand: [2, always]
one-var-declaration-per-line: [0]
one-var: [0]
operator-assignment: [2, always]
operator-linebreak: [2, after]
prefer-arrow-callback: [2, {allowNamedFunctions: true, allowUnboundThis: true}]
prefer-const: [2, {destructuring: all, ignoreReadBeforeAssign: true}]
prefer-destructuring: [0]
prefer-exponentiation-operator: [2]
prefer-named-capture-group: [0]
prefer-numeric-literals: [2]
prefer-object-has-own: [2]
prefer-object-spread: [2]
prefer-promise-reject-errors: [2, {allowEmptyReject: false}]
prefer-regex-literals: [2]
prefer-rest-params: [2]
prefer-spread: [2]
prefer-template: [2]
radix: [2, as-needed]
regexp/confusing-quantifier: [2]
regexp/control-character-escape: [2]
regexp/hexadecimal-escape: [0]
regexp/letter-case: [0]
regexp/match-any: [2]
regexp/negation: [2]
regexp/no-contradiction-with-assertion: [0]
regexp/no-control-character: [0]
regexp/no-dupe-characters-character-class: [2]
regexp/no-dupe-disjunctions: [2]
regexp/no-empty-alternative: [2]
regexp/no-empty-capturing-group: [2]
regexp/no-empty-character-class: [0]
regexp/no-empty-group: [2]
regexp/no-empty-lookarounds-assertion: [2]
regexp/no-empty-string-literal: [2]
regexp/no-escape-backspace: [2]
regexp/no-extra-lookaround-assertions: [0]
regexp/no-invalid-regexp: [2]
regexp/no-invisible-character: [2]
regexp/no-lazy-ends: [2]
regexp/no-legacy-features: [2]
regexp/no-misleading-capturing-group: [0]
regexp/no-misleading-unicode-character: [0]
regexp/no-missing-g-flag: [2]
regexp/no-non-standard-flag: [2]
regexp/no-obscure-range: [2]
regexp/no-octal: [2]
regexp/no-optional-assertion: [2]
regexp/no-potentially-useless-backreference: [2]
regexp/no-standalone-backslash: [2]
regexp/no-super-linear-backtracking: [0]
regexp/no-super-linear-move: [0]
regexp/no-trivially-nested-assertion: [2]
regexp/no-trivially-nested-quantifier: [2]
regexp/no-unused-capturing-group: [0]
regexp/no-useless-assertions: [2]
regexp/no-useless-backreference: [2]
regexp/no-useless-character-class: [2]
regexp/no-useless-dollar-replacements: [2]
regexp/no-useless-escape: [2]
regexp/no-useless-flag: [2]
regexp/no-useless-lazy: [2]
regexp/no-useless-non-capturing-group: [2]
regexp/no-useless-quantifier: [2]
regexp/no-useless-range: [2]
regexp/no-useless-set-operand: [2]
regexp/no-useless-string-literal: [2]
regexp/no-useless-two-nums-quantifier: [2]
regexp/no-zero-quantifier: [2]
regexp/optimal-lookaround-quantifier: [2]
regexp/optimal-quantifier-concatenation: [0]
regexp/prefer-character-class: [0]
regexp/prefer-d: [0]
regexp/prefer-escape-replacement-dollar-char: [0]
regexp/prefer-lookaround: [0]
regexp/prefer-named-backreference: [0]
regexp/prefer-named-capture-group: [0]
regexp/prefer-named-replacement: [0]
regexp/prefer-plus-quantifier: [2]
regexp/prefer-predefined-assertion: [2]
regexp/prefer-quantifier: [0]
regexp/prefer-question-quantifier: [2]
regexp/prefer-range: [2]
regexp/prefer-regexp-exec: [2]
regexp/prefer-regexp-test: [2]
regexp/prefer-result-array-groups: [0]
regexp/prefer-set-operation: [2]
regexp/prefer-star-quantifier: [2]
regexp/prefer-unicode-codepoint-escapes: [2]
regexp/prefer-w: [0]
regexp/require-unicode-regexp: [0]
regexp/simplify-set-operations: [2]
regexp/sort-alternatives: [0]
regexp/sort-character-class-elements: [0]
regexp/sort-flags: [0]
regexp/strict: [2]
regexp/unicode-escape: [0]
regexp/use-ignore-case: [0]
require-atomic-updates: [0]
require-await: [0]
require-unicode-regexp: [0]
require-yield: [2]
sonarjs/cognitive-complexity: [0]
sonarjs/elseif-without-else: [0]
sonarjs/max-switch-cases: [0]
sonarjs/no-all-duplicated-branches: [2]
sonarjs/no-collapsible-if: [0]
sonarjs/no-collection-size-mischeck: [2]
sonarjs/no-duplicate-string: [0]
sonarjs/no-duplicated-branches: [0]
sonarjs/no-element-overwrite: [2]
sonarjs/no-empty-collection: [2]
sonarjs/no-extra-arguments: [2]
sonarjs/no-gratuitous-expressions: [2]
sonarjs/no-identical-conditions: [2]
sonarjs/no-identical-expressions: [2]
sonarjs/no-identical-functions: [2, 5]
sonarjs/no-ignored-return: [2]
sonarjs/no-inverted-boolean-check: [2]
sonarjs/no-nested-switch: [0]
sonarjs/no-nested-template-literals: [0]
sonarjs/no-one-iteration-loop: [2]
sonarjs/no-redundant-boolean: [2]
sonarjs/no-redundant-jump: [2]
sonarjs/no-same-line-conditional: [2]
sonarjs/no-small-switch: [0]
sonarjs/no-unused-collection: [2]
sonarjs/no-use-of-empty-return-value: [2]
sonarjs/no-useless-catch: [2]
sonarjs/non-existent-operator: [2]
sonarjs/prefer-immediate-return: [0]
sonarjs/prefer-object-literal: [0]
sonarjs/prefer-single-boolean-return: [0]
sonarjs/prefer-while: [2]
sort-imports: [0]
sort-keys: [0]
sort-vars: [0]
strict: [0]
symbol-description: [2]
unicode-bom: [2, never]
unicorn/better-regex: [0]
unicorn/catch-error-name: [0]
unicorn/consistent-destructuring: [2]
unicorn/consistent-empty-array-spread: [2]
unicorn/consistent-function-scoping: [2]
unicorn/custom-error-definition: [0]
unicorn/empty-brace-spaces: [2]
unicorn/error-message: [0]
unicorn/escape-case: [0]
unicorn/expiring-todo-comments: [0]
unicorn/explicit-length-check: [0]
unicorn/filename-case: [0]
unicorn/import-index: [0]
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]
unicorn/no-for-loop: [0]
unicorn/no-hex-escape: [0]
unicorn/no-instanceof-array: [0]
unicorn/no-invalid-fetch-options: [2]
unicorn/no-invalid-remove-event-listener: [2]
unicorn/no-keyword-prefix: [0]
unicorn/no-length-as-slice-end: [2]
unicorn/no-lonely-if: [2]
unicorn/no-magic-array-flat-depth: [0]
unicorn/no-negated-condition: [0]
unicorn/no-negation-in-equality-check: [2]
unicorn/no-nested-ternary: [0]
unicorn/no-new-array: [0]
unicorn/no-new-buffer: [0]
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]
unicorn/no-typeof-undefined: [2]
unicorn/no-unnecessary-await: [2]
unicorn/no-unnecessary-polyfills: [2]
unicorn/no-unreadable-array-destructuring: [0]
unicorn/no-unreadable-iife: [2]
unicorn/no-unused-properties: [2]
unicorn/no-useless-fallback-in-spread: [2]
unicorn/no-useless-length-check: [2]
unicorn/no-useless-promise-resolve-reject: [2]
unicorn/no-useless-spread: [2]
unicorn/no-useless-switch-case: [2]
unicorn/no-useless-undefined: [0]
unicorn/no-zero-fractions: [2]
unicorn/number-literal-case: [0]
unicorn/numeric-separators-style: [0]
unicorn/prefer-add-event-listener: [2]
unicorn/prefer-array-find: [2]
unicorn/prefer-array-flat-map: [2]
unicorn/prefer-array-flat: [2]
unicorn/prefer-array-index-of: [2]
unicorn/prefer-array-some: [2]
unicorn/prefer-at: [0]
unicorn/prefer-blob-reading-methods: [2]
unicorn/prefer-code-point: [0]
unicorn/prefer-date-now: [2]
unicorn/prefer-default-parameters: [0]
unicorn/prefer-dom-node-append: [2]
unicorn/prefer-dom-node-dataset: [0]
unicorn/prefer-dom-node-remove: [2]
unicorn/prefer-dom-node-text-content: [2]
unicorn/prefer-event-target: [2]
unicorn/prefer-export-from: [0]
unicorn/prefer-includes: [2]
unicorn/prefer-json-parse-buffer: [0]
unicorn/prefer-keyboard-event-key: [2]
unicorn/prefer-logical-operator-over-ternary: [2]
unicorn/prefer-math-trunc: [2]
unicorn/prefer-modern-dom-apis: [0]
unicorn/prefer-modern-math-apis: [2]
unicorn/prefer-module: [2]
unicorn/prefer-native-coercion-functions: [2]
unicorn/prefer-negative-index: [2]
unicorn/prefer-node-protocol: [2]
unicorn/prefer-number-properties: [0]
unicorn/prefer-object-from-entries: [2]
unicorn/prefer-object-has-own: [0]
unicorn/prefer-optional-catch-binding: [2]
unicorn/prefer-prototype-methods: [0]
unicorn/prefer-query-selector: [0]
unicorn/prefer-reflect-apply: [0]
unicorn/prefer-regexp-test: [2]
unicorn/prefer-set-has: [0]
unicorn/prefer-set-size: [2]
unicorn/prefer-spread: [0]
unicorn/prefer-string-raw: [0]
unicorn/prefer-string-replace-all: [0]
unicorn/prefer-string-slice: [0]
unicorn/prefer-string-starts-ends-with: [2]
unicorn/prefer-string-trim-start-end: [2]
unicorn/prefer-structured-clone: [2]
unicorn/prefer-switch: [0]
unicorn/prefer-ternary: [0]
unicorn/prefer-text-content: [2]
unicorn/prefer-top-level-await: [0]
unicorn/prefer-type-error: [0]
unicorn/prevent-abbreviations: [0]
unicorn/relative-url-style: [2]
unicorn/require-array-join-separator: [2]
unicorn/require-number-to-fixed-digits-argument: [2]
unicorn/require-post-message-target-origin: [0]
unicorn/string-content: [0]
unicorn/switch-case-braces: [0]
unicorn/template-indent: [2]
unicorn/text-encoding-identifier-case: [0]
unicorn/throw-new-error: [2]
use-isnan: [2]
valid-typeof: [2, {requireStringLiterals: true}]
vars-on-top: [0]
wc/attach-shadow-constructor: [2]
wc/define-tag-after-class-definition: [0]
wc/expose-class-on-global: [0]
wc/file-name-matches-element: [2]
wc/guard-define-call: [0]
wc/guard-super-call: [2]
wc/max-elements-per-file: [0]
wc/no-child-traversal-in-attributechangedcallback: [2]
wc/no-child-traversal-in-connectedcallback: [2]
wc/no-closed-shadow-root: [2]
wc/no-constructor-attributes: [2]
wc/no-constructor-params: [2]
wc/no-constructor: [2]
wc/no-customized-built-in-elements: [2]
wc/no-exports-with-element: [0]
wc/no-invalid-element-name: [2]
wc/no-invalid-extends: [2]
wc/no-method-prefixed-with-on: [2]
wc/no-self-class: [2]
wc/no-typos: [2]
wc/require-listener-teardown: [2]
wc/tag-name-matches-class: [2]
yoda: [2, never]

View file

@ -1,7 +1,7 @@
contact_links:
- name: 🔓 Security Reports
url: mailto:security@forgejo.org
about: "Please email <security@forgejo.org> (GPG: `A4676E79`) instead of opening a public issue."
about: "Please email <security@forgejo.org> (See https://forgejo.org/.well-known/security.txt)."
- name: 💬 Matrix Chat Room
url: https://matrix.to/#/#forgejo-chat:matrix.org
about: Please ask questions and discuss configuration or deployment problems here.

View file

@ -3,4 +3,4 @@ ARG RELEASE_VERSION=unkown
LABEL maintainer="contact@forgejo.org" \
org.opencontainers.image.version="${RELEASE_VERSION}"
RUN mkdir -p /app/gitea
RUN ( echo '#!/bin/sh' ; echo "echo forgejo v$RELEASE_VERSION" ) > /app/gitea/forgejo-cli ; chmod +x /app/gitea/forgejo-cli
RUN ( echo '#!/bin/sh' ; echo "echo forgejo v$RELEASE_VERSION" ) > /app/gitea/gitea ; chmod +x /app/gitea/gitea

View file

@ -1,3 +1,3 @@
module code.gitea.io/gitea
go 1.23.1
go 1.23.3

View file

@ -0,0 +1,29 @@
inputs:
packages:
description: 'Packages to install'
required: true
release:
description: 'Release to install from'
default: testing
runs:
using: "composite"
steps:
- name: setup apt package source
run: |
export DEBIAN_FRONTEND=noninteractive
echo "deb http://deb.debian.org/debian/ ${RELEASE} main" > "/etc/apt/sources.list.d/${RELEASE}.list"
env:
RELEASE: ${{inputs.release}}
- name: install packages
run: |
apt-get update -qq
apt-get -q install -qq -y ${PACKAGES}
env:
PACKAGES: ${{inputs.packages}}
- name: remove temporary package list to prevent using it in other steps
run: |
rm "/etc/apt/sources.list.d/${RELEASE}.list"
apt-get update -qq
env:
RELEASE: ${{inputs.release}}

View file

@ -0,0 +1,15 @@
runs:
using: "composite"
steps:
- run: |
su forgejo -c 'make deps-backend'
- uses: actions/cache@v4
id: cache-backend
with:
path: ${{github.workspace}}/gitea
key: backend-build-${{ github.sha }}
- if: steps.cache-backend.outputs.cache-hit != 'true'
run: |
su forgejo -c 'make backend'
env:
TAGS: bindata

View file

@ -0,0 +1,12 @@
runs:
using: "composite"
steps:
- name: setup user and permissions
run: |
git config --add safe.directory '*'
# ignore if the user already exists (like with the playwright image)
adduser --quiet --comment forgejo --disabled-password forgejo || true
chown -R forgejo:forgejo .
- uses: https://codeberg.org/fnetx/setup-cache-go@b2214eaf6fb44c7e8512c0f462a2c3ec31f86a73
with:
username: forgejo

View file

@ -31,7 +31,7 @@ on:
jobs:
backporting:
if: >
!startsWith(vars.ROLE, 'forgejo-') && (
( vars.ROLE == 'forgejo-coding' ) && (
github.event.pull_request.merged
&&
contains(toJSON(github.event.pull_request.labels), 'backport/v')
@ -45,7 +45,7 @@ jobs:
cat <<'EOF'
${{ toJSON(github) }}
EOF
- uses: https://code.forgejo.org/actions/git-backporting@v4.8.0
- uses: https://code.forgejo.org/actions/git-backporting@v4.8.4
with:
target-branch-pattern: "^backport/(?<target>(v.*))$"
strategy: ort

View file

@ -22,10 +22,10 @@ on:
jobs:
release-simulation:
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
if: vars.ROLE == 'forgejo-coding'
runs-on: self-hosted
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- id: forgejo
uses: https://code.forgejo.org/actions/setup-forgejo@v1

View file

@ -27,7 +27,7 @@ jobs:
# root is used for testing, allow it
if: vars.ROLE == 'forgejo-integration' || github.repository_owner == 'root'
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
fetch-depth: 0
@ -37,11 +37,11 @@ jobs:
repository="${{ github.repository }}"
echo "value=${repository##*/}" >> "$GITHUB_OUTPUT"
- uses: https://code.forgejo.org/actions/setup-node@v3
- uses: https://code.forgejo.org/actions/setup-node@v4
with:
node-version: 20
- uses: https://code.forgejo.org/actions/setup-go@v4
- uses: https://code.forgejo.org/actions/setup-go@v5
with:
go-version-file: "go.mod"
@ -87,7 +87,7 @@ jobs:
- name: cache node_modules
id: node
uses: https://code.forgejo.org/actions/cache@v3
uses: https://code.forgejo.org/actions/cache@v4
with:
path: |
node_modules
@ -170,7 +170,7 @@ jobs:
platforms: linux/amd64,linux/arm64,linux/arm/v6
release-notes: "${{ steps.release-notes.outputs.value }}"
binary-name: forgejo
binary-path: /app/gitea/forgejo-cli
binary-path: /app/gitea/gitea
override: "${{ steps.release-info.outputs.override }}"
verify-labels: "maintainer=contact@forgejo.org,org.opencontainers.image.version=${{ steps.release-info.outputs.version }}"
verbose: ${{ vars.VERBOSE || secrets.VERBOSE || 'false' }}
@ -194,7 +194,7 @@ jobs:
verbose: ${{ vars.VERBOSE || secrets.VERBOSE || 'false' }}
- name: end-to-end tests
if: ${{ secrets.TOKEN != '' && vars.ROLE == 'forgejo-integration' }}
if: ${{ secrets.TOKEN != '' && vars.ROLE == 'forgejo-integration' && vars.SKIP_END_TO_END != 'true' }}
uses: https://code.forgejo.org/actions/cascading-pr@v2
with:
origin-url: ${{ env.GITHUB_SERVER_URL }}

View file

@ -1,59 +1,38 @@
# Copyright 2024 The Forgejo Authors
# SPDX-License-Identifier: MIT
#
# To modify this workflow:
#
# - push it to the wip-ci-end-to-end branch on the forgejo repository
# otherwise it will not have access to the secrets required to push
# the cascading PR
#
# - once it works, open a pull request for the sake of keeping track
# of the change even if the PR won't run it because it will use
# whatever is in the default branch instead
#
# - after it is merged, double check it works by setting the
# run-end-to-end-test on a pull request (any pull request will doe
#
name: issue-labels
on:
push:
branches:
- 'wip-ci-end-to-end'
pull_request_target:
types:
- labeled
jobs:
info:
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
runs-on: docker
container:
image: code.forgejo.org/oci/node:20-bookworm
steps:
- name: event
run: |
echo github.event.pull_request.head.repo.fork = ${{ github.event.pull_request.head.repo.fork }}
echo github.event.action = ${{ github.event.action }}
echo github.event.pull_request.merged = ${{ github.event.pull_request.merged }}
echo github.event.pull_request.labels.*.name
cat <<'EOF'
${{ toJSON(github.event.pull_request.labels.*.name) }}
EOF
cat <<'EOF'
${{ toJSON(github.event) }}
EOF
cascade:
end-to-end:
if: >
!startsWith(vars.ROLE, 'forgejo-') && (
vars.ROLE == 'forgejo-coding' &&
secrets.END_TO_END_CASCADING_PR_DESTINATION != '' &&
secrets.END_TO_END_CASCADING_PR_ORIGIN != '' &&
(
github.event_name == 'push' ||
(
github.event.action == 'label_updated' && contains(github.event.pull_request.labels.*.name, 'run-end-to-end-tests')
github.event_name == 'pull_request_target' &&
github.event.action == 'label_updated' &&
github.event.label.name == 'run-end-to-end-tests'
)
)
runs-on: docker
container:
image: code.forgejo.org/oci/node:20-bookworm
steps:
- name: Debug info
run: |
cat <<'EOF'
${{ toJSON(github) }}
EOF
- uses: actions/checkout@v4
with:
fetch-depth: '0'

View file

@ -1,37 +0,0 @@
name: e2e
on:
pull_request:
paths:
- Makefile
- playwright.config.js
- .forgejo/workflows/e2e.yml
- tests/e2e/**
- web_src/js/**
- web_src/css/form.css
- templates/webhook/shared-settings.tmpl
- templates/org/team/new.tmpl
jobs:
test-e2e:
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
runs-on: docker
container:
image: 'code.forgejo.org/oci/playwright:latest'
steps:
- uses: https://code.forgejo.org/actions/checkout@v4
- uses: https://code.forgejo.org/actions/setup-go@v4
with:
go-version-file: "go.mod"
- run: |
git config --add safe.directory '*'
chown -R forgejo:forgejo .
- run: |
su forgejo -c 'make deps-frontend frontend deps-backend'
- run: |
su forgejo -c 'make backend'
- run: |
su forgejo -c 'make generate test-e2e-sqlite'
timeout-minutes: 40
env:
USE_REPO_TEST_DIR: 1

View file

@ -0,0 +1,52 @@
# Copyright 2024 The Forgejo Authors
# SPDX-License-Identifier: MIT
name: issue-labels
on:
pull_request:
types:
- labeled
- edited
- opened
jobs:
merge-conditions:
if: >
vars.ROLE == 'forgejo-coding' &&
github.event_name == 'pull_request' &&
(
github.event.action == 'label_updated' ||
github.event.action == 'edited' ||
github.event.action == 'opened'
)
runs-on: docker
container:
image: 'code.forgejo.org/oci/node:20-bookworm'
steps:
- name: Debug info
run: |
cat <<'EOF'
${{ toJSON(github) }}
EOF
- name: Missing test label
if: >
!(
contains(toJSON(github.event.pull_request.labels), 'test/present')
|| contains(toJSON(github.event.pull_request.labels), 'test/not-needed')
|| contains(toJSON(github.event.pull_request.labels), 'test/manual')
)
run: |
echo "Test label must be set to either 'present', 'not-needed' or 'manual'."
exit 1
- name: Missing manual test instructions
if: >
(
contains(toJSON(github.event.pull_request.labels), 'test/manual')
&& !contains(toJSON(github.event.pull_request.body), '# Test')
)
run: |
echo "Manual test label is set. The PR description needs to contain test steps introduced by a heading like:"
echo "# Testing"
exit 1

View file

@ -39,7 +39,7 @@ jobs:
runs-on: self-hosted
if: vars.DOER != '' && vars.FORGEJO != '' && vars.TO_OWNER != '' && vars.FROM_OWNER != '' && secrets.TOKEN != ''
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: copy & sign
uses: https://code.forgejo.org/forgejo/forgejo-build-publish/publish@v5
@ -59,20 +59,35 @@ jobs:
gpg-passphrase: ${{ secrets.GPG_PASSPHRASE }}
verbose: ${{ vars.VERBOSE }}
- name: get trigger mirror issue
id: mirror
uses: https://code.forgejo.org/infrastructure/issue-action/get@v1.1.0
with:
forgejo: https://code.forgejo.org
repository: forgejo/forgejo
labels: mirror-trigger
- name: trigger the mirror
uses: https://code.forgejo.org/infrastructure/issue-action/set@v1.1.0
with:
forgejo: https://code.forgejo.org
repository: forgejo/forgejo
token: ${{ secrets.LABEL_ISSUE_FORGEJO_MIRROR_TOKEN }}
numbers: ${{ steps.mirror.outputs.numbers }}
label-wait-if-exists: 3600
label: trigger
- name: upgrade v*.next.forgejo.org
run: |
export DEBIAN_FRONTEND=noninteractive
apt-get update -qq
apt-get -q install -y -qq curl
version="${{ github.ref_name }}"
version=${version##*v}
major=$(echo $version | sed -E -e 's/^([0-9]+).*/\1/')
# https://forgejo.org/docs/next/developer/infrastructure
curl -o /dev/null -sS https://v$major.next.forgejo.org/.well-known/wakeup-on-logs/forgejo-v$major
uses: https://code.forgejo.org/infrastructure/next-digest@v1.1.0
with:
url: https://placeholder:${{ secrets.TOKEN_NEXT_DIGEST }}@code.forgejo.org/infrastructure/next-digest
ref_name: '${{ github.ref_name }}'
image: 'codeberg.org/forgejo-experimental/forgejo'
tag_suffix: '-rootless'
- name: set up go for the DNS update below
if: vars.ROLE == 'forgejo-experimental' && secrets.OVH_APP_KEY != ''
uses: https://code.forgejo.org/actions/setup-go@v4
uses: https://code.forgejo.org/actions/setup-go@v5
with:
go-version-file: "go.mod"
- name: update the _release.experimental DNS record

View file

@ -6,14 +6,14 @@ on:
jobs:
release-notes:
if: ${{ !startsWith(vars.ROLE, 'forgejo-')
if: vars.ROLE == 'forgejo-coding'
runs-on: docker
container:
image: 'code.forgejo.org/oci/node:20-bookworm'
steps:
- uses: https://code.forgejo.org/actions/checkout@v3
- uses: https://code.forgejo.org/actions/checkout@v4
- uses: https://code.forgejo.org/actions/setup-go@v4
- uses: https://code.forgejo.org/actions/setup-go@v5
with:
go-version-file: "go.mod"
cache: false

View file

@ -7,12 +7,12 @@ on:
jobs:
release-notes:
if: ${{ !startsWith(vars.ROLE, 'forgejo-') && contains(github.event.pull_request.labels.*.name, 'worth a release-note') }}
if: ( vars.ROLE == 'forgejo-coding' ) && contains(github.event.pull_request.labels.*.name, 'worth a release-note')
runs-on: docker
container:
image: 'code.forgejo.org/oci/node:20-bookworm'
steps:
- uses: https://code.forgejo.org/actions/checkout@v3
- uses: https://code.forgejo.org/actions/checkout@v4
- name: event
run: |
@ -23,7 +23,7 @@ jobs:
${{ toJSON(github.event) }}
EOF
- uses: https://code.forgejo.org/actions/setup-go@v4
- uses: https://code.forgejo.org/actions/setup-go@v5
with:
go-version-file: "go.mod"
cache: false

View file

@ -8,7 +8,9 @@ name: renovate
on:
push:
branches:
- 'renovate/**' # self-test updates
- renovate/** # self-test updates
paths:
- .forgejo/workflows/renovate.yml
schedule:
- cron: '0 0/2 * * *'
workflow_dispatch:
@ -19,15 +21,15 @@ env:
jobs:
renovate:
if: ${{ secrets.RENOVATE_TOKEN != '' }}
if: vars.ROLE == 'forgejo-coding' && secrets.RENOVATE_TOKEN != ''
runs-on: docker
runs-on: docker-runner-one
container:
image: code.forgejo.org/forgejo-contrib/renovate:38.93.2
image: code.forgejo.org/forgejo-contrib/renovate:39.19.1
steps:
- name: Load renovate repo cache
uses: https://code.forgejo.org/actions/cache/restore@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
uses: https://code.forgejo.org/actions/cache/restore@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1
with:
path: |
.tmp/cache/renovate/repository
@ -60,7 +62,7 @@ jobs:
- name: Save renovate repo cache
if: always() && env.RENOVATE_DRY_RUN != 'full'
uses: https://code.forgejo.org/actions/cache/save@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
uses: https://code.forgejo.org/actions/cache/save@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1
with:
path: |
.tmp/cache/renovate/repository

View file

@ -6,10 +6,11 @@ on:
branches:
- 'forgejo*'
- 'v*/forgejo*'
workflow_dispatch:
jobs:
backend-checks:
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
if: vars.ROLE == 'forgejo-coding' || vars.ROLE == 'forgejo-testing'
runs-on: docker
container:
image: 'code.forgejo.org/oci/node:20-bookworm'
@ -19,306 +20,246 @@ jobs:
cat <<'EOF'
${{ toJSON(github) }}
EOF
- uses: https://code.forgejo.org/actions/checkout@v3
- uses: https://code.forgejo.org/actions/setup-go@v4
with:
go-version-file: "go.mod"
- run: make deps-backend deps-tools
- run: make --always-make -j$(nproc) lint-backend tidy-check swagger-check fmt-check swagger-validate # ensure the "go-licenses" make target runs
- run: |
make backend
env:
TAGS: bindata
- uses: actions/cache@v4
with:
path: '/workspace/forgejo/forgejo/gitea'
key: backend-build-${{ github.sha }}
- uses: https://code.forgejo.org/actions/checkout@v4
- uses: ./.forgejo/workflows-composite/setup-env
- run: su forgejo -c 'make deps-backend deps-tools'
- run: su forgejo -c 'make --always-make -j$(nproc) lint-backend tidy-check swagger-check fmt-check swagger-validate' # ensure the "go-licenses" make target runs
- uses: ./.forgejo/workflows-composite/build-backend
frontend-checks:
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
if: vars.ROLE == 'forgejo-coding' || vars.ROLE == 'forgejo-testing'
runs-on: docker
container:
image: 'code.forgejo.org/oci/node:20-bookworm'
steps:
- uses: https://code.forgejo.org/actions/checkout@v3
- uses: https://code.forgejo.org/actions/checkout@v4
- run: make deps-frontend
- run: make lint-frontend
- run: make checks-frontend
- run: make test-frontend-coverage
- run: make frontend
- name: Install zstd for cache saving
# works around https://github.com/actions/cache/issues/1169, because the
# consuming job has zstd and doesn't restore the cache otherwise
run: |
apt-get update -qq
apt-get -q install -qq -y zstd
- name: "Cache frontend build for playwright testing"
uses: actions/cache/save@v4
with:
path: ${{github.workspace}}/public/assets
key: frontend-build-${{ github.sha }}
test-unit:
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
if: vars.ROLE == 'forgejo-coding' || vars.ROLE == 'forgejo-testing'
runs-on: docker
needs: [backend-checks, frontend-checks]
container:
image: 'code.forgejo.org/oci/node:20-bookworm'
services:
elasticsearch:
image: docker.io/bitnami/elasticsearch:7
image: code.forgejo.org/oci/bitnami/elasticsearch:7
options: --tmpfs /bitnami/elasticsearch/data
env:
discovery.type: single-node
ES_JAVA_OPTS: "-Xms512m -Xmx512m"
minio:
image: docker.io/bitnami/minio:2024.8.17
image: code.forgejo.org/oci/bitnami/minio:2024.8.17
options: >-
--hostname gitea.minio
--hostname gitea.minio --tmpfs /bitnami/minio/data
env:
MINIO_DOMAIN: minio
MINIO_ROOT_USER: 123456
MINIO_ROOT_PASSWORD: 12345678
steps:
- uses: https://code.forgejo.org/actions/checkout@v3
- uses: https://code.forgejo.org/actions/setup-go@v4
with:
go-version-file: "go.mod"
- run: |
git config --add safe.directory '*'
adduser --quiet --comment forgejo --disabled-password forgejo
chown -R forgejo:forgejo .
- uses: https://code.forgejo.org/actions/checkout@v4
- uses: ./.forgejo/workflows-composite/setup-env
- name: install git >= 2.42
run: |
export DEBIAN_FRONTEND=noninteractive
echo deb http://deb.debian.org/debian/ testing main > /etc/apt/sources.list.d/testing.list
apt-get update -qq
apt-get -q install -qq -y git
rm /etc/apt/sources.list.d/testing.list
apt-get update -qq
uses: ./.forgejo/workflows-composite/apt-install-from
with:
packages: git
- name: test release-notes-assistant.sh
run: |
apt-get -q install -qq -y jq
./release-notes-assistant.sh test_main
- run: |
su forgejo -c 'make deps-backend'
- uses: actions/cache/restore@v4
id: cache-backend
with:
path: '/workspace/forgejo/forgejo/gitea'
key: backend-build-${{ github.sha }}
- if: steps.cache-backend.outputs.cache-hit != 'true'
run: |
su forgejo -c 'make backend'
env:
TAGS: bindata
- uses: ./.forgejo/workflows-composite/build-backend
- run: |
su forgejo -c 'make test-backend test-check'
timeout-minutes: 50
timeout-minutes: 120
env:
RACE_ENABLED: 'true'
TAGS: bindata
TEST_ELASTICSEARCH_URL: http://elasticsearch:9200
test-remote-cacher:
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
test-e2e:
if: vars.ROLE == 'forgejo-coding' || vars.ROLE == 'forgejo-testing'
runs-on: docker
needs: [backend-checks, frontend-checks]
container:
image: 'code.forgejo.org/oci/playwright:latest'
steps:
- uses: https://code.forgejo.org/actions/checkout@v4
with:
fetch-depth: 20
- uses: ./.forgejo/workflows-composite/setup-env
- name: "Restore frontend build"
uses: actions/cache/restore@v4
id: cache-frontend
with:
path: ${{github.workspace}}/public/assets
key: frontend-build-${{ github.sha }}
- name: "Build frontend (if not cached)"
if: steps.cache-frontend.outputs.cache-hit != 'true'
run: |
su forgejo -c 'make deps-frontend frontend'
- uses: ./.forgejo/workflows-composite/build-backend
- name: Get changed files
id: changed-files
uses: https://code.forgejo.org/tj-actions/changed-files@v45
with:
separator: '\n'
- run: |
su forgejo -c 'make generate test-e2e-sqlite'
timeout-minutes: 120
env:
USE_REPO_TEST_DIR: 1
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
CHANGED_FILES: ${{steps.changed-files.outputs.all_changed_files}}
- name: Upload test artifacts on failure
if: failure()
uses: https://code.forgejo.org/forgejo/upload-artifact@v4
with:
name: test-artifacts.zip
path: tests/e2e/test-artifacts/
retention-days: 3
test-remote-cacher:
if: vars.ROLE == 'forgejo-coding' || vars.ROLE == 'forgejo-testing'
runs-on: docker
needs: [backend-checks, frontend-checks, test-unit]
container:
image: 'code.forgejo.org/oci/node:20-bookworm'
name: ${{ format('test-remote-cacher ({0})', matrix.cacher.name) }}
strategy:
matrix:
cacher:
# redis
- image: docker.io/bitnami/redis:7.2
port: 6379
# redict
- image: registry.redict.io/redict:7.3.0-scratch
port: 6379
# valkey
- image: docker.io/bitnami/valkey:7.2
port: 6379
# garnet
- image: ghcr.io/microsoft/garnet-alpine:1.0.14
port: 6379
- name: redis
image: code.forgejo.org/oci/bitnami/redis:7.2
options: --tmpfs /bitnami/redis/data
- name: redict
image: registry.redict.io/redict:7.3.0-scratch
options: --tmpfs /data
- name: valkey
image: code.forgejo.org/oci/bitnami/valkey:7.2
options: --tmpfs /bitnami/redis/data
- name: garnet
image: ghcr.io/microsoft/garnet-alpine:1.0.14
options: --tmpfs /data
services:
cacher:
image: ${{ matrix.cacher.image }}
options: ${{ matrix.cacher.options }}
steps:
- uses: https://code.forgejo.org/actions/checkout@v3
- uses: https://code.forgejo.org/actions/setup-go@v4
with:
go-version-file: "go.mod"
- run: |
git config --add safe.directory '*'
adduser --quiet --comment forgejo --disabled-password forgejo
chown -R forgejo:forgejo .
- uses: https://code.forgejo.org/actions/checkout@v4
- uses: ./.forgejo/workflows-composite/setup-env
- name: install git >= 2.42
run: |
export DEBIAN_FRONTEND=noninteractive
echo deb http://deb.debian.org/debian/ testing main > /etc/apt/sources.list.d/testing.list
apt-get update -qq
apt-get -q install -qq -y git
rm /etc/apt/sources.list.d/testing.list
apt-get update -qq
- run: |
su forgejo -c 'make deps-backend'
- uses: actions/cache/restore@v4
id: cache-backend
uses: ./.forgejo/workflows-composite/apt-install-from
with:
path: '/workspace/forgejo/forgejo/gitea'
key: backend-build-${{ github.sha }}
- if: steps.cache-backend.outputs.cache-hit != 'true'
run: |
su forgejo -c 'make backend'
env:
TAGS: bindata
packages: git
- uses: ./.forgejo/workflows-composite/build-backend
- run: |
su forgejo -c 'make test-remote-cacher test-check'
timeout-minutes: 50
timeout-minutes: 120
env:
RACE_ENABLED: 'true'
TAGS: bindata
TEST_REDIS_SERVER: cacher:${{ matrix.cacher.port }}
test-mysql:
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
if: vars.ROLE == 'forgejo-coding' || vars.ROLE == 'forgejo-testing'
runs-on: docker
needs: [backend-checks, frontend-checks]
container:
image: 'code.forgejo.org/oci/node:20-bookworm'
services:
mysql:
image: 'docker.io/bitnami/mysql:8.4'
image: 'code.forgejo.org/oci/bitnami/mysql:8.4'
env:
ALLOW_EMPTY_PASSWORD: yes
MYSQL_DATABASE: testgitea
#
# See also https://codeberg.org/forgejo/forgejo/issues/976
#
MYSQL_EXTRA_FLAGS: --innodb-adaptive-flushing=OFF --innodb-buffer-pool-size=4G --innodb-log-buffer-size=128M --innodb-flush-log-at-trx-commit=0 --innodb-flush-log-at-timeout=30 --innodb-flush-method=nosync --innodb-fsync-threshold=1000000000
MYSQL_EXTRA_FLAGS: --innodb-adaptive-flushing=OFF --innodb-buffer-pool-size=4G --innodb-log-buffer-size=128M --innodb-flush-log-at-trx-commit=0 --innodb-flush-log-at-timeout=30 --innodb-flush-method=nosync --innodb-fsync-threshold=1000000000 --disable-log-bin
options: --tmpfs /bitnami/mysql/data
steps:
- uses: https://code.forgejo.org/actions/checkout@v3
- uses: https://code.forgejo.org/actions/setup-go@v4
with:
go-version-file: "go.mod"
- uses: https://code.forgejo.org/actions/checkout@v4
- uses: ./.forgejo/workflows-composite/setup-env
- name: install dependencies & git >= 2.42
run: |
export DEBIAN_FRONTEND=noninteractive
echo deb http://deb.debian.org/debian/ testing main > /etc/apt/sources.list.d/testing.list
apt-get update -qq
apt-get install --no-install-recommends -qq -y git git-lfs
rm /etc/apt/sources.list.d/testing.list
apt-get update -qq
- name: setup user and permissions
run: |
git config --add safe.directory '*'
adduser --quiet --comment forgejo --disabled-password forgejo
chown -R forgejo:forgejo .
- run: |
su forgejo -c 'make deps-backend'
- uses: actions/cache/restore@v4
id: cache-backend
uses: ./.forgejo/workflows-composite/apt-install-from
with:
path: '/workspace/forgejo/forgejo/gitea'
key: backend-build-${{ github.sha }}
- if: steps.cache-backend.outputs.cache-hit != 'true'
run: |
su forgejo -c 'make backend'
env:
TAGS: bindata
packages: git git-lfs
- uses: ./.forgejo/workflows-composite/build-backend
- run: |
su forgejo -c 'make test-mysql-migration test-mysql'
timeout-minutes: 50
timeout-minutes: 120
env:
USE_REPO_TEST_DIR: 1
test-pgsql:
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
if: vars.ROLE == 'forgejo-coding' || vars.ROLE == 'forgejo-testing'
runs-on: docker
needs: [backend-checks, frontend-checks]
container:
image: 'code.forgejo.org/oci/node:20-bookworm'
services:
minio:
image: docker.io/bitnami/minio:2024.8.17
image: code.forgejo.org/oci/bitnami/minio:2024.8.17
env:
MINIO_ROOT_USER: 123456
MINIO_ROOT_PASSWORD: 12345678
options: --tmpfs /bitnami/minio/data
ldap:
image: docker.io/gitea/test-openldap:latest
image: code.forgejo.org/oci/test-openldap:latest
pgsql:
image: 'code.forgejo.org/oci/postgres:15'
env:
POSTGRES_DB: test
POSTGRES_PASSWORD: postgres
options: --tmpfs /var/lib/postgresql/data
steps:
- uses: https://code.forgejo.org/actions/checkout@v3
- uses: https://code.forgejo.org/actions/setup-go@v4
with:
go-version-file: "go.mod"
- uses: https://code.forgejo.org/actions/checkout@v4
- uses: ./.forgejo/workflows-composite/setup-env
- name: install dependencies & git >= 2.42
run: |
export DEBIAN_FRONTEND=noninteractive
echo deb http://deb.debian.org/debian/ testing main > /etc/apt/sources.list.d/testing.list
apt-get update -qq
apt-get install --no-install-recommends -qq -y git git-lfs
rm /etc/apt/sources.list.d/testing.list
apt-get update -qq
- name: setup user and permissions
run: |
git config --add safe.directory '*'
adduser --quiet --comment forgejo --disabled-password forgejo
chown -R forgejo:forgejo .
- run: |
su forgejo -c 'make deps-backend'
- uses: actions/cache/restore@v4
id: cache-backend
uses: ./.forgejo/workflows-composite/apt-install-from
with:
path: '/workspace/forgejo/forgejo/gitea'
key: backend-build-${{ github.sha }}
- if: steps.cache-backend.outputs.cache-hit != 'true'
run: |
su forgejo -c 'make backend'
env:
TAGS: bindata
packages: git git-lfs
- uses: ./.forgejo/workflows-composite/build-backend
- run: |
su forgejo -c 'make test-pgsql-migration test-pgsql'
timeout-minutes: 50
timeout-minutes: 120
env:
RACE_ENABLED: true
USE_REPO_TEST_DIR: 1
TEST_LDAP: 1
test-sqlite:
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
if: vars.ROLE == 'forgejo-coding' || vars.ROLE == 'forgejo-testing'
runs-on: docker
needs: [backend-checks, frontend-checks]
container:
image: 'code.forgejo.org/oci/node:20-bookworm'
steps:
- uses: https://code.forgejo.org/actions/checkout@v3
- uses: https://code.forgejo.org/actions/setup-go@v4
with:
go-version-file: "go.mod"
- uses: https://code.forgejo.org/actions/checkout@v4
- uses: ./.forgejo/workflows-composite/setup-env
- name: install dependencies & git >= 2.42
run: |
export DEBIAN_FRONTEND=noninteractive
echo deb http://deb.debian.org/debian/ testing main > /etc/apt/sources.list.d/testing.list
apt-get update -qq
apt-get install --no-install-recommends -qq -y git git-lfs
rm /etc/apt/sources.list.d/testing.list
apt-get update -qq
- name: setup user and permissions
run: |
git config --add safe.directory '*'
adduser --quiet --comment forgejo --disabled-password forgejo
chown -R forgejo:forgejo .
- run: |
su forgejo -c 'make deps-backend'
- uses: actions/cache/restore@v4
id: cache-backend
uses: ./.forgejo/workflows-composite/apt-install-from
with:
path: '/workspace/forgejo/forgejo/gitea'
key: backend-build-${{ github.sha }}
- if: steps.cache-backend.outputs.cache-hit != 'true'
run: |
su forgejo -c 'make backend'
env:
TAGS: bindata sqlite sqlite_unlock_notify
packages: git git-lfs
- uses: ./.forgejo/workflows-composite/build-backend
- run: |
su forgejo -c 'make test-sqlite-migration test-sqlite'
timeout-minutes: 50
timeout-minutes: 120
env:
TAGS: sqlite sqlite_unlock_notify
RACE_ENABLED: true
TEST_TAGS: sqlite sqlite_unlock_notify
USE_REPO_TEST_DIR: 1
security-check:
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
if: vars.ROLE == 'forgejo-coding' || vars.ROLE == 'forgejo-testing'
runs-on: docker
needs:
- test-sqlite
@ -329,9 +270,7 @@ jobs:
container:
image: 'code.forgejo.org/oci/node:20-bookworm'
steps:
- uses: https://code.forgejo.org/actions/checkout@v3
- uses: https://code.forgejo.org/actions/setup-go@v4
with:
go-version-file: "go.mod"
- run: make deps-backend deps-tools
- run: make security-check
- uses: https://code.forgejo.org/actions/checkout@v4
- uses: ./.forgejo/workflows-composite/setup-env
- run: su forgejo -c 'make deps-backend deps-tools'
- run: su forgejo -c 'make security-check'

3
.gitignore vendored
View file

@ -115,6 +115,9 @@ prime/
*_source.tar.bz2
.DS_Store
# Direnv configuration
/.envrc
# nix-direnv generated files
.direnv/

View file

@ -77,6 +77,8 @@ linters-settings:
- name: unreachable-code
- name: var-declaration
- name: var-naming
- name: redefines-builtin-id
disabled: true
gofumpt:
extra-rules: true
depguard:

View file

@ -10,7 +10,7 @@ branch-known:
cleanup-line: 'sed -Ee "s/^(feat|fix):\s*//g" -e "s/^\[WIP\] //" -e "s/^WIP: //" -e "s;\[(UI|BUG|FEAT|v.*?/forgejo)\]\s*;;g"'
render-header: |
## Draft release notes
## Release notes
comment: |
<details>
<summary>Where does that come from?</summary>

View file

@ -16,6 +16,9 @@ templates/.* @caesar @crystal @gusted
## the issue sidebar was touched by fnetx
templates/repo/issue/view_content/sidebar.* @fnetx
# Playwright tests
tests/e2e/.* @fnetx
# Files related to Go development.
# The modules usually don't require much knowledge about Forgejo and could

View file

@ -51,7 +51,7 @@ RUN chmod 755 /tmp/local/usr/bin/entrypoint \
/go/src/code.gitea.io/gitea/environment-to-ini
RUN chmod 644 /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete
FROM code.forgejo.org/oci/golang:1.23-alpine3.20
FROM code.forgejo.org/oci/alpine:3.20
ARG RELEASE_VERSION
LABEL maintainer="contact@forgejo.org" \
org.opencontainers.image.authors="Forgejo" \
@ -103,6 +103,6 @@ CMD ["/bin/s6-svscan", "/etc/s6"]
COPY --from=build-env /tmp/local /
RUN cd /usr/local/bin ; ln -s gitea forgejo
COPY --from=build-env /go/src/code.gitea.io/gitea/gitea /app/gitea/gitea
RUN ln /app/gitea/gitea /app/gitea/forgejo-cli
RUN ln -s /app/gitea/gitea /app/gitea/forgejo-cli
COPY --from=build-env /go/src/code.gitea.io/gitea/environment-to-ini /usr/local/bin/environment-to-ini
COPY --from=build-env /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete /etc/profile.d/gitea_bash_autocomplete.sh

View file

@ -49,7 +49,7 @@ RUN chmod 755 /tmp/local/usr/local/bin/docker-entrypoint.sh \
/go/src/code.gitea.io/gitea/environment-to-ini
RUN chmod 644 /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete
FROM code.forgejo.org/oci/golang:1.23-alpine3.20
FROM code.forgejo.org/oci/alpine:3.20
LABEL maintainer="contact@forgejo.org" \
org.opencontainers.image.authors="Forgejo" \
org.opencontainers.image.url="https://forgejo.org" \
@ -90,7 +90,7 @@ RUN chown git:git /var/lib/gitea /etc/gitea
COPY --from=build-env /tmp/local /
RUN cd /usr/local/bin ; ln -s gitea forgejo
COPY --from=build-env --chown=root:root /go/src/code.gitea.io/gitea/gitea /app/gitea/gitea
RUN ln /app/gitea/gitea /app/gitea/forgejo-cli
RUN ln -s /app/gitea/gitea /app/gitea/forgejo-cli
COPY --from=build-env --chown=root:root /go/src/code.gitea.io/gitea/environment-to-ini /usr/local/bin/environment-to-ini
COPY --from=build-env /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete /etc/profile.d/gitea_bash_autocomplete.sh

105
Makefile
View file

@ -24,22 +24,32 @@ HAS_GO := $(shell hash $(GO) > /dev/null 2>&1 && echo yes)
COMMA := ,
DIFF ?= diff --unified
ifeq ($(USE_GOTESTSUM), yes)
GOTEST ?= gotestsum --
GOTESTCOMPILEDRUNPREFIX ?= gotestsum --raw-command -- go tool test2json -t
GOTESTCOMPILEDRUNSUFFIX ?= -test.v=test2json
else
GOTEST ?= $(GO) test
GOTESTCOMPILEDRUNPREFIX ?=
GOTESTCOMPILEDRUNSUFFIX ?=
endif
XGO_VERSION := go-1.21.x
AIR_PACKAGE ?= github.com/air-verse/air@v1 # renovate: datasource=go
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/v3/cmd/editorconfig-checker@v3.0.3 # renovate: datasource=go
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.7.0 # renovate: datasource=go
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.61.0 # renovate: datasource=go
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.62.0 # renovate: datasource=go
GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.11 # renovate: datasource=go
MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.6.0 # renovate: datasource=go
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.31.0 # renovate: datasource=go
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
GO_LICENSES_PACKAGE ?= github.com/google/go-licenses@v1.6.0 # renovate: datasource=go
GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@v1 # renovate: datasource=go
DEADCODE_PACKAGE ?= golang.org/x/tools/cmd/deadcode@v0.25.0 # renovate: datasource=go
DEADCODE_PACKAGE ?= golang.org/x/tools/cmd/deadcode@v0.26.0 # renovate: datasource=go
GOMOCK_PACKAGE ?= go.uber.org/mock/mockgen@v0.4.0 # renovate: datasource=go
GOPLS_PACKAGE ?= golang.org/x/tools/gopls@v0.16.2 # renovate: datasource=go
RENOVATE_NPM_PACKAGE ?= renovate@38.93.2 # renovate: datasource=docker packageName=code.forgejo.org/forgejo-contrib/renovate
RENOVATE_NPM_PACKAGE ?= renovate@39.19.1 # renovate: datasource=docker packageName=code.forgejo.org/forgejo-contrib/renovate
ifeq ($(HAS_GO), yes)
CGO_EXTRA_CFLAGS := -DSQLITE_MAX_VARIABLE_NUMBER=32766
@ -154,9 +164,8 @@ 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 *.js tests/e2e/*.js tests/e2e/shared/*.js
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 $(wildcard *.go *.js *.md *.yml *.yaml *.toml)
SPELLCHECK_FILES := $(GO_DIRS) $(WEB_DIRS) docs/content templates options/locale/locale_en-US.ini .github $(wildcard *.go *.js *.ts *.vue *.md *.yml *.yaml *.toml)
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)
@ -408,7 +417,7 @@ lint-frontend: lint-js lint-css
lint-frontend-fix: lint-js-fix lint-css-fix
.PHONY: lint-backend
lint-backend: lint-go lint-go-vet lint-editorconfig lint-renovate
lint-backend: lint-go lint-go-vet lint-editorconfig lint-renovate lint-locale
.PHONY: lint-backend-fix
lint-backend-fix: lint-go-fix lint-go-vet lint-editorconfig
@ -427,11 +436,11 @@ lint-codespell-fix-i:
.PHONY: lint-js
lint-js: node_modules
npx eslint --color --max-warnings=0 --ext js,vue $(ESLINT_FILES)
npx eslint --color --max-warnings=0
.PHONY: lint-js-fix
lint-js-fix: node_modules
npx eslint --color --max-warnings=0 --ext js,vue $(ESLINT_FILES) --fix
npx eslint --color --max-warnings=0 --fix
.PHONY: lint-css
lint-css: node_modules
@ -451,6 +460,10 @@ lint-renovate: node_modules
@if grep --quiet --extended-regexp -e '^( WARN:|ERROR:)' .lint-renovate ; then cat .lint-renovate ; rm .lint-renovate ; exit 1 ; fi
@rm .lint-renovate
.PHONY: lint-locale
lint-locale:
$(GO) run build/lint-locale.go
.PHONY: lint-md
lint-md: node_modules
npx markdownlint docs *.md
@ -534,12 +547,12 @@ test: test-frontend test-backend
.PHONY: test-backend
test-backend:
@echo "Running go test with $(GOTESTFLAGS) -tags '$(TEST_TAGS)'..."
@$(GO) test $(GOTESTFLAGS) -tags='$(TEST_TAGS)' $(GO_TEST_PACKAGES)
@$(GOTEST) $(GOTESTFLAGS) -tags='$(TEST_TAGS)' $(GO_TEST_PACKAGES)
.PHONY: test-remote-cacher
test-remote-cacher:
@echo "Running go test with $(GOTESTFLAGS) -tags '$(TEST_TAGS)'..."
@$(GO) test $(GOTESTFLAGS) -tags='$(TEST_TAGS)' $(GO_TEST_REMOTE_CACHER_PACKAGES)
@$(GOTEST) $(GOTESTFLAGS) -tags='$(TEST_TAGS)' $(GO_TEST_REMOTE_CACHER_PACKAGES)
.PHONY: test-frontend
test-frontend: node_modules
@ -564,7 +577,7 @@ test-check:
.PHONY: test\#%
test\#%:
@echo "Running go test with -tags '$(TEST_TAGS)'..."
@$(GO) test $(GOTESTFLAGS) -tags='$(TEST_TAGS)' -run $(subst .,/,$*) $(GO_TEST_PACKAGES)
@$(GOTEST) $(GOTESTFLAGS) -tags='$(TEST_TAGS)' -run $(subst .,/,$*) $(GO_TEST_PACKAGES)
.PHONY: coverage
coverage:
@ -575,7 +588,7 @@ coverage:
.PHONY: unit-test-coverage
unit-test-coverage:
@echo "Running unit-test-coverage $(GOTESTFLAGS) -tags '$(TEST_TAGS)'..."
@$(GO) test $(GOTESTFLAGS) -timeout=20m -tags='$(TEST_TAGS)' -cover -coverprofile coverage.out $(GO_TEST_PACKAGES) && echo "\n==>\033[32m Ok\033[m\n" || exit 1
@$(GOTEST) $(GOTESTFLAGS) -timeout=20m -tags='$(TEST_TAGS)' -cover -coverprofile coverage.out $(GO_TEST_PACKAGES) && echo "\n==>\033[32m Ok\033[m\n" || exit 1
.PHONY: tidy
tidy:
@ -608,11 +621,11 @@ generate-ini-sqlite:
.PHONY: test-sqlite
test-sqlite: integrations.sqlite.test generate-ini-sqlite
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./integrations.sqlite.test
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini $(GOTESTCOMPILEDRUNPREFIX) ./integrations.sqlite.test $(GOTESTCOMPILEDRUNSUFFIX)
.PHONY: test-sqlite\#%
test-sqlite\#%: integrations.sqlite.test generate-ini-sqlite
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./integrations.sqlite.test -test.run $(subst .,/,$*)
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini $(GOTESTCOMPILEDRUNPREFIX) ./integrations.sqlite.test $(GOTESTCOMPILEDRUNSUFFIX) -test.run $(subst .,/,$*)
.PHONY: test-sqlite-migration
test-sqlite-migration: migrations.sqlite.test migrations.individual.sqlite.test
@ -629,11 +642,11 @@ generate-ini-mysql:
.PHONY: test-mysql
test-mysql: integrations.mysql.test generate-ini-mysql
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini ./integrations.mysql.test
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini $(GOTESTCOMPILEDRUNPREFIX) ./integrations.mysql.test $(GOTESTCOMPILEDRUNSUFFIX)
.PHONY: test-mysql\#%
test-mysql\#%: integrations.mysql.test generate-ini-mysql
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini ./integrations.mysql.test -test.run $(subst .,/,$*)
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini $(GOTESTCOMPILEDRUNPREFIX) ./integrations.mysql.test $(GOTESTCOMPILEDRUNSUFFIX) -test.run $(subst .,/,$*)
.PHONY: test-mysql-migration
test-mysql-migration: migrations.mysql.test migrations.individual.mysql.test
@ -647,15 +660,16 @@ generate-ini-pgsql:
-e 's|{{REPO_TEST_DIR}}|${REPO_TEST_DIR}|g' \
-e 's|{{TEST_LOGGER}}|$(or $(TEST_LOGGER),test$(COMMA)file)|g' \
-e 's|{{TEST_TYPE}}|$(or $(TEST_TYPE),integration)|g' \
-e 's|{{TEST_STORAGE_TYPE}}|$(or $(TEST_STORAGE_TYPE),minio)|g' \
tests/pgsql.ini.tmpl > tests/pgsql.ini
.PHONY: test-pgsql
test-pgsql: integrations.pgsql.test generate-ini-pgsql
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini ./integrations.pgsql.test
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini $(GOTESTCOMPILEDRUNPREFIX) ./integrations.pgsql.test $(GOTESTCOMPILEDRUNSUFFIX)
.PHONY: test-pgsql\#%
test-pgsql\#%: integrations.pgsql.test generate-ini-pgsql
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini ./integrations.pgsql.test -test.run $(subst .,/,$*)
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini $(GOTESTCOMPILEDRUNPREFIX) ./integrations.pgsql.test $(GOTESTCOMPILEDRUNSUFFIX) -test.run $(subst .,/,$*)
.PHONY: test-pgsql-migration
test-pgsql-migration: migrations.pgsql.test migrations.individual.pgsql.test
@ -674,35 +688,34 @@ test-e2e: test-e2e-sqlite
.PHONY: test-e2e-sqlite
test-e2e-sqlite: playwright e2e.sqlite.test generate-ini-sqlite
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./e2e.sqlite.test -test.run TestE2e
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini $(GOTESTCOMPILEDRUNPREFIX) ./e2e.sqlite.test $(GOTESTCOMPILEDRUNSUFFIX) -test.run TestE2e
.PHONY: test-e2e-sqlite\#%
test-e2e-sqlite\#%: playwright e2e.sqlite.test generate-ini-sqlite
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./e2e.sqlite.test -test.run TestE2e/$*
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini $(GOTESTCOMPILEDRUNPREFIX) ./e2e.sqlite.test $(GOTESTCOMPILEDRUNSUFFIX) -test.run TestE2e/$*
.PHONY: test-e2e-sqlite-firefox\#%
test-e2e-sqlite-firefox\#%: playwright e2e.sqlite.test generate-ini-sqlite
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini PLAYWRIGHT_PROJECT=firefox ./e2e.sqlite.test -test.run TestE2e/$*
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini PLAYWRIGHT_PROJECT=firefox $(GOTESTCOMPILEDRUNPREFIX) ./e2e.sqlite.test $(GOTESTCOMPILEDRUNSUFFIX) -test.run TestE2e/$*
.PHONY: test-e2e-mysql
test-e2e-mysql: playwright e2e.mysql.test generate-ini-mysql
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini ./e2e.mysql.test -test.run TestE2e
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini $(GOTESTCOMPILEDRUNPREFIX) ./e2e.mysql.test $(GOTESTCOMPILEDRUNSUFFIX) -test.run TestE2e
.PHONY: test-e2e-mysql\#%
test-e2e-mysql\#%: playwright e2e.mysql.test generate-ini-mysql
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini ./e2e.mysql.test -test.run TestE2e/$*
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini $(GOTESTCOMPILEDRUNPREFIX) ./e2e.mysql.test $(GOTESTCOMPILEDRUNSUFFIX) -test.run TestE2e/$*
.PHONY: test-e2e-pgsql
test-e2e-pgsql: playwright e2e.pgsql.test generate-ini-pgsql
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini ./e2e.pgsql.test -test.run TestE2e
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini $(GOTESTCOMPILEDRUNPREFIX) ./e2e.pgsql.test $(GOTESTCOMPILEDRUNSUFFIX) -test.run TestE2e
.PHONY: test-e2e-pgsql\#%
test-e2e-pgsql\#%: playwright e2e.pgsql.test generate-ini-pgsql
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini ./e2e.pgsql.test -test.run TestE2e/$*
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini $(GOTESTCOMPILEDRUNPREFIX) ./e2e.pgsql.test $(GOTESTCOMPILEDRUNSUFFIX) -test.run TestE2e/$*
.PHONY: test-e2e-debugserver
test-e2e-debugserver: e2e.sqlite.test generate-ini-sqlite
sed -i s/3003/3000/g tests/sqlite.ini
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./e2e.sqlite.test -test.run TestDebugserver -test.timeout 24h
.PHONY: bench-sqlite
@ -726,73 +739,73 @@ integration-test-coverage-sqlite: integrations.cover.sqlite.test generate-ini-sq
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./integrations.cover.sqlite.test -test.coverprofile=integration.coverage.out
integrations.mysql.test: git-check $(GO_SOURCES)
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -o integrations.mysql.test
$(GOTEST) $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -o integrations.mysql.test
integrations.pgsql.test: git-check $(GO_SOURCES)
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -o integrations.pgsql.test
$(GOTEST) $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -o integrations.pgsql.test
integrations.sqlite.test: git-check $(GO_SOURCES)
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -o integrations.sqlite.test -tags '$(TEST_TAGS)'
$(GOTEST) $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -o integrations.sqlite.test -tags '$(TEST_TAGS)'
integrations.cover.test: git-check $(GO_SOURCES)
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -coverpkg $(shell echo $(GO_TEST_PACKAGES) | tr ' ' ',') -o integrations.cover.test
$(GOTEST) $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -coverpkg $(shell echo $(GO_TEST_PACKAGES) | tr ' ' ',') -o integrations.cover.test
integrations.cover.sqlite.test: git-check $(GO_SOURCES)
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -coverpkg $(shell echo $(GO_TEST_PACKAGES) | tr ' ' ',') -o integrations.cover.sqlite.test -tags '$(TEST_TAGS)'
$(GOTEST) $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -coverpkg $(shell echo $(GO_TEST_PACKAGES) | tr ' ' ',') -o integrations.cover.sqlite.test -tags '$(TEST_TAGS)'
.PHONY: migrations.mysql.test
migrations.mysql.test: $(GO_SOURCES) generate-ini-mysql
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration/migration-test -o migrations.mysql.test
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini ./migrations.mysql.test
$(GOTEST) $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration/migration-test -o migrations.mysql.test
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini $(GOTESTCOMPILEDRUNPREFIX) ./migrations.mysql.test $(GOTESTCOMPILEDRUNSUFFIX)
.PHONY: migrations.pgsql.test
migrations.pgsql.test: $(GO_SOURCES) generate-ini-pgsql
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration/migration-test -o migrations.pgsql.test
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini ./migrations.pgsql.test
$(GOTEST) $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration/migration-test -o migrations.pgsql.test
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini $(GOTESTCOMPILEDRUNPREFIX) ./migrations.pgsql.test $(GOTESTCOMPILEDRUNSUFFIX)
.PHONY: migrations.sqlite.test
migrations.sqlite.test: $(GO_SOURCES) generate-ini-sqlite
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration/migration-test -o migrations.sqlite.test -tags '$(TEST_TAGS)'
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./migrations.sqlite.test
$(GOTEST) $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration/migration-test -o migrations.sqlite.test -tags '$(TEST_TAGS)'
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini $(GOTESTCOMPILEDRUNPREFIX) ./migrations.sqlite.test $(GOTESTCOMPILEDRUNSUFFIX)
.PHONY: migrations.individual.mysql.test
migrations.individual.mysql.test: $(GO_SOURCES)
for pkg in $(MIGRATION_PACKAGES); do \
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg || exit 1; \
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini $(GOTEST) $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg || exit 1; \
done
.PHONY: migrations.individual.sqlite.test\#%
migrations.individual.sqlite.test\#%: $(GO_SOURCES) generate-ini-sqlite
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' code.gitea.io/gitea/models/migrations/$*
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini $(GOTEST) $(GOTESTFLAGS) -tags '$(TEST_TAGS)' code.gitea.io/gitea/models/migrations/$*
.PHONY: migrations.individual.pgsql.test
migrations.individual.pgsql.test: $(GO_SOURCES)
for pkg in $(MIGRATION_PACKAGES); do \
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg || exit 1;\
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini $(GOTEST) $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg || exit 1;\
done
.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/$*
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini $(GOTEST) $(GOTESTFLAGS) -tags '$(TEST_TAGS)' code.gitea.io/gitea/models/migrations/$*
.PHONY: migrations.individual.sqlite.test
migrations.individual.sqlite.test: $(GO_SOURCES) generate-ini-sqlite
for pkg in $(MIGRATION_PACKAGES); do \
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg || exit 1; \
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini $(GOTEST) $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg || exit 1; \
done
.PHONY: migrations.individual.sqlite.test\#%
migrations.individual.sqlite.test\#%: $(GO_SOURCES) generate-ini-sqlite
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' code.gitea.io/gitea/models/migrations/$*
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini $(GOTEST) $(GOTESTFLAGS) -tags '$(TEST_TAGS)' code.gitea.io/gitea/models/migrations/$*
e2e.mysql.test: $(GO_SOURCES)
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/e2e -o e2e.mysql.test
$(GOTEST) $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/e2e -o e2e.mysql.test
e2e.pgsql.test: $(GO_SOURCES)
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/e2e -o e2e.pgsql.test
$(GOTEST) $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/e2e -o e2e.pgsql.test
e2e.sqlite.test: $(GO_SOURCES)
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/e2e -o e2e.sqlite.test -tags '$(TEST_TAGS)'
$(GOTEST) $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/e2e -o e2e.sqlite.test -tags '$(TEST_TAGS)'
.PHONY: check
check: test

View file

@ -1,4 +1,3 @@
<div align="center">
<img src="./assets/logo.svg" alt="" width="192" align="center" />
<h1 align="center">Welcome to Forgejo</h1>

View file

@ -6,6 +6,18 @@ A [patch or minor release](https://semver.org/spec/v2.0.0.html) (e.g. upgrading
The release notes of each release [are available in the corresponding milestone](https://codeberg.org/forgejo/forgejo/milestones), starting with [Forgejo 7.0.7](https://codeberg.org/forgejo/forgejo/milestone/7683) and [Forgejo 8.0.1](https://codeberg.org/forgejo/forgejo/milestone/7682).
## 9.0.2
The Forgejo v9.0.2 release notes are [available in the v9.0.2 milestone](https://codeberg.org/forgejo/forgejo/milestone/8610).
## 9.0.1
The Forgejo v9.0.1 release notes are [available in the v9.0.1 milestone](https://codeberg.org/forgejo/forgejo/milestone/8544).
## 9.0.0
The Forgejo v9.0.0 release notes are [available in the v9.0.0 milestone](https://codeberg.org/forgejo/forgejo/milestone/7235).
## 8.0.3
The Forgejo v8.0.3 release notes are [available in the v8.0.3 milestone](https://codeberg.org/forgejo/forgejo/milestone/8231).
@ -155,6 +167,14 @@ A [companion blog post](https://forgejo.org/2024-07-release-v8-0/) provides addi
- [PR](https://codeberg.org/forgejo/forgejo/pulls/2937): <!--number 2937 --><!--number--><!--description -->31 March updates<!--description-->
<!--end release-notes-assistant-->
## 7.0.11
The Forgejo v7.0.11 release notes are [available in the v7.0.11 milestone](https://codeberg.org/forgejo/forgejo/milestone/8609).
## 7.0.10
The Forgejo v7.0.10 release notes are [available in the v7.0.10 milestone](https://codeberg.org/forgejo/forgejo/milestone/8286).
## 7.0.9
The Forgejo v7.0.9 release notes are [available in the v7.0.9 milestone](https://codeberg.org/forgejo/forgejo/milestone/8232).

File diff suppressed because one or more lines are too long

View file

@ -53,8 +53,6 @@ func (e Emoji) MarshalJSON() ([]byte, error) {
}
func main() {
var err error
flag.Parse()
// generate data
@ -83,8 +81,6 @@ var replacer = strings.NewReplacer(
var emojiRE = regexp.MustCompile(`\{Emoji:"([^"]*)"`)
func generate() ([]byte, error) {
var err error
// load gemoji data
res, err := http.Get(gemojiURL)
if err != nil {

156
build/lint-locale.go Normal file
View file

@ -0,0 +1,156 @@
// Copyright 2024 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
//nolint:forbidigo
package main
import (
"fmt"
"html"
"io/fs"
"os"
"path/filepath"
"regexp"
"slices"
"strings"
"github.com/microcosm-cc/bluemonday"
"github.com/sergi/go-diff/diffmatchpatch"
"gopkg.in/ini.v1" //nolint:depguard
)
var (
policy *bluemonday.Policy
tagRemover *strings.Replacer
safeURL = "https://TO-BE-REPLACED.COM"
// Matches href="", href="#", href="%s", href="#%s", href="%[1]s" and href="#%[1]s".
placeHolderRegex = regexp.MustCompile(`href="#?(%s|%\[\d\]s)?"`)
)
func initBlueMondayPolicy() {
policy = bluemonday.NewPolicy()
policy.RequireParseableURLs(true)
policy.AllowURLSchemes("https")
// Only allow safe URL on href.
// Only allow target="_blank".
// Only allow rel="nopener noreferrer", rel="noopener" and rel="noreferrer".
// Only allow placeholder on id and class.
policy.AllowAttrs("href").Matching(regexp.MustCompile("^" + regexp.QuoteMeta(safeURL) + "$")).OnElements("a")
policy.AllowAttrs("target").Matching(regexp.MustCompile("^_blank$")).OnElements("a")
policy.AllowAttrs("rel").Matching(regexp.MustCompile("^(noopener|noreferrer|noopener noreferrer)$")).OnElements("a")
policy.AllowAttrs("id", "class").Matching(regexp.MustCompile(`^%s|%\[\d\]s$`)).OnElements("a")
// Only allow positional placeholder as class.
positionalPlaceholderRe := regexp.MustCompile(`^%\[\d\]s$`)
policy.AllowAttrs("class").Matching(positionalPlaceholderRe).OnElements("strong")
policy.AllowAttrs("id").Matching(positionalPlaceholderRe).OnElements("code")
// Allowed elements with no attributes. Must be a recognized tagname.
policy.AllowElements("strong", "br", "b", "strike", "code", "i")
// TODO: Remove <c> in `actions.workflow.dispatch.trigger_found`.
policy.AllowNoAttrs().OnElements("c")
}
func initRemoveTags() {
oldnew := []string{}
for _, el := range []string{
"email@example.com", "correu@example.com", "epasts@domens.lv", "email@exemplo.com", "eposta@ornek.com", "email@példa.hu", "email@esempio.it",
"user", "utente", "lietotājs", "gebruiker", "usuário", "Benutzer", "Bruker",
"server", "servidor", "kiszolgáló", "serveris",
"label", "etichetta", "etiķete", "rótulo", "Label", "utilizador",
"filename", "bestandsnaam", "dosyaadi", "fails", "nome do arquivo", "datnes nosaukums",
} {
oldnew = append(oldnew, "<"+el+">", "REPLACED-TAG")
}
tagRemover = strings.NewReplacer(oldnew...)
}
func preprocessTranslationValue(value string) string {
// href should be a parsable URL, replace placeholder strings with a safe url.
value = placeHolderRegex.ReplaceAllString(value, `href="`+safeURL+`"`)
// Remove tags that aren't tags but will be parsed as tags. We already know they are safe and sound.
value = tagRemover.Replace(value)
return value
}
func checkLocaleContent(localeContent []byte) []string {
// Same configuration as Forgejo uses.
cfg := ini.Empty(ini.LoadOptions{
IgnoreContinuation: true,
})
cfg.NameMapper = ini.SnackCase
if err := cfg.Append(localeContent); err != nil {
panic(err)
}
dmp := diffmatchpatch.New()
errors := []string{}
for _, section := range cfg.Sections() {
for _, key := range section.Keys() {
var trKey string
if section.Name() == "" || section.Name() == "DEFAULT" || section.Name() == "common" {
trKey = key.Name()
} else {
trKey = section.Name() + "." + key.Name()
}
keyValue := preprocessTranslationValue(key.Value())
if html.UnescapeString(policy.Sanitize(keyValue)) != keyValue {
// Create a nice diff of the difference.
diffs := dmp.DiffMain(keyValue, html.UnescapeString(policy.Sanitize(keyValue)), false)
diffs = dmp.DiffCleanupSemantic(diffs)
diffs = dmp.DiffCleanupEfficiency(diffs)
errors = append(errors, trKey+": "+dmp.DiffPrettyText(diffs))
}
}
}
return errors
}
func main() {
initBlueMondayPolicy()
initRemoveTags()
localeDir := filepath.Join("options", "locale")
localeFiles, err := os.ReadDir(localeDir)
if err != nil {
panic(err)
}
if !slices.ContainsFunc(localeFiles, func(e fs.DirEntry) bool { return strings.HasSuffix(e.Name(), ".ini") }) {
fmt.Println("No locale files found")
os.Exit(1)
}
exitCode := 0
for _, localeFile := range localeFiles {
if !strings.HasSuffix(localeFile.Name(), ".ini") {
continue
}
localeContent, err := os.ReadFile(filepath.Join(localeDir, localeFile.Name()))
if err != nil {
panic(err)
}
if err := checkLocaleContent(localeContent); len(err) > 0 {
fmt.Println(localeFile.Name())
fmt.Println(strings.Join(err, "\n"))
fmt.Println()
exitCode = 1
}
}
os.Exit(exitCode)
}

65
build/lint-locale_test.go Normal file
View file

@ -0,0 +1,65 @@
// Copyright 2024 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package main
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestLocalizationPolicy(t *testing.T) {
initBlueMondayPolicy()
initRemoveTags()
t.Run("Remove tags", func(t *testing.T) {
assert.Empty(t, checkLocaleContent([]byte(`hidden_comment_types_description = Comment types checked here will not be shown inside issue pages. Checking "Label" for example removes all "<user> added/removed <label>" comments.`)))
assert.EqualValues(t, []string{"key: \x1b[31m<not-an-allowed-key>\x1b[0m REPLACED-TAG"}, checkLocaleContent([]byte(`key = "<not-an-allowed-key> <label>"`)))
assert.EqualValues(t, []string{"key: \x1b[31m<user@example.com>\x1b[0m REPLACED-TAG"}, checkLocaleContent([]byte(`key = "<user@example.com> <email@example.com>"`)))
assert.EqualValues(t, []string{"key: \x1b[31m<tag>\x1b[0m REPLACED-TAG \x1b[31m</tag>\x1b[0m"}, checkLocaleContent([]byte(`key = "<tag> <email@example.com> </tag>"`)))
})
t.Run("Specific exception", func(t *testing.T) {
assert.Empty(t, checkLocaleContent([]byte(`workflow.dispatch.trigger_found = This workflow has a <c>workflow_dispatch</c> event trigger.`)))
assert.Empty(t, checkLocaleContent([]byte(`pulls.title_desc_one = wants to merge %[1]d commit from <code>%[2]s</code> into <code id="%[4]s">%[3]s</code>`)))
assert.Empty(t, checkLocaleContent([]byte(`editor.commit_directly_to_this_branch = Commit directly to the <strong class="%[2]s">%[1]s</strong> branch.`)))
assert.EqualValues(t, []string{"workflow.dispatch.trigger_found: This workflow has a \x1b[31m<d>\x1b[0mworkflow_dispatch\x1b[31m</d>\x1b[0m event trigger."}, checkLocaleContent([]byte(`workflow.dispatch.trigger_found = This workflow has a <d>workflow_dispatch</d> event trigger.`)))
assert.EqualValues(t, []string{"key: <code\x1b[31m id=\"branch_targe\"\x1b[0m>%[3]s</code>"}, checkLocaleContent([]byte(`key = <code id="branch_targe">%[3]s</code>`)))
assert.EqualValues(t, []string{"key: <a\x1b[31m class=\"ui sh\"\x1b[0m href=\"https://TO-BE-REPLACED.COM\">"}, checkLocaleContent([]byte(`key = <a class="ui sh" href="%[3]s">`)))
assert.EqualValues(t, []string{"key: <a\x1b[31m class=\"js-click-me\"\x1b[0m href=\"https://TO-BE-REPLACED.COM\">"}, checkLocaleContent([]byte(`key = <a class="js-click-me" href="%[3]s">`)))
assert.EqualValues(t, []string{"key: <strong\x1b[31m class=\"branch-target\"\x1b[0m>%[1]s</strong>"}, checkLocaleContent([]byte(`key = <strong class="branch-target">%[1]s</strong>`)))
})
t.Run("General safe tags", func(t *testing.T) {
assert.Empty(t, checkLocaleContent([]byte("error404 = The page you are trying to reach either <strong>does not exist</strong> or <strong>you are not authorized</strong> to view it.")))
assert.Empty(t, checkLocaleContent([]byte("teams.specific_repositories_helper = Members will only have access to repositories explicitly added to the team. Selecting this <strong>will not</strong> automatically remove repositories already added with <i>All repositories</i>.")))
assert.Empty(t, checkLocaleContent([]byte("sqlite_helper = File path for the SQLite3 database.<br>Enter an absolute path if you run Forgejo as a service.")))
assert.Empty(t, checkLocaleContent([]byte("hi_user_x = Hi <b>%s</b>,")))
assert.EqualValues(t, []string{"error404: The page you are trying to reach either <strong\x1b[31m title='aaa'\x1b[0m>does not exist</strong> or <strong>you are not authorized</strong> to view it."}, checkLocaleContent([]byte("error404 = The page you are trying to reach either <strong title='aaa'>does not exist</strong> or <strong>you are not authorized</strong> to view it.")))
})
t.Run("<a>", func(t *testing.T) {
assert.Empty(t, checkLocaleContent([]byte(`admin.new_user.text = Please <a href="%s">click here</a> to manage this user from the admin panel.`)))
assert.Empty(t, checkLocaleContent([]byte(`access_token_desc = Selected token permissions limit authorization only to the corresponding <a href="%[1]s" target="_blank">API</a> routes. Read the <a href="%[2]s" target="_blank">documentation</a> for more information.`)))
assert.Empty(t, checkLocaleContent([]byte(`webauthn_desc = Security keys are hardware devices containing cryptographic keys. They can be used for two-factor authentication. Security keys must support the <a rel="noreferrer" target="_blank" href="%s">WebAuthn Authenticator</a> standard.`)))
assert.Empty(t, checkLocaleContent([]byte("issues.closed_at = `closed this issue <a id=\"%[1]s\" href=\"#%[1]s\">%[2]s</a>`")))
assert.EqualValues(t, []string{"key: \x1b[31m<a href=\"https://example.com\">\x1b[0m"}, checkLocaleContent([]byte(`key = <a href="https://example.com">`)))
assert.EqualValues(t, []string{"key: \x1b[31m<a href=\"javascript:alert('1')\">\x1b[0m"}, checkLocaleContent([]byte(`key = <a href="javascript:alert('1')">`)))
assert.EqualValues(t, []string{"key: <a href=\"https://TO-BE-REPLACED.COM\"\x1b[31m download\x1b[0m>"}, checkLocaleContent([]byte(`key = <a href="%s" download>`)))
assert.EqualValues(t, []string{"key: <a href=\"https://TO-BE-REPLACED.COM\"\x1b[31m target=\"_self\"\x1b[0m>"}, checkLocaleContent([]byte(`key = <a href="%s" target="_self">`)))
assert.EqualValues(t, []string{"key: \x1b[31m<a href=\"https://example.com/%s\">\x1b[0m"}, checkLocaleContent([]byte(`key = <a href="https://example.com/%s">`)))
assert.EqualValues(t, []string{"key: \x1b[31m<a href=\"https://example.com/?q=%s\">\x1b[0m"}, checkLocaleContent([]byte(`key = <a href="https://example.com/?q=%s">`)))
assert.EqualValues(t, []string{"key: \x1b[31m<a href=\"%s/open-redirect\">\x1b[0m"}, checkLocaleContent([]byte(`key = <a href="%s/open-redirect">`)))
assert.EqualValues(t, []string{"key: \x1b[31m<a href=\"%s?q=open-redirect\">\x1b[0m"}, checkLocaleContent([]byte(`key = <a href="%s?q=open-redirect">`)))
})
t.Run("Escaped HTML characters", func(t *testing.T) {
assert.Empty(t, checkLocaleContent([]byte("activity.git_stats_push_to_branch = `إلى %s و\"`")))
assert.EqualValues(t, []string{"key: و\x1b[31m&nbsp\x1b[0m\x1b[32m\u00a0\x1b[0m"}, checkLocaleContent([]byte(`key = و&nbsp;`)))
})
}

View file

@ -386,7 +386,7 @@ func (a *authService) addLdapSimpleAuth(c *cli.Context) error {
return a.createAuthSource(ctx, authSource)
}
// updateLdapBindDn updates a new LDAP (simple auth) authentication source.
// updateLdapSimpleAuth updates a new LDAP (simple auth) authentication source.
func (a *authService) updateLdapSimpleAuth(c *cli.Context) error {
ctx, cancel := installSignals()
defer cancel()

View file

@ -322,7 +322,8 @@ func runHookUpdate(c *cli.Context) error {
return fail(ctx, fmt.Sprintf("The deletion of %s is skipped as it's an internal reference.", refFullName), "")
}
return nil
// If the new comment isn't empty it means modification.
return fail(ctx, fmt.Sprintf("The modification of %s is skipped as it's an internal reference.", refFullName), "")
}
func runHookPostReceive(c *cli.Context) error {

View file

@ -180,8 +180,15 @@ func TestRunHookUpdate(t *testing.T) {
})
t.Run("Update of internal reference", func(t *testing.T) {
defer test.MockVariableValue(&cli.OsExiter, func(code int) {})()
defer test.MockVariableValue(&setting.IsProd, false)()
finish := captureOutput(t, os.Stderr)
err := app.Run([]string{"./forgejo", "update", "refs/pull/1/head", "0a51ae26bc73c47e2f754560c40904cf14ed51a9", "0000000000000000000000000000000000000001"})
require.NoError(t, err)
out := finish()
require.Error(t, err)
assert.Contains(t, out, "The modification of refs/pull/1/head is skipped as it's an internal reference.")
})
t.Run("Removal of branch", func(t *testing.T) {

View file

@ -91,7 +91,7 @@ func TestMigrateActionsArtifacts(t *testing.T) {
srcStorage, _ := createLocalStorage(t)
defer test.MockVariableValue(&storage.ActionsArtifacts, srcStorage)()
id := int64(0)
id := int64(42)
addArtifact := func(storagePath string, status actions.ArtifactStatus) {
id++

View file

@ -147,6 +147,12 @@ func runServ(c *cli.Context) error {
return nil
}
defer func() {
if err := recover(); err != nil {
_ = fail(ctx, "Internal Server Error", "Panic: %v\n%s", err, log.Stack(2))
}
}()
keys := strings.Split(c.Args().First(), "-")
if len(keys) != 2 || keys[0] != "key" {
return fail(ctx, "Key ID format error", "Invalid key argument: %s", c.Args().First())
@ -193,10 +199,7 @@ func runServ(c *cli.Context) error {
}
verb := words[0]
repoPath := words[1]
if repoPath[0] == '/' {
repoPath = repoPath[1:]
}
repoPath := strings.TrimPrefix(words[1], "/")
var lfsVerb string
if verb == lfsAuthenticateVerb {

View file

@ -1,4 +1,6 @@
{
"go.buildTags": "sqlite,sqlite_unlock_notify",
"go.testFlags": ["-v"]
"go.testFlags": ["-v"],
"go.lintTool": "golangci-lint",
"go.lintFlags": ["--fast"]
}

View file

@ -328,6 +328,10 @@ RUN_USER = ; git
;; Maximum number of locks returned per page
;LFS_LOCKS_PAGING_NUM = 50
;;
;; When clients make lfs batch requests, reject them if there are more pointers than this number
;; zero means 'unlimited'
;LFS_MAX_BATCH_SIZE = 0
;;
;; Allow graceful restarts using SIGHUP to fork
;ALLOW_GRACEFUL_RESTARTS = true
;;
@ -349,16 +353,25 @@ RUN_USER = ; git
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Database to use. Either "mysql", "postgres", "mssql" or "sqlite3".
;; Database to use. Either "sqlite3", "mySQL" or "postgres".
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; SQLite Configuration
;;
DB_TYPE = sqlite3
;PATH= ; defaults to data/forgejo.db
;SQLITE_TIMEOUT = ; Query timeout defaults to: 500
;SQLITE_JOURNAL_MODE = ; defaults to sqlite database default (often DELETE), can be used to enable WAL mode. https://www.sqlite.org/pragma.html#pragma_journal_mode
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; MySQL Configuration
;;
DB_TYPE = mysql
HOST = 127.0.0.1:3306 ; can use socket e.g. /var/run/mysqld/mysqld.sock
NAME = gitea
USER = root
;DB_TYPE = mysql
;HOST = 127.0.0.1:3306 ; can use socket e.g. /var/run/mysqld/mysqld.sock
;NAME = gitea
;USER = root
;PASSWD = ;Use PASSWD = `your password` for quoting if you use special characters in the password.
;SSL_MODE = false ; either "false" (default), "true", or "skip-verify"
;CHARSET_COLLATION = ; Empty as default, Gitea will try to find a case-sensitive collation. Don't change it unless you clearly know what you need.
@ -377,26 +390,6 @@ USER = root
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; SQLite Configuration
;;
;DB_TYPE = sqlite3
;PATH= ; defaults to data/forgejo.db
;SQLITE_TIMEOUT = ; Query timeout defaults to: 500
;SQLITE_JOURNAL_MODE = ; defaults to sqlite database default (often DELETE), can be used to enable WAL mode. https://www.sqlite.org/pragma.html#pragma_journal_mode
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; MSSQL Configuration
;;
;DB_TYPE = mssql
;HOST = 172.17.0.2:1433
;NAME = gitea
;USER = SA
;PASSWD = MwantsaSecurePassword1
;CHARSET_COLLATION = ; Empty as default, Gitea will try to find a case-sensitive collation. Don't change it unless you clearly know what you need.
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Other settings
;;
;; For iterate buffer, default is 50
@ -529,7 +522,8 @@ INTERNAL_TOKEN =
;; HMAC to encode urls with, it **is required** if camo is enabled.
;HMAC_KEY =
;; Set to true to use camo for https too lese only non https urls are proxyed
;ALLWAYS = false
;; ALLWAYS is deprecated and will be removed in the future
;ALWAYS = false
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -924,6 +918,24 @@ LEVEL = Info
;; Valid site url schemes for user profiles
;VALID_SITE_URL_SCHEMES=http,https
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;[service.explore]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Only allow signed in users to view the explore pages.
;REQUIRE_SIGNIN_VIEW = false
;;
;; Disable the users explore page.
;DISABLE_USERS_PAGE = false
;;
;; Disable the organizations explore page.
;DISABLE_ORGANIZATIONS_PAGE = false
;;
;; Disable the code explore page.
;DISABLE_CODE_PAGE = false
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -1926,7 +1938,7 @@ LEVEL = Info
;ENABLED = true
;;
;; 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
;ALLOWED_TYPES = .avif,.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
;;
;; Max size of each file. Defaults to 2048MB
;MAX_SIZE = 2048
@ -2295,7 +2307,7 @@ LEVEL = Info
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Delete all old actions from database
;; Delete all old activities from database
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;[cron.delete_old_actions]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -2653,6 +2665,10 @@ LEVEL = Info
;; override the minio base path if storage type is minio
;MINIO_BASE_PATH = lfs/
;[lfs_client]
;; When mirroring an upstream lfs endpoint, limit the number of pointers in each batch request to this number
;BATCH_SIZE = 20
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; settings for packages, will override storage setting

1170
eslint.config.mjs Normal file

File diff suppressed because it is too large Load diff

100
go.mod
View file

@ -1,20 +1,20 @@
module code.gitea.io/gitea
go 1.23.1
go 1.23.3
require (
code.forgejo.org/f3/gof3/v3 v3.7.0
code.forgejo.org/forgejo-contrib/go-libravatar v0.0.0-20191008002943-06d1c002b251
code.forgejo.org/forgejo/reply v1.0.2
code.forgejo.org/go-chi/cache v0.0.0-20240912103640-dcb08fba860d
code.forgejo.org/go-chi/captcha v0.0.0-20240905153133-df43b9250ed5
code.forgejo.org/go-chi/session v0.0.0-20240905153124-557e3de77cd2
code.forgejo.org/go-chi/binding v1.0.0
code.forgejo.org/go-chi/cache v1.0.0
code.forgejo.org/go-chi/captcha v1.0.0
code.forgejo.org/go-chi/session v1.0.0
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
connectrpc.com/connect v1.17.0
gitea.com/go-chi/binding v0.0.0-20240430071103-39a851e106ed
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
@ -23,9 +23,9 @@ require (
github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.7.2
github.com/alecthomas/chroma/v2 v2.14.0
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb
github.com/blevesearch/bleve/v2 v2.4.2
github.com/buildkite/terminal-to-html/v3 v3.16.2
github.com/caddyserver/certmagic v0.21.0
github.com/blevesearch/bleve/v2 v2.4.3
github.com/buildkite/terminal-to-html/v3 v3.16.4
github.com/caddyserver/certmagic v0.21.4
github.com/chi-middleware/proxy v1.1.1
github.com/djherbis/buffer v1.2.0
github.com/djherbis/nio/v3 v3.0.1
@ -34,14 +34,14 @@ require (
github.com/editorconfig/editorconfig-core-go/v2 v2.6.2
github.com/emersion/go-imap v1.2.1
github.com/felixge/fgprof v0.9.5
github.com/fsnotify/fsnotify v1.7.0
github.com/fsnotify/fsnotify v1.8.0
github.com/gliderlabs/ssh v0.3.7
github.com/go-ap/activitypub v0.0.0-20231114162308-e219254dc5c9
github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73
github.com/go-chi/chi/v5 v5.1.0
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.9
github.com/go-enry/go-enry/v2 v2.9.1
github.com/go-fed/httpsig v1.1.1-0.20201223112313-55836744818e
github.com/go-git/go-git/v5 v5.11.0
github.com/go-ldap/ldap/v3 v3.4.6
@ -54,28 +54,28 @@ require (
github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85
github.com/golang-jwt/jwt/v5 v5.2.1
github.com/google/go-github/v64 v64.0.0
github.com/google/pprof v0.0.0-20240528025155-186aa0362fba
github.com/google/pprof v0.0.0-20241017200806-017d972448fc
github.com/google/uuid v1.6.0
github.com/gorilla/feeds v1.2.0
github.com/gorilla/sessions v1.2.2
github.com/gorilla/sessions v1.4.0
github.com/h2non/gock v1.2.0
github.com/hashicorp/go-version v1.6.0
github.com/hashicorp/golang-lru/v2 v2.0.7
github.com/huandu/xstrings v1.5.0
github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056
github.com/jhillyerd/enmime v1.3.0
github.com/jhillyerd/enmime/v2 v2.0.0
github.com/json-iterator/go v1.1.12
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
github.com/klauspost/compress v1.17.9
github.com/klauspost/compress v1.17.11
github.com/klauspost/cpuid/v2 v2.2.8
github.com/lib/pq v1.10.9
github.com/markbates/goth v1.80.0
github.com/mattn/go-isatty v0.0.20
github.com/mattn/go-sqlite3 v1.14.22
github.com/meilisearch/meilisearch-go v0.28.0
github.com/mattn/go-sqlite3 v1.14.24
github.com/meilisearch/meilisearch-go v0.29.0
github.com/mholt/archiver/v3 v3.5.1
github.com/microcosm-cc/bluemonday v1.0.27
github.com/minio/minio-go/v7 v7.0.74
github.com/minio/minio-go/v7 v7.0.78
github.com/msteinert/pam v1.2.0
github.com/nektos/act v0.2.52
github.com/niklasfasching/go-org v1.7.0
@ -83,9 +83,8 @@ require (
github.com/opencontainers/go-digest v1.0.0
github.com/opencontainers/image-spec v1.1.0
github.com/pquerna/otp v1.4.0
github.com/prometheus/client_golang v1.18.0
github.com/quasoft/websspi v1.1.2
github.com/redis/go-redis/v9 v9.6.1
github.com/prometheus/client_golang v1.20.5
github.com/redis/go-redis/v9 v9.7.0
github.com/robfig/cron/v3 v3.0.1
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1
github.com/sassoftware/go-rpmutils v0.4.0
@ -94,22 +93,22 @@ require (
github.com/stretchr/testify v1.9.0
github.com/syndtr/goleveldb v1.0.0
github.com/ulikunitz/xz v0.5.12
github.com/urfave/cli/v2 v2.27.4
github.com/urfave/cli/v2 v2.27.5
github.com/valyala/fastjson v1.6.4
github.com/xanzy/go-gitlab v0.109.0
github.com/yohcop/openid-go v1.0.1
github.com/yuin/goldmark v1.7.4
github.com/yuin/goldmark v1.7.8
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
go.uber.org/mock v0.4.0
golang.org/x/crypto v0.27.0
golang.org/x/image v0.20.0
golang.org/x/net v0.29.0
golang.org/x/crypto v0.29.0
golang.org/x/image v0.21.0
golang.org/x/net v0.31.0
golang.org/x/oauth2 v0.23.0
golang.org/x/sys v0.25.0
golang.org/x/text v0.18.0
golang.org/x/tools v0.25.0
google.golang.org/grpc v1.66.2
google.golang.org/protobuf v1.34.2
golang.org/x/sys v0.27.0
golang.org/x/text v0.20.0
golang.org/x/tools v0.26.0
google.golang.org/grpc v1.68.0
google.golang.org/protobuf v1.35.1
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
gopkg.in/ini.v1 v1.67.0
gopkg.in/yaml.v3 v3.0.1
@ -119,7 +118,7 @@ require (
)
require (
cloud.google.com/go/compute/metadata v0.3.0 // indirect
cloud.google.com/go/compute/metadata v0.5.0 // 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
@ -138,13 +137,13 @@ 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.10 // indirect
github.com/blevesearch/bleve_index_api v1.1.12 // indirect
github.com/blevesearch/geo v0.1.20 // indirect
github.com/blevesearch/go-faiss v1.0.20 // indirect
github.com/blevesearch/go-faiss v1.0.23 // 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.15 // indirect
github.com/blevesearch/scorch_segment_api/v2 v2.2.16 // 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
@ -153,15 +152,15 @@ require (
github.com/blevesearch/zapx/v12 v12.3.10 // indirect
github.com/blevesearch/zapx/v13 v13.3.10 // indirect
github.com/blevesearch/zapx/v14 v14.3.10 // indirect
github.com/blevesearch/zapx/v15 v15.3.13 // indirect
github.com/blevesearch/zapx/v16 v16.1.5 // indirect
github.com/blevesearch/zapx/v15 v15.3.16 // indirect
github.com/blevesearch/zapx/v16 v16.1.8 // indirect
github.com/boombuler/barcode v1.0.1 // indirect
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 // indirect
github.com/caddyserver/zerossl v0.1.2 // indirect
github.com/caddyserver/zerossl v0.1.3 // indirect
github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cloudflare/circl v1.3.8 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.5 // 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
@ -223,9 +222,9 @@ require (
github.com/mailru/easyjson v0.7.7 // indirect
github.com/markbates/going v1.0.3 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/mholt/acmez/v2 v2.0.1 // indirect
github.com/miekg/dns v1.1.59 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/mholt/acmez/v2 v2.0.3 // indirect
github.com/miekg/dns v1.1.62 // indirect
github.com/minio/md5-simd v1.1.2 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
@ -234,6 +233,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mrjones/oauth v0.0.0-20190623134757-126b35219450 // indirect
github.com/mschoch/smat v0.2.0 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/nwaples/rardecode v1.1.3 // indirect
github.com/oklog/ulid v1.3.1 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
@ -244,13 +244,13 @@ require (
github.com/pjbgf/sha1cd v0.3.0 // indirect
github.com/pkg/errors v0.9.1 // 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/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.55.0 // indirect
github.com/prometheus/procfs v0.15.1 // 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/rs/xid v1.6.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
@ -271,7 +271,7 @@ require (
github.com/xanzy/ssh-agent v0.3.3 // indirect
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
github.com/zeebo/blake3 v0.2.3 // indirect
github.com/zeebo/blake3 v0.2.4 // indirect
go.etcd.io/bbolt v1.3.9 // indirect
go.mongodb.org/mongo-driver v1.13.1 // indirect
go.opentelemetry.io/otel v1.26.0 // indirect
@ -281,9 +281,9 @@ require (
go.uber.org/zap v1.27.0 // indirect
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect
golang.org/x/mod v0.21.0 // indirect
golang.org/x/sync v0.8.0 // indirect
golang.org/x/sync v0.9.0 // indirect
golang.org/x/time v0.5.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // 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
@ -293,6 +293,8 @@ 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 => code.forgejo.org/forgejo/act v1.21.2
replace github.com/nektos/act => code.forgejo.org/forgejo/act v1.22.0
replace github.com/mholt/archiver/v3 => code.forgejo.org/forgejo/archiver/v3 v3.5.1
replace github.com/goccy/go-json => github.com/grafana/go-json v0.0.0-20241115232854-f14426c40ff2

210
go.sum
View file

@ -1,21 +1,23 @@
cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc=
cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY=
cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY=
code.forgejo.org/f3/gof3/v3 v3.7.0 h1:ZfuCP8CGm8ZJbWmL+V0pUu3E0X4FCAA7GfRDy/y5/K4=
code.forgejo.org/f3/gof3/v3 v3.7.0/go.mod h1:oNhOeqD4DZYjVcNjQXIOdDX9b/1tqxi9ITLS8H9/Csw=
code.forgejo.org/forgejo-contrib/go-libravatar v0.0.0-20191008002943-06d1c002b251 h1:HTZl3CBk3ABNYtFI6TPLvJgGKFIhKT5CBk0sbOtkDKU=
code.forgejo.org/forgejo-contrib/go-libravatar v0.0.0-20191008002943-06d1c002b251/go.mod h1:PphB88CPbx601QrWPMZATeorACeVmQlyv3u+uUMbSaM=
code.forgejo.org/forgejo/act v1.21.2 h1:LERMtDNZDFXOYYYSU7Yduyyz7sN0t/Xnc1wFlupweiE=
code.forgejo.org/forgejo/act v1.21.2/go.mod h1:+PcvJ9iv+NTFeJSh79ra9Jbk9l0vvyA9D9me5/dbxYM=
code.forgejo.org/forgejo/act v1.22.0 h1:NbUf0+vQ48+ddwe4zVkINqnxKYl/to+NUvW7iisPA60=
code.forgejo.org/forgejo/act v1.22.0/go.mod h1:+PcvJ9iv+NTFeJSh79ra9Jbk9l0vvyA9D9me5/dbxYM=
code.forgejo.org/forgejo/archiver/v3 v3.5.1 h1:UmmbA7D5550uf71SQjarmrn6yKwOGxtEjb3jaYYtmSE=
code.forgejo.org/forgejo/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4=
code.forgejo.org/forgejo/reply v1.0.2 h1:dMhQCHV6/O3L5CLWNTol+dNzDAuyCK88z4J/lCdgFuQ=
code.forgejo.org/forgejo/reply v1.0.2/go.mod h1:RyZUfzQLc+fuLIGjTSQWDAJWPiL4WtKXB/FifT5fM7U=
code.forgejo.org/go-chi/cache v0.0.0-20240912103640-dcb08fba860d h1:nOu/2GX571t4intmtfvpctS148OqsBYrGUySVm93ifc=
code.forgejo.org/go-chi/cache v0.0.0-20240912103640-dcb08fba860d/go.mod h1:OVlZ/TqDYJ+RUJ+R+J+OLxtlyjo3pbjBeK7LAWAB+Vk=
code.forgejo.org/go-chi/captcha v0.0.0-20240905153133-df43b9250ed5 h1:A7P1liXCpJBHEJ5KIDsF0ujnQ8FQ/aX1UixTW0vGrDQ=
code.forgejo.org/go-chi/captcha v0.0.0-20240905153133-df43b9250ed5/go.mod h1:YLOsiln/arX3egGtxG4QNp49G2CIqP9pqD2VL56obLc=
code.forgejo.org/go-chi/session v0.0.0-20240905153124-557e3de77cd2 h1:Ht2myT1qf4YbLcO/W3pQaWTn6PPdKz0tM5tnqMOz/Cg=
code.forgejo.org/go-chi/session v0.0.0-20240905153124-557e3de77cd2/go.mod h1:oJs2Q5P5I7bzJGsgHt6fVzh2jlIr/9SLAvz/ZXb87BI=
code.forgejo.org/go-chi/binding v1.0.0 h1:EIDJtk9brK7WsT7rvS/D4cxX8XlnhY3LMy8ex1jeHu0=
code.forgejo.org/go-chi/binding v1.0.0/go.mod h1:fWwqaHj0H1/KeCpBqdvKunflq8pYfciEHI5v3UUeE2E=
code.forgejo.org/go-chi/cache v1.0.0 h1:akLfGxNlHcacmtutovNtYFSTMsbdcp5MGjAEsP4pxnE=
code.forgejo.org/go-chi/cache v1.0.0/go.mod h1:OVlZ/TqDYJ+RUJ+R+J+OLxtlyjo3pbjBeK7LAWAB+Vk=
code.forgejo.org/go-chi/captcha v1.0.0 h1:ZKVznXrPfruc1RMavCFBEINGxB3RAYr4I+WQAK8+eP0=
code.forgejo.org/go-chi/captcha v1.0.0/go.mod h1:YLOsiln/arX3egGtxG4QNp49G2CIqP9pqD2VL56obLc=
code.forgejo.org/go-chi/session v1.0.0 h1:1hjLWHpXkb4vs/g9rk/unhRL4AoKEqVUPJ+opI8UO3Y=
code.forgejo.org/go-chi/session v1.0.0/go.mod h1:lS76JFHZqGXYJTBHqwZ910UG046hIXAaYIN6J0Lf8sI=
code.gitea.io/actions-proto-go v0.4.0 h1:OsPBPhodXuQnsspG1sQ4eRE1PeoZyofd7+i73zCwnsU=
code.gitea.io/actions-proto-go v0.4.0/go.mod h1:mn7Wkqz6JbnTOHQpot3yDeHx+O5C9EGhMEE+htvHBas=
code.gitea.io/gitea-vet v0.2.3 h1:gdFmm6WOTM65rE8FUBTRzeQZYzXePKSSB1+r574hWwI=
@ -32,8 +34,6 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078 h1:cliQ4HHsCo6xi2oWZYKWW4bly/Ory9FuTpFPRxj/mAg=
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078/go.mod h1:g/V2Hjas6Z1UHUp4yIx6bATpNzJ7DYtD0FG3+xARWxs=
gitea.com/go-chi/binding v0.0.0-20240430071103-39a851e106ed h1:EZZBtilMLSZNWtHHcgq2mt6NSGhJSZBuduAlinMEmso=
gitea.com/go-chi/binding v0.0.0-20240430071103-39a851e106ed/go.mod h1:E3i3cgB04dDx0v3CytCgRTTn9Z/9x891aet3r456RVw=
gitea.com/lunny/levelqueue v0.4.2-0.20230414023320-3c0159fe0fe4 h1:IFT+hup2xejHqdhS7keYWioqfmxdnfblFDTGoOwcZ+o=
gitea.com/lunny/levelqueue v0.4.2-0.20230414023320-3c0159fe0fe4/go.mod h1:HBqmLbz56JWpfEGG0prskAV97ATNRoj5LDmPicD22hU=
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGqTOXqu2aRi/XEQxDCBwM8yJtE6s=
@ -98,22 +98,22 @@ github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJR
github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb h1:m935MPodAbYS46DG4pJSv7WO+VECIWUQ7OJYSoTrMh4=
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI=
github.com/blevesearch/bleve/v2 v2.4.2 h1:NooYP1mb3c0StkiY9/xviiq2LGSaE8BQBCc/pirMx0U=
github.com/blevesearch/bleve/v2 v2.4.2/go.mod h1:ATNKj7Yl2oJv/lGuF4kx39bST2dveX6w0th2FFYLkc8=
github.com/blevesearch/bleve_index_api v1.1.10 h1:PDLFhVjrjQWr6jCuU7TwlmByQVCSEURADHdCqVS9+g0=
github.com/blevesearch/bleve_index_api v1.1.10/go.mod h1:PbcwjIcRmjhGbkS/lJCpfgVSMROV6TRubGGAODaK1W8=
github.com/blevesearch/bleve/v2 v2.4.3 h1:XDYj+1prgX84L2Cf+V3ojrOPqXxy0qxyd2uLMmeuD+4=
github.com/blevesearch/bleve/v2 v2.4.3/go.mod h1:hEPDPrbYw3vyrm5VOa36GyS4bHWuIf4Fflp7460QQXY=
github.com/blevesearch/bleve_index_api v1.1.12 h1:P4bw9/G/5rulOF7SJ9l4FsDoo7UFJ+5kexNy1RXfegY=
github.com/blevesearch/bleve_index_api v1.1.12/go.mod h1:PbcwjIcRmjhGbkS/lJCpfgVSMROV6TRubGGAODaK1W8=
github.com/blevesearch/geo v0.1.20 h1:paaSpu2Ewh/tn5DKn/FB5SzvH0EWupxHEIwbCk/QPqM=
github.com/blevesearch/geo v0.1.20/go.mod h1:DVG2QjwHNMFmjo+ZgzrIq2sfCh6rIHzy9d9d0B59I6w=
github.com/blevesearch/go-faiss v1.0.20 h1:AIkdTQFWuZ5LQmKQSebgMR4RynGNw8ZseJXaan5kvtI=
github.com/blevesearch/go-faiss v1.0.20/go.mod h1:jrxHrbl42X/RnDPI+wBoZU8joxxuRwedrxqswQ3xfU8=
github.com/blevesearch/go-faiss v1.0.23 h1:Wmc5AFwDLKGl2L6mjLX1Da3vCL0EKa2uHHSorcIS1Uc=
github.com/blevesearch/go-faiss v1.0.23/go.mod h1:OMGQwOaRRYxrmeNdMrXJPvVx8gBnvE5RYrr0BahNnkk=
github.com/blevesearch/go-porterstemmer v1.0.3 h1:GtmsqID0aZdCSNiY8SkuPJ12pD4jI+DdXTAn4YRcHCo=
github.com/blevesearch/go-porterstemmer v1.0.3/go.mod h1:angGc5Ht+k2xhJdZi511LtmxuEf0OVpvUUNrwmM1P7M=
github.com/blevesearch/gtreap v0.1.1 h1:2JWigFrzDMR+42WGIN/V2p0cUvn4UP3C4Q5nmaZGW8Y=
github.com/blevesearch/gtreap v0.1.1/go.mod h1:QaQyDRAT51sotthUWAH4Sj08awFSSWzgYICSZ3w0tYk=
github.com/blevesearch/mmap-go v1.0.4 h1:OVhDhT5B/M1HNPpYPBKIEJaD0F3Si+CrEKULGCDPWmc=
github.com/blevesearch/mmap-go v1.0.4/go.mod h1:EWmEAOmdAS9z/pi/+Toxu99DnsbhG1TIxUoRmJw/pSs=
github.com/blevesearch/scorch_segment_api/v2 v2.2.15 h1:prV17iU/o+A8FiZi9MXmqbagd8I0bCqM7OKUYPbnb5Y=
github.com/blevesearch/scorch_segment_api/v2 v2.2.15/go.mod h1:db0cmP03bPNadXrCDuVkKLV6ywFSiRgPFT1YVrestBc=
github.com/blevesearch/scorch_segment_api/v2 v2.2.16 h1:uGvKVvG7zvSxCwcm4/ehBa9cCEuZVE+/zvrSl57QUVY=
github.com/blevesearch/scorch_segment_api/v2 v2.2.16/go.mod h1:VF5oHVbIFTu+znY1v30GjSpT5+9YFs9dV2hjvuh34F0=
github.com/blevesearch/segment v0.9.1 h1:+dThDy+Lvgj5JMxhmOVlgFfkUtZV2kw49xax4+jTfSU=
github.com/blevesearch/segment v0.9.1/go.mod h1:zN21iLm7+GnBHWTao9I+Au/7MBiL8pPFtJBJTsk6kQw=
github.com/blevesearch/snowballstem v0.9.0 h1:lMQ189YspGP6sXvZQ4WZ+MLawfV8wOmPoD/iWeNXm8s=
@ -130,10 +130,10 @@ github.com/blevesearch/zapx/v13 v13.3.10 h1:0KY9tuxg06rXxOZHg3DwPJBjniSlqEgVpxIq
github.com/blevesearch/zapx/v13 v13.3.10/go.mod h1:w2wjSDQ/WBVeEIvP0fvMJZAzDwqwIEzVPnCPrz93yAk=
github.com/blevesearch/zapx/v14 v14.3.10 h1:SG6xlsL+W6YjhX5N3aEiL/2tcWh3DO75Bnz77pSwwKU=
github.com/blevesearch/zapx/v14 v14.3.10/go.mod h1:qqyuR0u230jN1yMmE4FIAuCxmahRQEOehF78m6oTgns=
github.com/blevesearch/zapx/v15 v15.3.13 h1:6EkfaZiPlAxqXz0neniq35my6S48QI94W/wyhnpDHHQ=
github.com/blevesearch/zapx/v15 v15.3.13/go.mod h1:Turk/TNRKj9es7ZpKK95PS7f6D44Y7fAFy8F4LXQtGg=
github.com/blevesearch/zapx/v16 v16.1.5 h1:b0sMcarqNFxuXvjoXsF8WtwVahnxyhEvBSRJi/AUHjU=
github.com/blevesearch/zapx/v16 v16.1.5/go.mod h1:J4mSF39w1QELc11EWRSBFkPeZuO7r/NPKkHzDCoiaI8=
github.com/blevesearch/zapx/v15 v15.3.16 h1:Ct3rv7FUJPfPk99TI/OofdC+Kpb4IdyfdMH48sb+FmE=
github.com/blevesearch/zapx/v15 v15.3.16/go.mod h1:Turk/TNRKj9es7ZpKK95PS7f6D44Y7fAFy8F4LXQtGg=
github.com/blevesearch/zapx/v16 v16.1.8 h1:Bxzpw6YQpFs7UjoCV1+RvDw6fmAT2GZxldwX8b3wVBM=
github.com/blevesearch/zapx/v16 v16.1.8/go.mod h1:JqQlOqlRVaYDkpLIl3JnKql8u4zKTNlVEa3nLsi0Gn8=
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/boombuler/barcode v1.0.1 h1:NDBbPmhS+EqABEs5Kg3n/5ZNjy73Pz7SIV+KCeqyXcs=
github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
@ -143,13 +143,13 @@ github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
github.com/buildkite/terminal-to-html/v3 v3.16.2 h1:ueVE+BUqKOK3O4p+oul1y4Lo0sq7Qoj2Fb6/DJOrxYM=
github.com/buildkite/terminal-to-html/v3 v3.16.2/go.mod h1:tdi6+MA4AjV5udS5cm8PVxLHsbJWLGsr5W/tHFzPgbY=
github.com/buildkite/terminal-to-html/v3 v3.16.4 h1:QFYO8IGvRnp7tGgiQb8g9uFU8kY9wOzxsFFx17+yy6Q=
github.com/buildkite/terminal-to-html/v3 v3.16.4/go.mod h1:r/J7cC9c3EzBzP3/wDz0RJLPwv5PUAMp+KF2w+ntMc0=
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
github.com/caddyserver/certmagic v0.21.0 h1:yDoifClc4hIxhHer3AxUj4buhF+NzRR6torw/AOnuUE=
github.com/caddyserver/certmagic v0.21.0/go.mod h1:OgUZNXYV/ylYoFJNmoYVR5nntydLNMQISePPgqZTyhc=
github.com/caddyserver/zerossl v0.1.2 h1:tlEu1VzWGoqcCpivs9liKAKhfpJWYJkHEMmlxRbVAxE=
github.com/caddyserver/zerossl v0.1.2/go.mod h1:wtiJEHbdvunr40ZzhXlnIkOB8Xj4eKtBKizCcZitJiQ=
github.com/caddyserver/certmagic v0.21.4 h1:e7VobB8rffHv8ZZpSiZtEwnLDHUwLVYLWzWSa1FfKI0=
github.com/caddyserver/certmagic v0.21.4/go.mod h1:swUXjQ1T9ZtMv95qj7/InJvWLXURU85r+CfG0T+ZbDE=
github.com/caddyserver/zerossl v0.1.3 h1:onS+pxp3M8HnHpN5MMbOMyNjmTheJyWRaZYwn+YTAyA=
github.com/caddyserver/zerossl v0.1.3/go.mod h1:CxA0acn7oEGO6//4rtrRjYgEoa4MFw/XofZnrYwGqG4=
github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a h1:MISbI8sU/PSK/ztvmWKFcI7UGb5/HQT7B+i3a2myKgI=
github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a/go.mod h1:2GxOXOlEPAMFPfp014mK1SWq8G8BN8o7/dfYqJrVGn8=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
@ -165,8 +165,8 @@ github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
github.com/cloudflare/circl v1.3.8 h1:j+V8jJt09PoeMFIu2uh5JUyEaIHTXVOHslFoLNAKqwI=
github.com/cloudflare/circl v1.3.8/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZFnBQS5QU=
github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
@ -221,8 +221,8 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE=
@ -242,8 +242,8 @@ github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4=
github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
github.com/go-co-op/gocron v1.37.0 h1:ZYDJGtQ4OMhTLKOKMIch+/CY70Brbb1dGdooLEhh7b0=
github.com/go-co-op/gocron v1.37.0/go.mod h1:3L/n6BkO7ABj+TrfSVXLRzsP26zmikL4ISkLQ0O8iNY=
github.com/go-enry/go-enry/v2 v2.8.9 h1:vskZIABoxInDd5sHY49t+C/VgF8RWxRdRMoH5AdLqQU=
github.com/go-enry/go-enry/v2 v2.8.9/go.mod h1:9yrj4ES1YrbNb1Wb7/PWYr2bpaCXUGRt0uafN0ISyG8=
github.com/go-enry/go-enry/v2 v2.9.1 h1:G9iDteJ/Mc0F4Di5NeQknf83R2OkRbwY9cAYmcqVG6U=
github.com/go-enry/go-enry/v2 v2.9.1/go.mod h1:9yrj4ES1YrbNb1Wb7/PWYr2bpaCXUGRt0uafN0ISyG8=
github.com/go-enry/go-oniguruma v1.2.1 h1:k8aAMuJfMrqm/56SG2lV9Cfti6tC4x8673aHCcBk+eo=
github.com/go-enry/go-oniguruma v1.2.1/go.mod h1:bWDhYP+S6xZQgiRL7wlTScFYBe023B6ilRZbCAD5Hf4=
github.com/go-faster/city v1.0.1 h1:4WAxSZ3V2Ws4QRDrscLEDcibJY8uf41H6AhXDrNDcGw=
@ -294,8 +294,8 @@ github.com/go-swagger/go-swagger v0.30.5/go.mod h1:cWUhSyCNqV7J1wkkxfr5QmbcnCewe
github.com/go-swagger/scan-repo-boundary v0.0.0-20180623220736-973b3573c013 h1:l9rI6sNaZgNC0LnF3MiE+qTmyBA/tZAg1rtyrGbUMK0=
github.com/go-swagger/scan-repo-boundary v0.0.0-20180623220736-973b3573c013/go.mod h1:b65mBPzqzZWxOZGxSWrqs4GInLIn+u99Q9q7p+GKni0=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg=
github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U=
github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
github.com/go-testfixtures/testfixtures/v3 v3.12.0 h1:Ew0+c2o1mXSUqMwjuNup3MK/vw1HkLS3ILljX5C6lVE=
github.com/go-testfixtures/testfixtures/v3 v3.12.0/go.mod h1:13F0m6/DtqqSDso9IAVuhbZ4I7AiRAHrolmDMu9v5vY=
github.com/go-webauthn/webauthn v0.11.2 h1:Fgx0/wlmkClTKlnOsdOQ+K5HcHDsDcYIvtYmfhEOSUc=
@ -307,8 +307,6 @@ github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJA
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY=
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f h1:3BSP1Tbs2djlpprl7wCLuiqMaUh5SJkkzI2gDs+FgLs=
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f/go.mod h1:Pcatq5tYkCW2Q6yrR2VRHlbHpZ/R4/7qyL1TCF7vl14=
@ -360,8 +358,8 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
github.com/google/pprof v0.0.0-20240528025155-186aa0362fba h1:ql1qNgCyOB7iAEk8JTNM+zJrgIbnyCKX/wdlyPufP5g=
github.com/google/pprof v0.0.0-20240528025155-186aa0362fba/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
github.com/google/pprof v0.0.0-20241017200806-017d972448fc h1:NGyrhhFhwvRAZg02jnYVg3GBQy0qGBKmFQJwaPmpmxs=
github.com/google/pprof v0.0.0-20241017200806-017d972448fc/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@ -379,12 +377,12 @@ github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
github.com/gorilla/pat v0.0.0-20180118222023-199c85a7f6d1 h1:LqbZZ9sNMWVjeXS4NN5oVvhMjDyLhmA1LG86oSo+IqY=
github.com/gorilla/pat v0.0.0-20180118222023-199c85a7f6d1/go.mod h1:YeAe0gNeiNT5hoiZRI4yiOky6jVdNvfO2N6Kav/HmxY=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA=
github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo=
github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
github.com/gorilla/sessions v1.2.2 h1:lqzMYz6bOfvn2WriPUjNByzeXIlVzURcPmgMczkmTjY=
github.com/gorilla/sessions v1.2.2/go.mod h1:ePLdVu+jbEgHH+KWw8I1z2wqd0BAdAQh/8LRvBeoNcQ=
github.com/gorilla/sessions v1.4.0 h1:kpIYOp/oi6MG/p5PgxApU8srsSw9tuFbt46Lt7auzqQ=
github.com/gorilla/sessions v1.4.0/go.mod h1:FLWm50oby91+hl7p/wRxDth9bWSuk0qVL2emc7lT5ik=
github.com/grafana/go-json v0.0.0-20241115232854-f14426c40ff2 h1:8xGrYqQ1GM4aaMk7pNDfecBdL/VGhEbpvvGBoqO6BIY=
github.com/grafana/go-json v0.0.0-20241115232854-f14426c40ff2/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/h2non/gock v1.2.0 h1:K6ol8rfrRkUOefooBC8elXoaNGYkpp7y2qcxGG6BzUE=
github.com/h2non/gock v1.2.0/go.mod h1:tNhoxHYW2W42cYkYb1WqzdbYIieALC99kpYr7rH/BQk=
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
@ -431,8 +429,8 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOl
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc=
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
github.com/jhillyerd/enmime v1.3.0 h1:LV5kzfLidiOr8qRGIpYYmUZCnhrPbcFAnAFUnWn99rw=
github.com/jhillyerd/enmime v1.3.0/go.mod h1:6c6jg5HdRRV2FtvVL69LjiX1M8oE0xDX9VEhV3oy4gs=
github.com/jhillyerd/enmime/v2 v2.0.0 h1:I39PYf0peLGroKq+uX2yGB1ExH/78HcRJy4VmERQAVk=
github.com/jhillyerd/enmime/v2 v2.0.0/go.mod h1:wQkz7BochDzSukAz5ajAQaXOB7pEg5Vh5QWs7m1uAPw=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
@ -448,11 +446,10 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM=
github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
@ -467,6 +464,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
@ -488,22 +487,22 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/meilisearch/meilisearch-go v0.28.0 h1:f3XJ66ZM+R8bANAOLqsjvoq/HhQNpVJPYoNt6QgNzME=
github.com/meilisearch/meilisearch-go v0.28.0/go.mod h1:Szcc9CaDiKIfjdgdt49jlmDKpEzjD+x+b6Y6heMdlQ0=
github.com/mholt/acmez/v2 v2.0.1 h1:3/3N0u1pLjMK4sNEAFSI+bcvzbPhRpY383sy1kLHJ6k=
github.com/mholt/acmez/v2 v2.0.1/go.mod h1:fX4c9r5jYwMyMsC+7tkYRxHibkOTgta5DIFGoe67e1U=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM=
github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/meilisearch/meilisearch-go v0.29.0 h1:HZ9NEKN59USINQ/DXJge/aaXq8IrsKbXGTdAoBaaDz4=
github.com/meilisearch/meilisearch-go v0.29.0/go.mod h1:2cRCAn4ddySUsFfNDLVPod/plRibQsJkXF/4gLhxbOk=
github.com/mholt/acmez/v2 v2.0.3 h1:CgDBlEwg3QBp6s45tPQmFIBrkRIkBT4rW4orMM6p4sw=
github.com/mholt/acmez/v2 v2.0.3/go.mod h1:pQ1ysaDeGrIMvJ9dfJMk5kJNkn7L2sb3UhyrX6Q91cw=
github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk=
github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA=
github.com/miekg/dns v1.1.59 h1:C9EXc/UToRwKLhK5wKU/I4QVsBUc8kE6MkHBkeypWZs=
github.com/miekg/dns v1.1.59/go.mod h1:nZpewl5p6IvctfgrckopVx2OlSEHPRO/U4SYkRklrEk=
github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ=
github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ=
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
github.com/minio/minio-go/v7 v7.0.74 h1:fTo/XlPBTSpo3BAMshlwKL5RspXRv9us5UeHEGYCFe0=
github.com/minio/minio-go/v7 v7.0.74/go.mod h1:qydcVzV8Hqtj1VtEocfxbmVFa2siu6HGa+LDEPogjD8=
github.com/minio/minio-go/v7 v7.0.78 h1:LqW2zy52fxnI4gg8C2oZviTaKHcBV36scS+RzJnxUFs=
github.com/minio/minio-go/v7 v7.0.78/go.mod h1:84gmIilaX4zcvAWWzJ5Z1WI5axN+hAbM5w25xf8xvC0=
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
@ -524,6 +523,8 @@ github.com/mschoch/smat v0.2.0 h1:8imxQsjDm8yFEAVBe7azKmKSgzSkZXDuKkSq9374khM=
github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOlotKw=
github.com/msteinert/pam v1.2.0 h1:mYfjlvN2KYs2Pb9G6nb/1f/nPfAttT/Jee5Sq9r3bGE=
github.com/msteinert/pam v1.2.0/go.mod h1:d2n0DCUK8rGecChV3JzvmsDjOY4R7AYbsNxAT+ftQl0=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 h1:W6apQkHrMkS0Muv8G/TipAy/FJl/rCYT0+EuS8+Z0z4=
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
github.com/niklasfasching/go-org v1.7.0 h1:vyMdcMWWTe/XmANk19F4k8XGBYg0GQ/gJGMimOjGMek=
@ -573,18 +574,16 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pquerna/otp v1.4.0 h1:wZvl1TIVxKRThZIBiwOOHOGP/1+nZyWBil9Y2XNEDzg=
github.com/pquerna/otp v1.4.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk=
github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA=
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
github.com/prometheus/common v0.46.0 h1:doXzt5ybi1HBKpsZOL0sSkaNHJJqkyfEWZGGqqScV0Y=
github.com/prometheus/common v0.46.0/go.mod h1:Tp0qkxpb9Jsg54QMe+EAmqXkSV7Evdy1BTn+g2pa/hQ=
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
github.com/quasoft/websspi v1.1.2 h1:/mA4w0LxWlE3novvsoEL6BBA1WnjJATbjkh1kFrTidw=
github.com/quasoft/websspi v1.1.2/go.mod h1:HmVdl939dQ0WIXZhyik+ARdI03M6bQzaSEKcgpFmewk=
github.com/redis/go-redis/v9 v9.6.1 h1:HHDteefn6ZkTtY5fGUE8tj8uy85AHk6zP7CpzIAM0y4=
github.com/redis/go-redis/v9 v9.6.1/go.mod h1:0C0c6ycQsdpVNQpxb1njEQIqkx5UcsM8FJCQLgE9+RA=
github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc=
github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/redis/go-redis/v9 v9.7.0 h1:HhLSs+B6O021gwzl+locl0zEDnyNkxMtf/Z3NNBMa9E=
github.com/redis/go-redis/v9 v9.7.0/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rhysd/actionlint v1.6.27 h1:xxwe8YmveBcC8lydW6GoHMGmB6H/MTqUU60F2p10wjw=
@ -599,8 +598,8 @@ github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc=
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU=
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
@ -666,8 +665,8 @@ github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oW
github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc=
github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/urfave/cli/v2 v2.27.4 h1:o1owoI+02Eb+K107p27wEX9Bb8eqIoZCfLXloLUSWJ8=
github.com/urfave/cli/v2 v2.27.4/go.mod h1:m4QzxcD2qpra4z7WhzEGn74WZLViBnMpb1ToCAKdGRQ=
github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w=
github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ=
github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
@ -693,14 +692,14 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yuin/goldmark v1.4.15/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yuin/goldmark v1.7.4 h1:BDXOHExt+A7gwPCJgPIIq7ENvceR7we7rOS9TNoLZeg=
github.com/yuin/goldmark v1.7.4/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
github.com/yuin/goldmark v1.7.8 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic=
github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc h1:+IAOyRda+RLrxa1WC7umKOZRsGq4QrFFMYApOeHzQwQ=
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc/go.mod h1:ovIvrum6DQJA4QsJSovrkC4saKHQVs7TvcaeO8AIl5I=
github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY=
github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
github.com/zeebo/blake3 v0.2.3 h1:TFoLXsjeXqRNFxSbk35Dk4YtszE/MQQGK10BH4ptoTg=
github.com/zeebo/blake3 v0.2.3/go.mod h1:mjJjZpnsyIVtVgTOSpJ9vmRE4wgDeyt2HU3qXvvKCaQ=
github.com/zeebo/blake3 v0.2.4 h1:KYQPkhpRtcqh0ssGYcKLG1JYvddkEA8QwCM/yBqhaZI=
github.com/zeebo/blake3 v0.2.4/go.mod h1:7eeQ6d2iXWRGF6npfaxl2CU+xy2Fjo2gxeyZGCRUjcE=
github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo=
github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4=
go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI=
@ -734,12 +733,12 @@ golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2Uz
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA=
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
golang.org/x/image v0.20.0 h1:7cVCUjQwfL18gyBJOmYvptfSHS8Fb3YUDtfLIZ7Nbpw=
golang.org/x/image v0.20.0/go.mod h1:0a88To4CYVBAHp5FXJm8o7QbUl37Vd85ply1vyD8auM=
golang.org/x/image v0.21.0 h1:c5qV36ajHpdj4Qi0GnE0jUc/yuo33OLFaa0d+crTD5s=
golang.org/x/image v0.21.0/go.mod h1:vUbsLavqK/W303ZroQQVKQ+Af3Yl6Uz1Ppu5J/cLz78=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
@ -761,8 +760,8 @@ golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo=
golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM=
golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -772,14 +771,13 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -803,8 +801,8 @@ golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
@ -814,8 +812,8 @@ golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM=
golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8=
golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU=
golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@ -827,8 +825,8 @@ golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@ -839,16 +837,16 @@ golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.25.0 h1:oFU9pkj/iJgs+0DT+VMHrx+oBKs/LJMV+Uvg78sl+fE=
golang.org/x/tools v0.25.0/go.mod h1:/vtpO8WL1N9cQC3FN5zPqb//fRXskFHbLKk4OW1Q7rg=
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 h1:1GBuWVLM/KMVUv1t1En5Gs+gFZCNd360GGb4sSxtrhU=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0=
google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo=
google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
google.golang.org/grpc v1.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0=
google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@ -857,8 +855,8 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View file

@ -69,7 +69,7 @@ func CreateArtifact(ctx context.Context, t *ActionTask, artifactName, artifactPa
OwnerID: t.OwnerID,
CommitSHA: t.CommitSHA,
Status: int64(ArtifactStatusUploadPending),
ExpiredUnix: timeutil.TimeStamp(time.Now().Unix() + 3600*24*expiredDays),
ExpiredUnix: timeutil.TimeStamp(time.Now().Unix() + timeutil.Day*expiredDays),
}
if _, err := db.GetEngine(ctx).Insert(artifact); err != nil {
return nil, err
@ -78,6 +78,13 @@ func CreateArtifact(ctx context.Context, t *ActionTask, artifactName, artifactPa
} else if err != nil {
return nil, err
}
if _, err := db.GetEngine(ctx).ID(artifact.ID).Cols("expired_unix").Update(&ActionArtifact{
ExpiredUnix: timeutil.TimeStamp(time.Now().Unix() + timeutil.Day*expiredDays),
}); err != nil {
return nil, err
}
return artifact, nil
}

View file

@ -146,7 +146,11 @@ func (run *ActionRun) GetPushEventPayload() (*api.PushPayload, error) {
}
func (run *ActionRun) GetPullRequestEventPayload() (*api.PullRequestPayload, error) {
if run.Event == webhook_module.HookEventPullRequest || run.Event == webhook_module.HookEventPullRequestSync {
if run.Event == webhook_module.HookEventPullRequest ||
run.Event == webhook_module.HookEventPullRequestSync ||
run.Event == webhook_module.HookEventPullRequestAssign ||
run.Event == webhook_module.HookEventPullRequestMilestone ||
run.Event == webhook_module.HookEventPullRequestLabel {
var payload api.PullRequestPayload
if err := json.Unmarshal([]byte(run.EventPayload), &payload); err != nil {
return nil, err

View file

@ -118,12 +118,13 @@ func DeleteScheduleTaskByRepo(ctx context.Context, id int64) error {
return committer.Commit()
}
func CleanRepoScheduleTasks(ctx context.Context, repo *repo_model.Repository) error {
func CleanRepoScheduleTasks(ctx context.Context, repo *repo_model.Repository, cancelPreviousJobs bool) error {
// If actions disabled when there is schedule task, this will remove the outdated schedule tasks
// There is no other place we can do this because the app.ini will be changed manually
if err := DeleteScheduleTaskByRepo(ctx, repo.ID); err != nil {
return fmt.Errorf("DeleteCronTaskByRepo: %v", err)
}
if cancelPreviousJobs {
// cancel running cron jobs of this repository and delete old schedules
if err := CancelPreviousJobs(
ctx,
@ -134,5 +135,6 @@ func CleanRepoScheduleTasks(ctx context.Context, repo *repo_model.Repository) er
); err != nil {
return fmt.Errorf("CancelPreviousJobs: %v", err)
}
}
return nil
}

View file

@ -10,6 +10,7 @@ import (
_ "code.gitea.io/gitea/models"
_ "code.gitea.io/gitea/models/actions"
_ "code.gitea.io/gitea/models/forgefed"
)
func TestMain(m *testing.M) {

View file

@ -34,6 +34,7 @@ type ActivityStats struct {
OpenedPRAuthorCount int64
MergedPRs issues_model.PullRequestList
MergedPRAuthorCount int64
ActiveIssues issues_model.IssueList
OpenedIssues issues_model.IssueList
OpenedIssueAuthorCount int64
ClosedIssues issues_model.IssueList
@ -172,7 +173,7 @@ func (stats *ActivityStats) MergedPRPerc() int {
// ActiveIssueCount returns total active issue count
func (stats *ActivityStats) ActiveIssueCount() int {
return stats.OpenedIssueCount() + stats.ClosedIssueCount()
return len(stats.ActiveIssues)
}
// OpenedIssueCount returns open issue count
@ -285,13 +286,21 @@ func (stats *ActivityStats) FillIssues(ctx context.Context, repoID int64, fromTi
stats.ClosedIssueAuthorCount = count
// New issues
sess = issuesForActivityStatement(ctx, repoID, fromTime, false, false)
sess = newlyCreatedIssues(ctx, repoID, fromTime)
sess.OrderBy("issue.created_unix ASC")
stats.OpenedIssues = make(issues_model.IssueList, 0)
if err = sess.Find(&stats.OpenedIssues); err != nil {
return err
}
// Active issues
sess = activeIssues(ctx, repoID, fromTime)
sess.OrderBy("issue.created_unix ASC")
stats.ActiveIssues = make(issues_model.IssueList, 0)
if err = sess.Find(&stats.ActiveIssues); err != nil {
return err
}
// Opened issue authors
sess = issuesForActivityStatement(ctx, repoID, fromTime, false, false)
if _, err = sess.Select("count(distinct issue.poster_id) as `count`").Table("issue").Get(&count); err != nil {
@ -317,6 +326,22 @@ func (stats *ActivityStats) FillUnresolvedIssues(ctx context.Context, repoID int
return sess.Find(&stats.UnresolvedIssues)
}
func newlyCreatedIssues(ctx context.Context, repoID int64, fromTime time.Time) *xorm.Session {
sess := db.GetEngine(ctx).Where("issue.repo_id = ?", repoID).
And("issue.is_pull = ?", false). // Retain the is_pull check to exclude pull requests
And("issue.created_unix >= ?", fromTime.Unix()) // Include all issues created after fromTime
return sess
}
func activeIssues(ctx context.Context, repoID int64, fromTime time.Time) *xorm.Session {
sess := db.GetEngine(ctx).Where("issue.repo_id = ?", repoID).
And("issue.is_pull = ?", false).
And("issue.created_unix >= ? OR issue.closed_unix >= ?", fromTime.Unix(), fromTime.Unix())
return sess
}
func issuesForActivityStatement(ctx context.Context, repoID int64, fromTime time.Time, closed, unresolved bool) *xorm.Session {
sess := db.GetEngine(ctx).Where("issue.repo_id = ?", repoID).
And("issue.is_closed = ?", closed)

View file

@ -0,0 +1,30 @@
// Copyright 2024 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package activities
import (
"testing"
"time"
"code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestGetActivityStats(t *testing.T) {
require.NoError(t, unittest.PrepareTestDatabase())
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
stats, err := GetActivityStats(db.DefaultContext, repo, time.Unix(0, 0), true, true, true, true)
require.NoError(t, err)
assert.EqualValues(t, 2, stats.ActiveIssueCount())
assert.EqualValues(t, 2, stats.OpenedIssueCount())
assert.EqualValues(t, 0, stats.ClosedIssueCount())
assert.EqualValues(t, 3, stats.ActivePRCount())
}

View file

@ -96,6 +96,6 @@ func TestGetUserHeatmapDataByUser(t *testing.T) {
// Test JSON rendering
jsonData, err := json.Marshal(heatmap)
require.NoError(t, err)
assert.Equal(t, tc.JSONResult, string(jsonData))
assert.JSONEq(t, tc.JSONResult, string(jsonData))
}
}

View file

@ -15,12 +15,31 @@ import (
"code.gitea.io/gitea/modules/util"
)
type AuthorizationPurpose string
var (
// Used to store long term authorization tokens.
LongTermAuthorization AuthorizationPurpose = "long_term_authorization"
// Used to activate a user account.
UserActivation AuthorizationPurpose = "user_activation"
// Used to reset the password.
PasswordReset AuthorizationPurpose = "password_reset"
)
// Used to activate the specified email address for a user.
func EmailActivation(email string) AuthorizationPurpose {
return AuthorizationPurpose("email_activation:" + email)
}
// AuthorizationToken represents a authorization token to a user.
type AuthorizationToken struct {
ID int64 `xorm:"pk autoincr"`
UID int64 `xorm:"INDEX"`
LookupKey string `xorm:"INDEX UNIQUE"`
HashedValidator string
Purpose AuthorizationPurpose `xorm:"NOT NULL DEFAULT 'long_term_authorization'"`
Expiry timeutil.TimeStamp
}
@ -41,7 +60,7 @@ func (authToken *AuthorizationToken) IsExpired() bool {
// GenerateAuthToken generates a new authentication token for the given user.
// It returns the lookup key and validator values that should be passed to the
// user via a long-term cookie.
func GenerateAuthToken(ctx context.Context, userID int64, expiry timeutil.TimeStamp) (lookupKey, validator string, err error) {
func GenerateAuthToken(ctx context.Context, userID int64, expiry timeutil.TimeStamp, purpose AuthorizationPurpose) (lookupKey, validator string, err error) {
// Request 64 random bytes. The first 32 bytes will be used for the lookupKey
// and the other 32 bytes will be used for the validator.
rBytes, err := util.CryptoRandomBytes(64)
@ -56,14 +75,15 @@ func GenerateAuthToken(ctx context.Context, userID int64, expiry timeutil.TimeSt
Expiry: expiry,
LookupKey: lookupKey,
HashedValidator: HashValidator(rBytes[32:]),
Purpose: purpose,
})
return lookupKey, validator, err
}
// FindAuthToken will find a authorization token via the lookup key.
func FindAuthToken(ctx context.Context, lookupKey string) (*AuthorizationToken, error) {
func FindAuthToken(ctx context.Context, lookupKey string, purpose AuthorizationPurpose) (*AuthorizationToken, error) {
var authToken AuthorizationToken
has, err := db.GetEngine(ctx).Where("lookup_key = ?", lookupKey).Get(&authToken)
has, err := db.GetEngine(ctx).Where("lookup_key = ? AND purpose = ?", lookupKey, purpose).Get(&authToken)
if err != nil {
return nil, err
} else if !has {

View file

@ -12,6 +12,7 @@ import (
_ "code.gitea.io/gitea/models/actions"
_ "code.gitea.io/gitea/models/activities"
_ "code.gitea.io/gitea/models/auth"
_ "code.gitea.io/gitea/models/forgefed"
_ "code.gitea.io/gitea/models/perm/access"
)

View file

@ -0,0 +1,71 @@
-
id: 1
run_id: 791
runner_id: 1
repo_id: 4
owner_id: 1
commit_sha: c2d72f548424103f01ee1dc02889c1e2bff816b0
storage_path: "26/1/1712166500347189545.chunk"
file_size: 1024
file_compressed_size: 1024
content_encoding: ""
artifact_path: "abc.txt"
artifact_name: "artifact-download"
status: 1
created_unix: 1712338649
updated_unix: 1712338649
expired_unix: 1720114649
-
id: 19
run_id: 791
runner_id: 1
repo_id: 4
owner_id: 1
commit_sha: c2d72f548424103f01ee1dc02889c1e2bff816b0
storage_path: "26/19/1712348022422036662.chunk"
file_size: 1024
file_compressed_size: 1024
content_encoding: ""
artifact_path: "abc.txt"
artifact_name: "multi-file-download"
status: 2
created_unix: 1712348022
updated_unix: 1712348022
expired_unix: 1720124022
-
id: 20
run_id: 791
runner_id: 1
repo_id: 4
owner_id: 1
commit_sha: c2d72f548424103f01ee1dc02889c1e2bff816b0
storage_path: "26/20/1712348022423431524.chunk"
file_size: 1024
file_compressed_size: 1024
content_encoding: ""
artifact_path: "xyz/def.txt"
artifact_name: "multi-file-download"
status: 2
created_unix: 1712348022
updated_unix: 1712348022
expired_unix: 1720124022
-
id: 22
run_id: 792
runner_id: 1
repo_id: 4
owner_id: 1
commit_sha: c2d72f548424103f01ee1dc02889c1e2bff816b0
storage_path: "27/5/1730330775594233150.chunk"
file_size: 1024
file_compressed_size: 1024
content_encoding: "application/zip"
artifact_path: "artifact-v4-download.zip"
artifact_name: "artifact-v4-download"
status: 2
created_unix: 1730330775
updated_unix: 1730330775
expired_unix: 1738106775

View file

@ -94,3 +94,22 @@
content: "test markup light/dark-mode-only ![GitHub-Mark-Light](https://user-images.githubusercontent.com/3369400/139447912-e0f43f33-6d9f-45f8-be46-2df5bbc91289.png#gh-dark-mode-only)![GitHub-Mark-Dark](https://user-images.githubusercontent.com/3369400/139448065-39a229ba-4b06-434b-bc67-616e2ed80c8f.png#gh-light-mode-only)"
created_unix: 946684813
updated_unix: 946684813
-
id: 11
type: 22 # review
poster_id: 5
issue_id: 3 # in repo_id 1
content: "reviewed by user5"
review_id: 21
created_unix: 946684816
-
id: 12
type: 27 # review request
poster_id: 2
issue_id: 3 # in repo_id 1
content: "review request for user5"
review_id: 22
assignee_id: 5
created_unix: 946684817

View file

@ -7,6 +7,7 @@
target_url: https://example.com/builds/
description: My awesome CI-service
context: ci/awesomeness
context_hash: c65f4d64a3b14a3eced0c9b36799e66e1bd5ced7
creator_id: 2
-
@ -18,6 +19,7 @@
target_url: https://example.com/coverage/
description: My awesome Coverage service
context: cov/awesomeness
context_hash: 3929ac7bccd3fa1bf9b38ddedb77973b1b9a8cfe
creator_id: 2
-
@ -29,6 +31,7 @@
target_url: https://example.com/coverage/
description: My awesome Coverage service
context: cov/awesomeness
context_hash: 3929ac7bccd3fa1bf9b38ddedb77973b1b9a8cfe
creator_id: 2
-
@ -40,6 +43,7 @@
target_url: https://example.com/builds/
description: My awesome CI-service
context: ci/awesomeness
context_hash: c65f4d64a3b14a3eced0c9b36799e66e1bd5ced7
creator_id: 2
-
@ -51,15 +55,41 @@
target_url: https://example.com/builds/
description: My awesome deploy service
context: deploy/awesomeness
context_hash: ae9547713a6665fc4261d0756904932085a41cf2
creator_id: 2
-
id: 6
index: 6
index: 1
repo_id: 62
state: "failure"
sha: "774f93df12d14931ea93259ae93418da4482fcc1"
target_url: "/user2/test_workflows/actions"
description: My awesome deploy service
context: deploy/awesomeness
context_hash: ae9547713a6665fc4261d0756904932085a41cf2
creator_id: 2
-
id: 7
index: 6
repo_id: 1
state: "pending"
sha: "1234123412341234123412341234123412341234"
target_url: https://example.com/builds/
description: My awesome deploy service
context: deploy/awesomeness
context_hash: ae9547713a6665fc4261d0756904932085a41cf2
creator_id: 2
-
id: 8
index: 2
repo_id: 62
state: "error"
sha: "774f93df12d14931ea93259ae93418da4482fcc1"
target_url: "/user2/test_workflows/actions"
description: "My awesome deploy service - v2"
context: deploy/awesomeness
context_hash: ae9547713a6665fc4261d0756904932085a41cf2
creator_id: 2

View file

@ -0,0 +1 @@
[] # empty

View file

@ -0,0 +1 @@
[] # empty

View file

@ -29,7 +29,8 @@
size: 7597
is_fsck_enabled: true
close_issues_via_commit_in_any_branch: false
created_unix: 1731254961
updated_unix: 1731254961
-
id: 2
owner_id: 2
@ -91,6 +92,8 @@
size: 0
is_fsck_enabled: true
close_issues_via_commit_in_any_branch: false
created_unix: 1700000001
updated_unix: 1700000001
-
id: 4
@ -152,6 +155,8 @@
size: 0
is_fsck_enabled: true
close_issues_via_commit_in_any_branch: false
created_unix: 1700000002
updated_unix: 1700000002
-
id: 6
@ -182,6 +187,8 @@
size: 0
is_fsck_enabled: true
close_issues_via_commit_in_any_branch: false
created_unix: 1710000001
updated_unix: 1710000001
-
id: 7
@ -212,6 +219,8 @@
size: 0
is_fsck_enabled: true
close_issues_via_commit_in_any_branch: false
created_unix: 1710000003
updated_unix: 1710000003
-
id: 8
@ -242,6 +251,8 @@
size: 0
is_fsck_enabled: true
close_issues_via_commit_in_any_branch: false
created_unix: 1710000002
updated_unix: 1710000002
-
id: 9
@ -968,6 +979,8 @@
size: 0
is_fsck_enabled: true
close_issues_via_commit_in_any_branch: false
created_unix: 1700000003
updated_unix: 1700000003
-
id: 33

View file

@ -179,3 +179,22 @@
content: "Review Comment"
updated_unix: 946684810
created_unix: 946684810
-
id: 21
type: 2
reviewer_id: 5
issue_id: 3
content: "reviewed by user5"
commit_id: 4a357436d925b5c974181ff12a994538ddc5a269
updated_unix: 946684816
created_unix: 946684816
-
id: 22
type: 4
reviewer_id: 5
issue_id: 3
content: "review request for user5"
updated_unix: 946684817
created_unix: 946684817

View file

@ -10,6 +10,7 @@ import (
_ "code.gitea.io/gitea/models"
_ "code.gitea.io/gitea/models/actions"
_ "code.gitea.io/gitea/models/activities"
_ "code.gitea.io/gitea/models/forgefed"
)
func TestMain(m *testing.M) {

View file

@ -82,6 +82,10 @@ var migrations = []*Migration{
NewMigration("Add SSH keypair to `pull_mirror` table", AddSSHKeypairToPushMirror),
// v22 -> v23
NewMigration("Add `legacy` to `web_authn_credential` table", AddLegacyToWebAuthnCredential),
// v23 -> v24
NewMigration("Add `delete_branch_after_merge` to `auto_merge` table", AddDeleteBranchAfterMergeToAutoMerge),
// v24 -> v25
NewMigration("Add `purpose` column to `forgejo_auth_token` table", AddPurposeToForgejoAuthToken),
}
// GetCurrentDBVersion returns the current Forgejo database version.

View file

@ -0,0 +1,16 @@
// Copyright 2024 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package forgejo_migrations //nolint:revive
import "xorm.io/xorm"
// AddDeleteBranchAfterMergeToAutoMerge: add DeleteBranchAfterMerge column, setting existing rows to false
func AddDeleteBranchAfterMergeToAutoMerge(x *xorm.Engine) error {
type AutoMerge struct {
ID int64 `xorm:"pk autoincr"`
DeleteBranchAfterMerge bool `xorm:"NOT NULL DEFAULT false"`
}
return x.Sync(&AutoMerge{})
}

View file

@ -0,0 +1,19 @@
// Copyright 2024 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package forgejo_migrations //nolint:revive
import "xorm.io/xorm"
func AddPurposeToForgejoAuthToken(x *xorm.Engine) error {
type ForgejoAuthToken struct {
ID int64 `xorm:"pk autoincr"`
Purpose string `xorm:"NOT NULL DEFAULT 'long_term_authorization'"`
}
if err := x.Sync(new(ForgejoAuthToken)); err != nil {
return err
}
_, err := x.Exec("UPDATE `forgejo_auth_token` SET purpose = 'long_term_authorization' WHERE purpose = ''")
return err
}

View file

@ -288,27 +288,18 @@ func GetLatestCommitStatus(ctx context.Context, repoID int64, sha string, listOp
// GetLatestCommitStatusForPairs returns all statuses with a unique context for a given list of repo-sha pairs
func GetLatestCommitStatusForPairs(ctx context.Context, repoSHAs []RepoSHA) (map[int64][]*CommitStatus, error) {
type result struct {
Index int64
RepoID int64
SHA string
}
results := make([]result, 0, len(repoSHAs))
getBase := func() *xorm.Session {
return db.GetEngine(ctx).Table(&CommitStatus{})
}
results := []*CommitStatus{}
// Create a disjunction of conditions for each repoID and SHA pair
conds := make([]builder.Cond, 0, len(repoSHAs))
for _, repoSHA := range repoSHAs {
conds = append(conds, builder.Eq{"repo_id": repoSHA.RepoID, "sha": repoSHA.SHA})
}
sess := getBase().Where(builder.Or(conds...)).
Select("max( `index` ) as `index`, repo_id, sha").
GroupBy("context_hash, repo_id, sha").OrderBy("max( `index` ) desc")
sess := db.GetEngine(ctx).Table(&CommitStatus{}).
Select("MAX(`index`) AS `index`, *").
Where(builder.Or(conds...)).
GroupBy("context_hash, repo_id, sha").OrderBy("MAX(`index`) DESC")
err := sess.Find(&results)
if err != nil {
return nil, err
@ -316,28 +307,10 @@ func GetLatestCommitStatusForPairs(ctx context.Context, repoSHAs []RepoSHA) (map
repoStatuses := make(map[int64][]*CommitStatus)
if len(results) > 0 {
statuses := make([]*CommitStatus, 0, len(results))
conds = make([]builder.Cond, 0, len(results))
for _, result := range results {
cond := builder.Eq{
"`index`": result.Index,
"repo_id": result.RepoID,
"sha": result.SHA,
}
conds = append(conds, cond)
}
err = getBase().Where(builder.Or(conds...)).Find(&statuses)
if err != nil {
return nil, err
}
// Group the statuses by repo ID
for _, status := range statuses {
for _, status := range results {
repoStatuses[status.RepoID] = append(repoStatuses[status.RepoID], status)
}
}
return repoStatuses, nil
}

View file

@ -35,8 +35,8 @@ func TestGetCommitStatuses(t *testing.T) {
SHA: sha1,
})
require.NoError(t, err)
assert.Equal(t, 5, int(maxResults))
assert.Len(t, statuses, 5)
assert.EqualValues(t, 6, maxResults)
assert.Len(t, statuses, 6)
assert.Equal(t, "ci/awesomeness", statuses[0].Context)
assert.Equal(t, structs.CommitStatusPending, statuses[0].State)
@ -58,13 +58,17 @@ func TestGetCommitStatuses(t *testing.T) {
assert.Equal(t, structs.CommitStatusError, statuses[4].State)
assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[4].APIURL(db.DefaultContext))
assert.Equal(t, "deploy/awesomeness", statuses[5].Context)
assert.Equal(t, structs.CommitStatusPending, statuses[5].State)
assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[5].APIURL(db.DefaultContext))
statuses, maxResults, err = db.FindAndCount[git_model.CommitStatus](db.DefaultContext, &git_model.CommitStatusOptions{
ListOptions: db.ListOptions{Page: 2, PageSize: 50},
RepoID: repo1.ID,
SHA: sha1,
})
require.NoError(t, err)
assert.Equal(t, 5, int(maxResults))
assert.EqualValues(t, 6, maxResults)
assert.Empty(t, statuses)
}
@ -265,3 +269,148 @@ func TestCommitStatusesHideActionsURL(t *testing.T) {
assert.Empty(t, statuses[0].TargetURL)
assert.Equal(t, "https://mycicd.org/1", statuses[1].TargetURL)
}
func TestGetLatestCommitStatusForPairs(t *testing.T) {
require.NoError(t, unittest.PrepareTestDatabase())
t.Run("All", func(t *testing.T) {
pairs, err := git_model.GetLatestCommitStatusForPairs(db.DefaultContext, nil)
require.NoError(t, err)
assert.EqualValues(t, map[int64][]*git_model.CommitStatus{
1: {
{
ID: 7,
Index: 6,
RepoID: 1,
State: structs.CommitStatusPending,
SHA: "1234123412341234123412341234123412341234",
TargetURL: "https://example.com/builds/",
Description: "My awesome deploy service",
ContextHash: "ae9547713a6665fc4261d0756904932085a41cf2",
Context: "deploy/awesomeness",
CreatorID: 2,
},
{
ID: 4,
Index: 4,
State: structs.CommitStatusFailure,
TargetURL: "https://example.com/builds/",
Description: "My awesome CI-service",
Context: "ci/awesomeness",
CreatorID: 2,
RepoID: 1,
SHA: "1234123412341234123412341234123412341234",
ContextHash: "c65f4d64a3b14a3eced0c9b36799e66e1bd5ced7",
},
{
ID: 3,
Index: 3,
State: structs.CommitStatusSuccess,
TargetURL: "https://example.com/coverage/",
Description: "My awesome Coverage service",
Context: "cov/awesomeness",
CreatorID: 2,
RepoID: 1,
SHA: "1234123412341234123412341234123412341234",
ContextHash: "3929ac7bccd3fa1bf9b38ddedb77973b1b9a8cfe",
},
},
62: {
{
ID: 8,
Index: 2,
RepoID: 62,
State: structs.CommitStatusError,
TargetURL: "/user2/test_workflows/actions",
Description: "My awesome deploy service - v2",
Context: "deploy/awesomeness",
SHA: "774f93df12d14931ea93259ae93418da4482fcc1",
ContextHash: "ae9547713a6665fc4261d0756904932085a41cf2",
CreatorID: 2,
},
},
}, pairs)
})
t.Run("Repo 1", func(t *testing.T) {
pairs, err := git_model.GetLatestCommitStatusForPairs(db.DefaultContext, []git_model.RepoSHA{{1, "1234123412341234123412341234123412341234"}})
require.NoError(t, err)
assert.EqualValues(t, map[int64][]*git_model.CommitStatus{
1: {
{
ID: 7,
Index: 6,
RepoID: 1,
State: structs.CommitStatusPending,
SHA: "1234123412341234123412341234123412341234",
TargetURL: "https://example.com/builds/",
Description: "My awesome deploy service",
ContextHash: "ae9547713a6665fc4261d0756904932085a41cf2",
Context: "deploy/awesomeness",
CreatorID: 2,
},
{
ID: 4,
Index: 4,
State: structs.CommitStatusFailure,
TargetURL: "https://example.com/builds/",
Description: "My awesome CI-service",
Context: "ci/awesomeness",
CreatorID: 2,
RepoID: 1,
SHA: "1234123412341234123412341234123412341234",
ContextHash: "c65f4d64a3b14a3eced0c9b36799e66e1bd5ced7",
},
{
ID: 3,
Index: 3,
State: structs.CommitStatusSuccess,
TargetURL: "https://example.com/coverage/",
Description: "My awesome Coverage service",
Context: "cov/awesomeness",
CreatorID: 2,
RepoID: 1,
SHA: "1234123412341234123412341234123412341234",
ContextHash: "3929ac7bccd3fa1bf9b38ddedb77973b1b9a8cfe",
},
},
}, pairs)
})
t.Run("Repo 62", func(t *testing.T) {
pairs, err := git_model.GetLatestCommitStatusForPairs(db.DefaultContext, []git_model.RepoSHA{{62, "774f93df12d14931ea93259ae93418da4482fcc1"}})
require.NoError(t, err)
assert.EqualValues(t, map[int64][]*git_model.CommitStatus{
62: {
{
ID: 8,
Index: 2,
RepoID: 62,
State: structs.CommitStatusError,
TargetURL: "/user2/test_workflows/actions",
Description: "My awesome deploy service - v2",
Context: "deploy/awesomeness",
SHA: "774f93df12d14931ea93259ae93418da4482fcc1",
ContextHash: "ae9547713a6665fc4261d0756904932085a41cf2",
CreatorID: 2,
},
},
}, pairs)
})
t.Run("Repo 62 nonexistant sha", func(t *testing.T) {
pairs, err := git_model.GetLatestCommitStatusForPairs(db.DefaultContext, []git_model.RepoSHA{{62, "774f93df12d14931ea93259ae93418da4482fcc"}})
require.NoError(t, err)
assert.EqualValues(t, map[int64][]*git_model.CommitStatus{}, pairs)
})
t.Run("SHA with non existant repo id", func(t *testing.T) {
pairs, err := git_model.GetLatestCommitStatusForPairs(db.DefaultContext, []git_model.RepoSHA{{1, "774f93df12d14931ea93259ae93418da4482fcc1"}})
require.NoError(t, err)
assert.EqualValues(t, map[int64][]*git_model.CommitStatus{}, pairs)
})
}

View file

@ -136,8 +136,6 @@ var ErrLFSObjectNotExist = db.ErrNotExist{Resource: "LFS Meta object"}
// NewLFSMetaObject stores a given populated LFSMetaObject structure in the database
// if it is not already present.
func NewLFSMetaObject(ctx context.Context, repoID int64, p lfs.Pointer) (*LFSMetaObject, error) {
var err error
ctx, committer, err := db.TxContext(ctx)
if err != nil {
return nil, err

View file

@ -11,6 +11,7 @@ import (
_ "code.gitea.io/gitea/models"
_ "code.gitea.io/gitea/models/actions"
_ "code.gitea.io/gitea/models/activities"
_ "code.gitea.io/gitea/models/forgefed"
)
func TestMain(m *testing.M) {

View file

@ -79,15 +79,21 @@ func IsRuleNameSpecial(ruleName string) bool {
}
func (protectBranch *ProtectedBranch) loadGlob() {
if protectBranch.globRule == nil {
if protectBranch.isPlainName || protectBranch.globRule != nil {
return
}
// detect if it is not glob
if !IsRuleNameSpecial(protectBranch.RuleName) {
protectBranch.isPlainName = true
return
}
// now we load the glob
var err error
protectBranch.globRule, err = glob.Compile(protectBranch.RuleName, '/')
if err != nil {
log.Warn("Invalid glob rule for ProtectedBranch[%d]: %s %v", protectBranch.ID, protectBranch.RuleName, err)
protectBranch.globRule = glob.MustCompile(glob.QuoteMeta(protectBranch.RuleName), '/')
}
protectBranch.isPlainName = !IsRuleNameSpecial(protectBranch.RuleName)
}
}
// Match tests if branchName matches the rule

View file

@ -75,3 +75,32 @@ func TestBranchRuleMatchPriority(t *testing.T) {
}
}
}
func TestBranchRuleSort(t *testing.T) {
in := []*ProtectedBranch{{
RuleName: "b",
CreatedUnix: 1,
}, {
RuleName: "b/*",
CreatedUnix: 3,
}, {
RuleName: "a/*",
CreatedUnix: 2,
}, {
RuleName: "c",
CreatedUnix: 0,
}, {
RuleName: "a",
CreatedUnix: 4,
}}
expect := []string{"c", "b", "a", "a/*", "b/*"}
pbr := ProtectedBranchRules(in)
pbr.sort()
var got []string
for i := range pbr {
got = append(got, pbr[i].RuleName)
}
assert.Equal(t, expect, got)
}

View file

@ -0,0 +1,11 @@
-
id: 3
user_id: 1
issue_id: 2
created_unix: 1500988004
-
id: 4
user_id: 3
issue_id: 0
created_unix: 1500988003

View file

@ -222,6 +222,12 @@ func (r RoleInRepo) LocaleHelper(lang translation.Locale) string {
return lang.TrString("repo.issues.role." + string(r) + "_helper")
}
type RequestReviewTarget interface {
ID() int64
Name() string
Type() string
}
// Comment represents a comment in commit and issue page.
type Comment struct {
ID int64 `xorm:"pk autoincr"`
@ -236,6 +242,8 @@ type Comment struct {
Label *Label `xorm:"-"`
AddedLabels []*Label `xorm:"-"`
RemovedLabels []*Label `xorm:"-"`
AddedRequestReview []RequestReviewTarget `xorm:"-"`
RemovedRequestReview []RequestReviewTarget `xorm:"-"`
OldProjectID int64
ProjectID int64
OldProject *project_model.Project `xorm:"-"`

View file

@ -875,7 +875,7 @@ func GetPinnedIssues(ctx context.Context, repoID int64, isPull bool) (IssueList,
return issues, nil
}
// IsNewPinnedAllowed returns if a new Issue or Pull request can be pinned
// IsNewPinAllowed returns if a new Issue or Pull request can be pinned
func IsNewPinAllowed(ctx context.Context, repoID int64, isPull bool) (bool, error) {
var maxPin int
_, err := db.GetEngine(ctx).SQL("SELECT COUNT(pin_order) FROM issue WHERE repo_id = ? AND is_pull = ? AND pin_order > 0", repoID, isPull).Get(&maxPin)

View file

@ -111,9 +111,7 @@ func NewIssueLabel(ctx context.Context, issue *Issue, label *Label, doer *user_m
return err
}
issue.isLabelsLoaded = false
issue.Labels = nil
if err = issue.LoadLabels(ctx); err != nil {
if err = issue.ReloadLabels(ctx); err != nil {
return err
}
@ -161,10 +159,7 @@ func NewIssueLabels(ctx context.Context, issue *Issue, labels []*Label, doer *us
return err
}
// reload all labels
issue.isLabelsLoaded = false
issue.Labels = nil
if err = issue.LoadLabels(ctx); err != nil {
if err = issue.ReloadLabels(ctx); err != nil {
return err
}
@ -205,8 +200,7 @@ func DeleteIssueLabel(ctx context.Context, issue *Issue, label *Label, doer *use
return err
}
issue.Labels = nil
return issue.LoadLabels(ctx)
return issue.ReloadLabels(ctx)
}
// DeleteLabelsByRepoID deletes labels of some repository
@ -326,14 +320,23 @@ func FixIssueLabelWithOutsideLabels(ctx context.Context) (int64, error) {
return res.RowsAffected()
}
// LoadLabels loads labels
// LoadLabels only if they are not already set
func (issue *Issue) LoadLabels(ctx context.Context) (err error) {
if !issue.isLabelsLoaded && issue.Labels == nil && issue.ID != 0 {
if !issue.isLabelsLoaded && issue.Labels == nil {
if err := issue.ReloadLabels(ctx); err != nil {
return err
}
issue.isLabelsLoaded = true
}
return nil
}
func (issue *Issue) ReloadLabels(ctx context.Context) (err error) {
if issue.ID != 0 {
issue.Labels, err = GetLabelsByIssueID(ctx, issue.ID)
if err != nil {
return fmt.Errorf("getLabelsByIssueID [%d]: %w", issue.ID, err)
}
issue.isLabelsLoaded = true
}
return nil
}
@ -496,8 +499,7 @@ func ReplaceIssueLabels(ctx context.Context, issue *Issue, labels []*Label, doer
}
}
issue.Labels = nil
if err = issue.LoadLabels(ctx); err != nil {
if err = issue.ReloadLabels(ctx); err != nil {
return err
}

View file

@ -15,6 +15,114 @@ import (
"github.com/stretchr/testify/require"
)
func TestIssueNewIssueLabels(t *testing.T) {
require.NoError(t, unittest.PrepareTestDatabase())
issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2})
label1 := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 1})
label2 := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 4})
doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
label3 := &issues_model.Label{RepoID: 1, Name: "label3", Color: "#123"}
require.NoError(t, issues_model.NewLabel(db.DefaultContext, label3))
// label1 is already set, do nothing
// label3 is new, add it
require.NoError(t, issues_model.NewIssueLabels(db.DefaultContext, issue, []*issues_model.Label{label1, label3}, doer))
assert.Len(t, issue.Labels, 3)
// check that the pre-existing label1 is still present
assert.Equal(t, label1.ID, issue.Labels[0].ID)
// check that new label3 was added
assert.Equal(t, label3.ID, issue.Labels[1].ID)
// check that pre-existing label2 was not removed
assert.Equal(t, label2.ID, issue.Labels[2].ID)
}
func TestIssueNewIssueLabel(t *testing.T) {
require.NoError(t, unittest.PrepareTestDatabase())
issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 3})
doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
label := &issues_model.Label{RepoID: 1, Name: "label3", Color: "#123"}
require.NoError(t, issues_model.NewLabel(db.DefaultContext, label))
require.NoError(t, issues_model.NewIssueLabel(db.DefaultContext, issue, label, doer))
assert.Len(t, issue.Labels, 1)
assert.Equal(t, label.ID, issue.Labels[0].ID)
}
func TestIssueReplaceIssueLabels(t *testing.T) {
require.NoError(t, unittest.PrepareTestDatabase())
issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2})
label1 := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 1})
label2 := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 4})
doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
label3 := &issues_model.Label{RepoID: 1, Name: "label3", Color: "#123"}
require.NoError(t, issues_model.NewLabel(db.DefaultContext, label3))
issue.LoadLabels(db.DefaultContext)
assert.Len(t, issue.Labels, 2)
assert.Equal(t, label1.ID, issue.Labels[0].ID)
assert.Equal(t, label2.ID, issue.Labels[1].ID)
// label1 is already set, do nothing
// label3 is new, add it
// label2 is not in the list but already set, remove it
require.NoError(t, issues_model.ReplaceIssueLabels(db.DefaultContext, issue, []*issues_model.Label{label1, label3}, doer))
assert.Len(t, issue.Labels, 2)
assert.Equal(t, label1.ID, issue.Labels[0].ID)
assert.Equal(t, label3.ID, issue.Labels[1].ID)
}
func TestIssueDeleteIssueLabel(t *testing.T) {
require.NoError(t, unittest.PrepareTestDatabase())
issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2})
label1 := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 1})
label2 := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 4})
doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
issue.LoadLabels(db.DefaultContext)
assert.Len(t, issue.Labels, 2)
assert.Equal(t, label1.ID, issue.Labels[0].ID)
assert.Equal(t, label2.ID, issue.Labels[1].ID)
require.NoError(t, issues_model.DeleteIssueLabel(db.DefaultContext, issue, label2, doer))
assert.Len(t, issue.Labels, 1)
assert.Equal(t, label1.ID, issue.Labels[0].ID)
}
func TestIssueLoadLabels(t *testing.T) {
require.NoError(t, unittest.PrepareTestDatabase())
issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2})
label1 := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 1})
label2 := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 4})
assert.Empty(t, issue.Labels)
issue.LoadLabels(db.DefaultContext)
assert.Len(t, issue.Labels, 2)
assert.Equal(t, label1.ID, issue.Labels[0].ID)
assert.Equal(t, label2.ID, issue.Labels[1].ID)
unittest.AssertSuccessfulDelete(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: label2.ID})
// the database change is not noticed because the labels are cached
issue.LoadLabels(db.DefaultContext)
assert.Len(t, issue.Labels, 2)
issue.ReloadLabels(db.DefaultContext)
assert.Len(t, issue.Labels, 1)
assert.Equal(t, label1.ID, issue.Labels[0].ID)
}
func TestNewIssueLabelsScope(t *testing.T) {
require.NoError(t, unittest.PrepareTestDatabase())

View file

@ -15,7 +15,7 @@ import (
// IssueStats represents issue statistic information.
type IssueStats struct {
OpenCount, ClosedCount int64
OpenCount, ClosedCount, AllCount int64
YourRepositoriesCount int64
AssignCount int64
CreateCount int64
@ -104,6 +104,7 @@ func GetIssueStats(ctx context.Context, opts *IssuesOptions) (*IssueStats, error
}
accum.OpenCount += stats.OpenCount
accum.ClosedCount += stats.ClosedCount
accum.AllCount += stats.AllCount
accum.YourRepositoriesCount += stats.YourRepositoriesCount
accum.AssignCount += stats.AssignCount
accum.CreateCount += stats.CreateCount
@ -131,7 +132,13 @@ func getIssueStatsChunk(ctx context.Context, opts *IssuesOptions, issueIDs []int
stats.ClosedCount, err = applyIssuesOptions(sess, opts, issueIDs).
And("issue.is_closed = ?", true).
Count(new(Issue))
if err != nil {
return stats, err
}
stats.AllCount = stats.OpenCount + stats.ClosedCount
return stats, nil
}
func applyIssuesOptions(sess *xorm.Session, opts *IssuesOptions, issueIDs []int64) *xorm.Session {

View file

@ -25,6 +25,7 @@ func TestGetIssueStats(t *testing.T) {
assert.Equal(t, int64(4), stats.OpenCount)
assert.Equal(t, int64(1), stats.ClosedCount)
assert.Equal(t, int64(5), stats.AllCount)
assert.Equal(t, int64(0), stats.YourRepositoriesCount)
assert.Equal(t, int64(0), stats.AssignCount)
assert.Equal(t, int64(0), stats.CreateCount)

View file

@ -231,8 +231,7 @@ func TestGetLabelsByOrgID(t *testing.T) {
testSuccess(3, "reversealphabetically", []int64{4, 3})
testSuccess(3, "default", []int64{3, 4})
var err error
_, err = issues_model.GetLabelsByOrgID(db.DefaultContext, 0, "leastissues", db.ListOptions{})
_, err := issues_model.GetLabelsByOrgID(db.DefaultContext, 0, "leastissues", db.ListOptions{})
assert.True(t, issues_model.IsErrOrgLabelNotExist(err))
_, err = issues_model.GetLabelsByOrgID(db.DefaultContext, -1, "leastissues", db.ListOptions{})

View file

@ -408,7 +408,7 @@ func (pr *PullRequest) getReviewedByLines(ctx context.Context, writer io.Writer)
// Note: This doesn't page as we only expect a very limited number of reviews
reviews, err := FindLatestReviews(ctx, FindReviewOptions{
Type: ReviewTypeApprove,
Types: []ReviewType{ReviewTypeApprove},
IssueID: pr.IssueID,
OfficialOnly: setting.Repository.PullRequest.DefaultMergeMessageOfficialApproversOnly,
})
@ -689,7 +689,7 @@ func GetPullRequestByIssueID(ctx context.Context, issueID int64) (*PullRequest,
return pr, pr.LoadAttributes(ctx)
}
// GetPullRequestsByBaseHeadInfo returns the pull request by given base and head
// GetPullRequestByBaseHeadInfo returns the pull request by given base and head
func GetPullRequestByBaseHeadInfo(ctx context.Context, baseID, headID int64, base, head string) (*PullRequest, error) {
pr := &PullRequest{}
sess := db.GetEngine(ctx).

View file

@ -26,6 +26,7 @@ type PullRequestsOptions struct {
SortType string
Labels []int64
MilestoneID int64
PosterID int64
}
func listPullRequestStatement(ctx context.Context, baseRepoID int64, opts *PullRequestsOptions) *xorm.Session {
@ -46,6 +47,10 @@ func listPullRequestStatement(ctx context.Context, baseRepoID int64, opts *PullR
sess.And("issue.milestone_id=?", opts.MilestoneID)
}
if opts.PosterID > 0 {
sess.And("issue.poster_id=?", opts.PosterID)
}
return sess
}

View file

@ -364,7 +364,7 @@ func GetCurrentReview(ctx context.Context, reviewer *user_model.User, issue *Iss
return nil, nil
}
reviews, err := FindReviews(ctx, FindReviewOptions{
Type: ReviewTypePending,
Types: []ReviewType{ReviewTypePending},
IssueID: issue.ID,
ReviewerID: reviewer.ID,
})

View file

@ -92,7 +92,7 @@ func (reviews ReviewList) LoadIssues(ctx context.Context) error {
// FindReviewOptions represent possible filters to find reviews
type FindReviewOptions struct {
db.ListOptions
Type ReviewType
Types []ReviewType
IssueID int64
ReviewerID int64
OfficialOnly bool
@ -107,8 +107,8 @@ func (opts *FindReviewOptions) toCond() builder.Cond {
if opts.ReviewerID > 0 {
cond = cond.And(builder.Eq{"reviewer_id": opts.ReviewerID})
}
if opts.Type != ReviewTypeUnknown {
cond = cond.And(builder.Eq{"type": opts.Type})
if len(opts.Types) > 0 {
cond = cond.And(builder.In("type", opts.Types))
}
if opts.OfficialOnly {
cond = cond.And(builder.Eq{"official": true})

View file

@ -64,7 +64,7 @@ func TestReviewType_Icon(t *testing.T) {
func TestFindReviews(t *testing.T) {
require.NoError(t, unittest.PrepareTestDatabase())
reviews, err := issues_model.FindReviews(db.DefaultContext, issues_model.FindReviewOptions{
Type: issues_model.ReviewTypeApprove,
Types: []issues_model.ReviewType{issues_model.ReviewTypeApprove},
IssueID: 2,
ReviewerID: 1,
})
@ -76,7 +76,7 @@ func TestFindReviews(t *testing.T) {
func TestFindLatestReviews(t *testing.T) {
require.NoError(t, unittest.PrepareTestDatabase())
reviews, err := issues_model.FindLatestReviews(db.DefaultContext, issues_model.FindReviewOptions{
Type: issues_model.ReviewTypeApprove,
Types: []issues_model.ReviewType{issues_model.ReviewTypeApprove},
IssueID: 11,
})
require.NoError(t, err)

View file

@ -60,34 +60,19 @@ func getStopwatch(ctx context.Context, userID, issueID int64) (sw *Stopwatch, ex
return sw, exists, err
}
// UserIDCount is a simple coalition of UserID and Count
type UserStopwatch struct {
UserID int64
StopWatches []*Stopwatch
}
// GetUIDsAndNotificationCounts between the two provided times
func GetUIDsAndStopwatch(ctx context.Context) ([]*UserStopwatch, error) {
func GetUIDsAndStopwatch(ctx context.Context) (map[int64][]*Stopwatch, error) {
sws := []*Stopwatch{}
if err := db.GetEngine(ctx).Where("issue_id != 0").Find(&sws); err != nil {
return nil, err
}
res := map[int64][]*Stopwatch{}
if len(sws) == 0 {
return []*UserStopwatch{}, nil
return res, nil
}
lastUserID := int64(-1)
res := []*UserStopwatch{}
for _, sw := range sws {
if lastUserID == sw.UserID {
lastUserStopwatch := res[len(res)-1]
lastUserStopwatch.StopWatches = append(lastUserStopwatch.StopWatches, sw)
} else {
res = append(res, &UserStopwatch{
UserID: sw.UserID,
StopWatches: []*Stopwatch{sw},
})
}
res[sw.UserID] = append(res[sw.UserID], sw)
}
return res, nil
}

View file

@ -4,12 +4,14 @@
package issues_test
import (
"path/filepath"
"testing"
"code.gitea.io/gitea/models/db"
issues_model "code.gitea.io/gitea/models/issues"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/timeutil"
"github.com/stretchr/testify/assert"
@ -77,3 +79,41 @@ func TestCreateOrStopIssueStopwatch(t *testing.T) {
unittest.AssertNotExistsBean(t, &issues_model.Stopwatch{UserID: 2, IssueID: 2})
unittest.AssertExistsAndLoadBean(t, &issues_model.TrackedTime{UserID: 2, IssueID: 2})
}
func TestGetUIDsAndStopwatch(t *testing.T) {
defer unittest.OverrideFixtures(
unittest.FixturesOptions{
Dir: filepath.Join(setting.AppWorkPath, "models/fixtures/"),
Base: setting.AppWorkPath,
Dirs: []string{"models/issues/TestGetUIDsAndStopwatch/"},
},
)()
require.NoError(t, unittest.PrepareTestDatabase())
uidStopwatches, err := issues_model.GetUIDsAndStopwatch(db.DefaultContext)
require.NoError(t, err)
assert.EqualValues(t, map[int64][]*issues_model.Stopwatch{
1: {
{
ID: 1,
UserID: 1,
IssueID: 1,
CreatedUnix: timeutil.TimeStamp(1500988001),
},
{
ID: 3,
UserID: 1,
IssueID: 2,
CreatedUnix: timeutil.TimeStamp(1500988004),
},
},
2: {
{
ID: 2,
UserID: 2,
IssueID: 2,
CreatedUnix: timeutil.TimeStamp(1500988002),
},
},
}, uidStopwatches)
}

View file

@ -13,6 +13,7 @@ import (
user_model "code.gitea.io/gitea/models/user"
_ "code.gitea.io/gitea/models/actions"
_ "code.gitea.io/gitea/models/forgefed"
_ "code.gitea.io/gitea/models/system"
"github.com/stretchr/testify/require"

View file

@ -38,25 +38,15 @@ import (
const minDBVersion = 70 // Gitea 1.5.3
// Migration describes on migration from lower version to high version
type Migration interface {
Description() string
Migrate(*xorm.Engine) error
}
type migration struct {
idNumber int64 // DB version is "the last migration's idNumber" + 1
description string
migrate func(*xorm.Engine) error
}
// NewMigration creates a new migration
func NewMigration(desc string, fn func(*xorm.Engine) error) Migration {
return &migration{desc, fn}
}
// Description returns the migration's description
func (m *migration) Description() string {
return m.description
// newMigration creates a new migration
func newMigration(idNumber int64, desc string, fn func(*xorm.Engine) error) *migration {
return &migration{idNumber, desc, fn}
}
// Migrate executes the migration
@ -67,538 +57,313 @@ func (m *migration) Migrate(x *xorm.Engine) error {
// Version describes the version table. Should have only one row with id==1
type Version struct {
ID int64 `xorm:"pk autoincr"`
Version int64
Version int64 // DB version is "the last migration's idNumber" + 1
}
// Use noopMigration when there is a migration that has been no-oped
var noopMigration = func(_ *xorm.Engine) error { return nil }
var preparedMigrations []*migration
// This is a sequence of migrations. Add new migrations to the bottom of the list.
// If you want to "retire" a migration, remove it from the top of the list and
// update minDBVersion accordingly
var migrations = []Migration{
// Gitea 1.5.0 ends at v69
func prepareMigrationTasks() []*migration {
if preparedMigrations != nil {
return preparedMigrations
}
preparedMigrations = []*migration{
// Gitea 1.5.0 ends at database version 69
// v70 -> v71
NewMigration("add issue_dependencies", v1_6.AddIssueDependencies),
// v71 -> v72
NewMigration("protect each scratch token", v1_6.AddScratchHash),
// v72 -> v73
NewMigration("add review", v1_6.AddReview),
newMigration(70, "add issue_dependencies", v1_6.AddIssueDependencies),
newMigration(71, "protect each scratch token", v1_6.AddScratchHash),
newMigration(72, "add review", v1_6.AddReview),
// Gitea 1.6.0 ends at v73
// Gitea 1.6.0 ends at database version 73
// v73 -> v74
NewMigration("add must_change_password column for users table", v1_7.AddMustChangePassword),
// v74 -> v75
NewMigration("add approval whitelists to protected branches", v1_7.AddApprovalWhitelistsToProtectedBranches),
// v75 -> v76
NewMigration("clear nonused data which not deleted when user was deleted", v1_7.ClearNonusedData),
newMigration(73, "add must_change_password column for users table", v1_7.AddMustChangePassword),
newMigration(74, "add approval whitelists to protected branches", v1_7.AddApprovalWhitelistsToProtectedBranches),
newMigration(75, "clear nonused data which not deleted when user was deleted", v1_7.ClearNonusedData),
// Gitea 1.7.0 ends at v76
// Gitea 1.7.0 ends at database version 76
// v76 -> v77
NewMigration("add pull request rebase with merge commit", v1_8.AddPullRequestRebaseWithMerge),
// v77 -> v78
NewMigration("add theme to users", v1_8.AddUserDefaultTheme),
// v78 -> v79
NewMigration("rename repo is_bare to repo is_empty", v1_8.RenameRepoIsBareToIsEmpty),
// v79 -> v80
NewMigration("add can close issues via commit in any branch", v1_8.AddCanCloseIssuesViaCommitInAnyBranch),
// v80 -> v81
NewMigration("add is locked to issues", v1_8.AddIsLockedToIssues),
// v81 -> v82
NewMigration("update U2F counter type", v1_8.ChangeU2FCounterType),
newMigration(76, "add pull request rebase with merge commit", v1_8.AddPullRequestRebaseWithMerge),
newMigration(77, "add theme to users", v1_8.AddUserDefaultTheme),
newMigration(78, "rename repo is_bare to repo is_empty", v1_8.RenameRepoIsBareToIsEmpty),
newMigration(79, "add can close issues via commit in any branch", v1_8.AddCanCloseIssuesViaCommitInAnyBranch),
newMigration(80, "add is locked to issues", v1_8.AddIsLockedToIssues),
newMigration(81, "update U2F counter type", v1_8.ChangeU2FCounterType),
// Gitea 1.8.0 ends at v82
// Gitea 1.8.0 ends at database version 82
// v82 -> v83
NewMigration("hot fix for wrong release sha1 on release table", v1_9.FixReleaseSha1OnReleaseTable),
// v83 -> v84
NewMigration("add uploader id for table attachment", v1_9.AddUploaderIDForAttachment),
// v84 -> v85
NewMigration("add table to store original imported gpg keys", v1_9.AddGPGKeyImport),
// v85 -> v86
NewMigration("hash application token", v1_9.HashAppToken),
// v86 -> v87
NewMigration("add http method to webhook", v1_9.AddHTTPMethodToWebhook),
// v87 -> v88
NewMigration("add avatar field to repository", v1_9.AddAvatarFieldToRepository),
newMigration(82, "hot fix for wrong release sha1 on release table", v1_9.FixReleaseSha1OnReleaseTable),
newMigration(83, "add uploader id for table attachment", v1_9.AddUploaderIDForAttachment),
newMigration(84, "add table to store original imported gpg keys", v1_9.AddGPGKeyImport),
newMigration(85, "hash application token", v1_9.HashAppToken),
newMigration(86, "add http method to webhook", v1_9.AddHTTPMethodToWebhook),
newMigration(87, "add avatar field to repository", v1_9.AddAvatarFieldToRepository),
// Gitea 1.9.0 ends at v88
// Gitea 1.9.0 ends at database version 88
// v88 -> v89
NewMigration("add commit status context field to commit_status", v1_10.AddCommitStatusContext),
// v89 -> v90
NewMigration("add original author/url migration info to issues, comments, and repo ", v1_10.AddOriginalMigrationInfo),
// v90 -> v91
NewMigration("change length of some repository columns", v1_10.ChangeSomeColumnsLengthOfRepo),
// v91 -> v92
NewMigration("add index on owner_id of repository and type, review_id of comment", v1_10.AddIndexOnRepositoryAndComment),
// v92 -> v93
NewMigration("remove orphaned repository index statuses", v1_10.RemoveLingeringIndexStatus),
// v93 -> v94
NewMigration("add email notification enabled preference to user", v1_10.AddEmailNotificationEnabledToUser),
// v94 -> v95
NewMigration("add enable_status_check, status_check_contexts to protected_branch", v1_10.AddStatusCheckColumnsForProtectedBranches),
// v95 -> v96
NewMigration("add table columns for cross referencing issues", v1_10.AddCrossReferenceColumns),
// v96 -> v97
NewMigration("delete orphaned attachments", v1_10.DeleteOrphanedAttachments),
// v97 -> v98
NewMigration("add repo_admin_change_team_access to user", v1_10.AddRepoAdminChangeTeamAccessColumnForUser),
// v98 -> v99
NewMigration("add original author name and id on migrated release", v1_10.AddOriginalAuthorOnMigratedReleases),
// v99 -> v100
NewMigration("add task table and status column for repository table", v1_10.AddTaskTable),
// v100 -> v101
NewMigration("update migration repositories' service type", v1_10.UpdateMigrationServiceTypes),
// v101 -> v102
NewMigration("change length of some external login users columns", v1_10.ChangeSomeColumnsLengthOfExternalLoginUser),
newMigration(88, "add commit status context field to commit_status", v1_10.AddCommitStatusContext),
newMigration(89, "add original author/url migration info to issues, comments, and repo ", v1_10.AddOriginalMigrationInfo),
newMigration(90, "change length of some repository columns", v1_10.ChangeSomeColumnsLengthOfRepo),
newMigration(91, "add index on owner_id of repository and type, review_id of comment", v1_10.AddIndexOnRepositoryAndComment),
newMigration(92, "remove orphaned repository index statuses", v1_10.RemoveLingeringIndexStatus),
newMigration(93, "add email notification enabled preference to user", v1_10.AddEmailNotificationEnabledToUser),
newMigration(94, "add enable_status_check, status_check_contexts to protected_branch", v1_10.AddStatusCheckColumnsForProtectedBranches),
newMigration(95, "add table columns for cross referencing issues", v1_10.AddCrossReferenceColumns),
newMigration(96, "delete orphaned attachments", v1_10.DeleteOrphanedAttachments),
newMigration(97, "add repo_admin_change_team_access to user", v1_10.AddRepoAdminChangeTeamAccessColumnForUser),
newMigration(98, "add original author name and id on migrated release", v1_10.AddOriginalAuthorOnMigratedReleases),
newMigration(99, "add task table and status column for repository table", v1_10.AddTaskTable),
newMigration(100, "update migration repositories' service type", v1_10.UpdateMigrationServiceTypes),
newMigration(101, "change length of some external login users columns", v1_10.ChangeSomeColumnsLengthOfExternalLoginUser),
// Gitea 1.10.0 ends at v102
// Gitea 1.10.0 ends at database version 102
// v102 -> v103
NewMigration("update migration repositories' service type", v1_11.DropColumnHeadUserNameOnPullRequest),
// v103 -> v104
NewMigration("Add WhitelistDeployKeys to protected branch", v1_11.AddWhitelistDeployKeysToBranches),
// v104 -> v105
NewMigration("remove unnecessary columns from label", v1_11.RemoveLabelUneededCols),
// v105 -> v106
NewMigration("add includes_all_repositories to teams", v1_11.AddTeamIncludesAllRepositories),
// v106 -> v107
NewMigration("add column `mode` to table watch", v1_11.AddModeColumnToWatch),
// v107 -> v108
NewMigration("Add template options to repository", v1_11.AddTemplateToRepo),
// v108 -> v109
NewMigration("Add comment_id on table notification", v1_11.AddCommentIDOnNotification),
// v109 -> v110
NewMigration("add can_create_org_repo to team", v1_11.AddCanCreateOrgRepoColumnForTeam),
// v110 -> v111
NewMigration("change review content type to text", v1_11.ChangeReviewContentToText),
// v111 -> v112
NewMigration("update branch protection for can push and whitelist enable", v1_11.AddBranchProtectionCanPushAndEnableWhitelist),
// v112 -> v113
NewMigration("remove release attachments which repository deleted", v1_11.RemoveAttachmentMissedRepo),
// v113 -> v114
NewMigration("new feature: change target branch of pull requests", v1_11.FeatureChangeTargetBranch),
// v114 -> v115
NewMigration("Remove authentication credentials from stored URL", v1_11.SanitizeOriginalURL),
// v115 -> v116
NewMigration("add user_id prefix to existing user avatar name", v1_11.RenameExistingUserAvatarName),
// v116 -> v117
NewMigration("Extend TrackedTimes", v1_11.ExtendTrackedTimes),
newMigration(102, "update migration repositories' service type", v1_11.DropColumnHeadUserNameOnPullRequest),
newMigration(103, "Add WhitelistDeployKeys to protected branch", v1_11.AddWhitelistDeployKeysToBranches),
newMigration(104, "remove unnecessary columns from label", v1_11.RemoveLabelUneededCols),
newMigration(105, "add includes_all_repositories to teams", v1_11.AddTeamIncludesAllRepositories),
newMigration(106, "add column `mode` to table watch", v1_11.AddModeColumnToWatch),
newMigration(107, "Add template options to repository", v1_11.AddTemplateToRepo),
newMigration(108, "Add comment_id on table notification", v1_11.AddCommentIDOnNotification),
newMigration(109, "add can_create_org_repo to team", v1_11.AddCanCreateOrgRepoColumnForTeam),
newMigration(110, "change review content type to text", v1_11.ChangeReviewContentToText),
newMigration(111, "update branch protection for can push and whitelist enable", v1_11.AddBranchProtectionCanPushAndEnableWhitelist),
newMigration(112, "remove release attachments which repository deleted", v1_11.RemoveAttachmentMissedRepo),
newMigration(113, "new feature: change target branch of pull requests", v1_11.FeatureChangeTargetBranch),
newMigration(114, "Remove authentication credentials from stored URL", v1_11.SanitizeOriginalURL),
newMigration(115, "add user_id prefix to existing user avatar name", v1_11.RenameExistingUserAvatarName),
newMigration(116, "Extend TrackedTimes", v1_11.ExtendTrackedTimes),
// Gitea 1.11.0 ends at v117
// Gitea 1.11.0 ends at database version 117
// v117 -> v118
NewMigration("Add block on rejected reviews branch protection", v1_12.AddBlockOnRejectedReviews),
// v118 -> v119
NewMigration("Add commit id and stale to reviews", v1_12.AddReviewCommitAndStale),
// v119 -> v120
NewMigration("Fix migrated repositories' git service type", v1_12.FixMigratedRepositoryServiceType),
// v120 -> v121
NewMigration("Add owner_name on table repository", v1_12.AddOwnerNameOnRepository),
// v121 -> v122
NewMigration("add is_restricted column for users table", v1_12.AddIsRestricted),
// v122 -> v123
NewMigration("Add Require Signed Commits to ProtectedBranch", v1_12.AddRequireSignedCommits),
// v123 -> v124
NewMigration("Add original information for reactions", v1_12.AddReactionOriginals),
// v124 -> v125
NewMigration("Add columns to user and repository", v1_12.AddUserRepoMissingColumns),
// v125 -> v126
NewMigration("Add some columns on review for migration", v1_12.AddReviewMigrateInfo),
// v126 -> v127
NewMigration("Fix topic repository count", v1_12.FixTopicRepositoryCount),
// v127 -> v128
NewMigration("add repository code language statistics", v1_12.AddLanguageStats),
// v128 -> v129
NewMigration("fix merge base for pull requests", v1_12.FixMergeBase),
// v129 -> v130
NewMigration("remove dependencies from deleted repositories", v1_12.PurgeUnusedDependencies),
// v130 -> v131
NewMigration("Expand webhooks for more granularity", v1_12.ExpandWebhooks),
// v131 -> v132
NewMigration("Add IsSystemWebhook column to webhooks table", v1_12.AddSystemWebhookColumn),
// v132 -> v133
NewMigration("Add Branch Protection Protected Files Column", v1_12.AddBranchProtectionProtectedFilesColumn),
// v133 -> v134
NewMigration("Add EmailHash Table", v1_12.AddEmailHashTable),
// v134 -> v135
NewMigration("Refix merge base for merged pull requests", v1_12.RefixMergeBase),
// v135 -> v136
NewMigration("Add OrgID column to Labels table", v1_12.AddOrgIDLabelColumn),
// v136 -> v137
NewMigration("Add CommitsAhead and CommitsBehind Column to PullRequest Table", v1_12.AddCommitDivergenceToPulls),
// v137 -> v138
NewMigration("Add Branch Protection Block Outdated Branch", v1_12.AddBlockOnOutdatedBranch),
// v138 -> v139
NewMigration("Add ResolveDoerID to Comment table", v1_12.AddResolveDoerIDCommentColumn),
// v139 -> v140
NewMigration("prepend refs/heads/ to issue refs", v1_12.PrependRefsHeadsToIssueRefs),
newMigration(117, "Add block on rejected reviews branch protection", v1_12.AddBlockOnRejectedReviews),
newMigration(118, "Add commit id and stale to reviews", v1_12.AddReviewCommitAndStale),
newMigration(119, "Fix migrated repositories' git service type", v1_12.FixMigratedRepositoryServiceType),
newMigration(120, "Add owner_name on table repository", v1_12.AddOwnerNameOnRepository),
newMigration(121, "add is_restricted column for users table", v1_12.AddIsRestricted),
newMigration(122, "Add Require Signed Commits to ProtectedBranch", v1_12.AddRequireSignedCommits),
newMigration(123, "Add original information for reactions", v1_12.AddReactionOriginals),
newMigration(124, "Add columns to user and repository", v1_12.AddUserRepoMissingColumns),
newMigration(125, "Add some columns on review for migration", v1_12.AddReviewMigrateInfo),
newMigration(126, "Fix topic repository count", v1_12.FixTopicRepositoryCount),
newMigration(127, "add repository code language statistics", v1_12.AddLanguageStats),
newMigration(128, "fix merge base for pull requests", v1_12.FixMergeBase),
newMigration(129, "remove dependencies from deleted repositories", v1_12.PurgeUnusedDependencies),
newMigration(130, "Expand webhooks for more granularity", v1_12.ExpandWebhooks),
newMigration(131, "Add IsSystemWebhook column to webhooks table", v1_12.AddSystemWebhookColumn),
newMigration(132, "Add Branch Protection Protected Files Column", v1_12.AddBranchProtectionProtectedFilesColumn),
newMigration(133, "Add EmailHash Table", v1_12.AddEmailHashTable),
newMigration(134, "Refix merge base for merged pull requests", v1_12.RefixMergeBase),
newMigration(135, "Add OrgID column to Labels table", v1_12.AddOrgIDLabelColumn),
newMigration(136, "Add CommitsAhead and CommitsBehind Column to PullRequest Table", v1_12.AddCommitDivergenceToPulls),
newMigration(137, "Add Branch Protection Block Outdated Branch", v1_12.AddBlockOnOutdatedBranch),
newMigration(138, "Add ResolveDoerID to Comment table", v1_12.AddResolveDoerIDCommentColumn),
newMigration(139, "prepend refs/heads/ to issue refs", v1_12.PrependRefsHeadsToIssueRefs),
// Gitea 1.12.0 ends at v140
// Gitea 1.12.0 ends at database version 140
// v140 -> v141
NewMigration("Save detected language file size to database instead of percent", v1_13.FixLanguageStatsToSaveSize),
// v141 -> v142
NewMigration("Add KeepActivityPrivate to User table", v1_13.AddKeepActivityPrivateUserColumn),
// v142 -> v143
NewMigration("Ensure Repository.IsArchived is not null", v1_13.SetIsArchivedToFalse),
// v143 -> v144
NewMigration("recalculate Stars number for all user", v1_13.RecalculateStars),
// v144 -> v145
NewMigration("update Matrix Webhook http method to 'PUT'", v1_13.UpdateMatrixWebhookHTTPMethod),
// v145 -> v146
NewMigration("Increase Language field to 50 in LanguageStats", v1_13.IncreaseLanguageField),
// v146 -> v147
NewMigration("Add projects info to repository table", v1_13.AddProjectsInfo),
// v147 -> v148
NewMigration("create review for 0 review id code comments", v1_13.CreateReviewsForCodeComments),
// v148 -> v149
NewMigration("remove issue dependency comments who refer to non existing issues", v1_13.PurgeInvalidDependenciesComments),
// v149 -> v150
NewMigration("Add Created and Updated to Milestone table", v1_13.AddCreatedAndUpdatedToMilestones),
// v150 -> v151
NewMigration("add primary key to repo_topic", v1_13.AddPrimaryKeyToRepoTopic),
// v151 -> v152
NewMigration("set default password algorithm to Argon2", v1_13.SetDefaultPasswordToArgon2),
// v152 -> v153
NewMigration("add TrustModel field to Repository", v1_13.AddTrustModelToRepository),
// v153 > v154
NewMigration("add Team review request support", v1_13.AddTeamReviewRequestSupport),
// v154 > v155
NewMigration("add timestamps to Star, Label, Follow, Watch and Collaboration", v1_13.AddTimeStamps),
newMigration(140, "Save detected language file size to database instead of percent", v1_13.FixLanguageStatsToSaveSize),
newMigration(141, "Add KeepActivityPrivate to User table", v1_13.AddKeepActivityPrivateUserColumn),
newMigration(142, "Ensure Repository.IsArchived is not null", v1_13.SetIsArchivedToFalse),
newMigration(143, "recalculate Stars number for all user", v1_13.RecalculateStars),
newMigration(144, "update Matrix Webhook http method to 'PUT'", v1_13.UpdateMatrixWebhookHTTPMethod),
newMigration(145, "Increase Language field to 50 in LanguageStats", v1_13.IncreaseLanguageField),
newMigration(146, "Add projects info to repository table", v1_13.AddProjectsInfo),
newMigration(147, "create review for 0 review id code comments", v1_13.CreateReviewsForCodeComments),
newMigration(148, "remove issue dependency comments who refer to non existing issues", v1_13.PurgeInvalidDependenciesComments),
newMigration(149, "Add Created and Updated to Milestone table", v1_13.AddCreatedAndUpdatedToMilestones),
newMigration(150, "add primary key to repo_topic", v1_13.AddPrimaryKeyToRepoTopic),
newMigration(151, "set default password algorithm to Argon2", v1_13.SetDefaultPasswordToArgon2),
newMigration(152, "add TrustModel field to Repository", v1_13.AddTrustModelToRepository),
newMigration(153, "add Team review request support", v1_13.AddTeamReviewRequestSupport),
newMigration(154, "add timestamps to Star, Label, Follow, Watch and Collaboration", v1_13.AddTimeStamps),
// Gitea 1.13.0 ends at v155
// Gitea 1.13.0 ends at database version 155
// v155 -> v156
NewMigration("add changed_protected_files column for pull_request table", v1_14.AddChangedProtectedFilesPullRequestColumn),
// v156 -> v157
NewMigration("fix publisher ID for tag releases", v1_14.FixPublisherIDforTagReleases),
// v157 -> v158
NewMigration("ensure repo topics are up-to-date", v1_14.FixRepoTopics),
// v158 -> v159
NewMigration("code comment replies should have the commitID of the review they are replying to", v1_14.UpdateCodeCommentReplies),
// v159 -> v160
NewMigration("update reactions constraint", v1_14.UpdateReactionConstraint),
// v160 -> v161
NewMigration("Add block on official review requests branch protection", v1_14.AddBlockOnOfficialReviewRequests),
// v161 -> v162
NewMigration("Convert task type from int to string", v1_14.ConvertTaskTypeToString),
// v162 -> v163
NewMigration("Convert webhook task type from int to string", v1_14.ConvertWebhookTaskTypeToString),
// v163 -> v164
NewMigration("Convert topic name from 25 to 50", v1_14.ConvertTopicNameFrom25To50),
// v164 -> v165
NewMigration("Add scope and nonce columns to oauth2_grant table", v1_14.AddScopeAndNonceColumnsToOAuth2Grant),
// v165 -> v166
NewMigration("Convert hook task type from char(16) to varchar(16) and trim the column", v1_14.ConvertHookTaskTypeToVarcharAndTrim),
// v166 -> v167
NewMigration("Where Password is Valid with Empty String delete it", v1_14.RecalculateUserEmptyPWD),
// v167 -> v168
NewMigration("Add user redirect", v1_14.AddUserRedirect),
// v168 -> v169
NewMigration("Recreate user table to fix default values", v1_14.RecreateUserTableToFixDefaultValues),
// v169 -> v170
NewMigration("Update DeleteBranch comments to set the old_ref to the commit_sha", v1_14.CommentTypeDeleteBranchUseOldRef),
// v170 -> v171
NewMigration("Add Dismissed to Review table", v1_14.AddDismissedReviewColumn),
// v171 -> v172
NewMigration("Add Sorting to ProjectBoard table", v1_14.AddSortingColToProjectBoard),
// v172 -> v173
NewMigration("Add sessions table for go-chi/session", v1_14.AddSessionTable),
// v173 -> v174
NewMigration("Add time_id column to Comment", v1_14.AddTimeIDCommentColumn),
// v174 -> v175
NewMigration("Create repo transfer table", v1_14.AddRepoTransfer),
// v175 -> v176
NewMigration("Fix Postgres ID Sequences broken by recreate-table", v1_14.FixPostgresIDSequences),
// v176 -> v177
NewMigration("Remove invalid labels from comments", v1_14.RemoveInvalidLabels),
// v177 -> v178
NewMigration("Delete orphaned IssueLabels", v1_14.DeleteOrphanedIssueLabels),
newMigration(155, "add changed_protected_files column for pull_request table", v1_14.AddChangedProtectedFilesPullRequestColumn),
newMigration(156, "fix publisher ID for tag releases", v1_14.FixPublisherIDforTagReleases),
newMigration(157, "ensure repo topics are up-to-date", v1_14.FixRepoTopics),
newMigration(158, "code comment replies should have the commitID of the review they are replying to", v1_14.UpdateCodeCommentReplies),
newMigration(159, "update reactions constraint", v1_14.UpdateReactionConstraint),
newMigration(160, "Add block on official review requests branch protection", v1_14.AddBlockOnOfficialReviewRequests),
newMigration(161, "Convert task type from int to string", v1_14.ConvertTaskTypeToString),
newMigration(162, "Convert webhook task type from int to string", v1_14.ConvertWebhookTaskTypeToString),
newMigration(163, "Convert topic name from 25 to 50", v1_14.ConvertTopicNameFrom25To50),
newMigration(164, "Add scope and nonce columns to oauth2_grant table", v1_14.AddScopeAndNonceColumnsToOAuth2Grant),
newMigration(165, "Convert hook task type from char(16) to varchar(16) and trim the column", v1_14.ConvertHookTaskTypeToVarcharAndTrim),
newMigration(166, "Where Password is Valid with Empty String delete it", v1_14.RecalculateUserEmptyPWD),
newMigration(167, "Add user redirect", v1_14.AddUserRedirect),
newMigration(168, "Recreate user table to fix default values", v1_14.RecreateUserTableToFixDefaultValues),
newMigration(169, "Update DeleteBranch comments to set the old_ref to the commit_sha", v1_14.CommentTypeDeleteBranchUseOldRef),
newMigration(170, "Add Dismissed to Review table", v1_14.AddDismissedReviewColumn),
newMigration(171, "Add Sorting to ProjectBoard table", v1_14.AddSortingColToProjectBoard),
newMigration(172, "Add sessions table for go-chi/session", v1_14.AddSessionTable),
newMigration(173, "Add time_id column to Comment", v1_14.AddTimeIDCommentColumn),
newMigration(174, "Create repo transfer table", v1_14.AddRepoTransfer),
newMigration(175, "Fix Postgres ID Sequences broken by recreate-table", v1_14.FixPostgresIDSequences),
newMigration(176, "Remove invalid labels from comments", v1_14.RemoveInvalidLabels),
newMigration(177, "Delete orphaned IssueLabels", v1_14.DeleteOrphanedIssueLabels),
// Gitea 1.14.0 ends at v178
// Gitea 1.14.0 ends at database version 178
// v178 -> v179
NewMigration("Add LFS columns to Mirror", v1_15.AddLFSMirrorColumns),
// v179 -> v180
NewMigration("Convert avatar url to text", v1_15.ConvertAvatarURLToText),
// v180 -> v181
NewMigration("Delete credentials from past migrations", v1_15.DeleteMigrationCredentials),
// v181 -> v182
NewMigration("Always save primary email on email address table", v1_15.AddPrimaryEmail2EmailAddress),
// v182 -> v183
NewMigration("Add issue resource index table", v1_15.AddIssueResourceIndexTable),
// v183 -> v184
NewMigration("Create PushMirror table", v1_15.CreatePushMirrorTable),
// v184 -> v185
NewMigration("Rename Task errors to message", v1_15.RenameTaskErrorsToMessage),
// v185 -> v186
NewMigration("Add new table repo_archiver", v1_15.AddRepoArchiver),
// v186 -> v187
NewMigration("Create protected tag table", v1_15.CreateProtectedTagTable),
// v187 -> v188
NewMigration("Drop unneeded webhook related columns", v1_15.DropWebhookColumns),
// v188 -> v189
NewMigration("Add key is verified to gpg key", v1_15.AddKeyIsVerified),
newMigration(178, "Add LFS columns to Mirror", v1_15.AddLFSMirrorColumns),
newMigration(179, "Convert avatar url to text", v1_15.ConvertAvatarURLToText),
newMigration(180, "Delete credentials from past migrations", v1_15.DeleteMigrationCredentials),
newMigration(181, "Always save primary email on email address table", v1_15.AddPrimaryEmail2EmailAddress),
newMigration(182, "Add issue resource index table", v1_15.AddIssueResourceIndexTable),
newMigration(183, "Create PushMirror table", v1_15.CreatePushMirrorTable),
newMigration(184, "Rename Task errors to message", v1_15.RenameTaskErrorsToMessage),
newMigration(185, "Add new table repo_archiver", v1_15.AddRepoArchiver),
newMigration(186, "Create protected tag table", v1_15.CreateProtectedTagTable),
newMigration(187, "Drop unneeded webhook related columns", v1_15.DropWebhookColumns),
newMigration(188, "Add key is verified to gpg key", v1_15.AddKeyIsVerified),
// Gitea 1.15.0 ends at v189
// Gitea 1.15.0 ends at database version 189
// v189 -> v190
NewMigration("Unwrap ldap.Sources", v1_16.UnwrapLDAPSourceCfg),
// v190 -> v191
NewMigration("Add agit flow pull request support", v1_16.AddAgitFlowPullRequest),
// v191 -> v192
NewMigration("Alter issue/comment table TEXT fields to LONGTEXT", v1_16.AlterIssueAndCommentTextFieldsToLongText),
// v192 -> v193
NewMigration("RecreateIssueResourceIndexTable to have a primary key instead of an unique index", v1_16.RecreateIssueResourceIndexTable),
// v193 -> v194
NewMigration("Add repo id column for attachment table", v1_16.AddRepoIDForAttachment),
// v194 -> v195
NewMigration("Add Branch Protection Unprotected Files Column", v1_16.AddBranchProtectionUnprotectedFilesColumn),
// v195 -> v196
NewMigration("Add table commit_status_index", v1_16.AddTableCommitStatusIndex),
// v196 -> v197
NewMigration("Add Color to ProjectBoard table", v1_16.AddColorColToProjectBoard),
// v197 -> v198
NewMigration("Add renamed_branch table", v1_16.AddRenamedBranchTable),
// v198 -> v199
NewMigration("Add issue content history table", v1_16.AddTableIssueContentHistory),
// v199 -> v200
NewMigration("No-op (remote version is using AppState now)", noopMigration),
// v200 -> v201
NewMigration("Add table app_state", v1_16.AddTableAppState),
// v201 -> v202
NewMigration("Drop table remote_version (if exists)", v1_16.DropTableRemoteVersion),
// v202 -> v203
NewMigration("Create key/value table for user settings", v1_16.CreateUserSettingsTable),
// v203 -> v204
NewMigration("Add Sorting to ProjectIssue table", v1_16.AddProjectIssueSorting),
// v204 -> v205
NewMigration("Add key is verified to ssh key", v1_16.AddSSHKeyIsVerified),
// v205 -> v206
NewMigration("Migrate to higher varchar on user struct", v1_16.MigrateUserPasswordSalt),
// v206 -> v207
NewMigration("Add authorize column to team_unit table", v1_16.AddAuthorizeColForTeamUnit),
// v207 -> v208
NewMigration("Add webauthn table and migrate u2f data to webauthn - NO-OPED", v1_16.AddWebAuthnCred),
// v208 -> v209
NewMigration("Use base32.HexEncoding instead of base64 encoding for cred ID as it is case insensitive - NO-OPED", v1_16.UseBase32HexForCredIDInWebAuthnCredential),
// v209 -> v210
NewMigration("Increase WebAuthentication CredentialID size to 410 - NO-OPED", v1_16.IncreaseCredentialIDTo410),
// v210 -> v211
NewMigration("v208 was completely broken - remigrate", v1_16.RemigrateU2FCredentials),
newMigration(189, "Unwrap ldap.Sources", v1_16.UnwrapLDAPSourceCfg),
newMigration(190, "Add agit flow pull request support", v1_16.AddAgitFlowPullRequest),
newMigration(191, "Alter issue/comment table TEXT fields to LONGTEXT", v1_16.AlterIssueAndCommentTextFieldsToLongText),
newMigration(192, "RecreateIssueResourceIndexTable to have a primary key instead of an unique index", v1_16.RecreateIssueResourceIndexTable),
newMigration(193, "Add repo id column for attachment table", v1_16.AddRepoIDForAttachment),
newMigration(194, "Add Branch Protection Unprotected Files Column", v1_16.AddBranchProtectionUnprotectedFilesColumn),
newMigration(195, "Add table commit_status_index", v1_16.AddTableCommitStatusIndex),
newMigration(196, "Add Color to ProjectBoard table", v1_16.AddColorColToProjectBoard),
newMigration(197, "Add renamed_branch table", v1_16.AddRenamedBranchTable),
newMigration(198, "Add issue content history table", v1_16.AddTableIssueContentHistory),
newMigration(199, "No-op (remote version is using AppState now)", noopMigration),
newMigration(200, "Add table app_state", v1_16.AddTableAppState),
newMigration(201, "Drop table remote_version (if exists)", v1_16.DropTableRemoteVersion),
newMigration(202, "Create key/value table for user settings", v1_16.CreateUserSettingsTable),
newMigration(203, "Add Sorting to ProjectIssue table", v1_16.AddProjectIssueSorting),
newMigration(204, "Add key is verified to ssh key", v1_16.AddSSHKeyIsVerified),
newMigration(205, "Migrate to higher varchar on user struct", v1_16.MigrateUserPasswordSalt),
newMigration(206, "Add authorize column to team_unit table", v1_16.AddAuthorizeColForTeamUnit),
newMigration(207, "Add webauthn table and migrate u2f data to webauthn - NO-OPED", v1_16.AddWebAuthnCred),
newMigration(208, "Use base32.HexEncoding instead of base64 encoding for cred ID as it is case insensitive - NO-OPED", v1_16.UseBase32HexForCredIDInWebAuthnCredential),
newMigration(209, "Increase WebAuthentication CredentialID size to 410 - NO-OPED", v1_16.IncreaseCredentialIDTo410),
newMigration(210, "v208 was completely broken - remigrate", v1_16.RemigrateU2FCredentials),
// Gitea 1.16.2 ends at v211
// Gitea 1.16.2 ends at database version 211
// v211 -> v212
NewMigration("Create ForeignReference table", v1_17.CreateForeignReferenceTable),
// v212 -> v213
NewMigration("Add package tables", v1_17.AddPackageTables),
// v213 -> v214
NewMigration("Add allow edits from maintainers to PullRequest table", v1_17.AddAllowMaintainerEdit),
// v214 -> v215
NewMigration("Add auto merge table", v1_17.AddAutoMergeTable),
// v215 -> v216
NewMigration("allow to view files in PRs", v1_17.AddReviewViewedFiles),
// v216 -> v217
NewMigration("No-op (Improve Action table indices v1)", noopMigration),
// v217 -> v218
NewMigration("Alter hook_task table TEXT fields to LONGTEXT", v1_17.AlterHookTaskTextFieldsToLongText),
// v218 -> v219
NewMigration("Improve Action table indices v2", v1_17.ImproveActionTableIndices),
// v219 -> v220
NewMigration("Add sync_on_commit column to push_mirror table", v1_17.AddSyncOnCommitColForPushMirror),
// v220 -> v221
NewMigration("Add container repository property", v1_17.AddContainerRepositoryProperty),
// v221 -> v222
NewMigration("Store WebAuthentication CredentialID as bytes and increase size to at least 1024", v1_17.StoreWebauthnCredentialIDAsBytes),
// v222 -> v223
NewMigration("Drop old CredentialID column", v1_17.DropOldCredentialIDColumn),
// v223 -> v224
NewMigration("Rename CredentialIDBytes column to CredentialID", v1_17.RenameCredentialIDBytes),
newMigration(211, "Create ForeignReference table", v1_17.CreateForeignReferenceTable),
newMigration(212, "Add package tables", v1_17.AddPackageTables),
newMigration(213, "Add allow edits from maintainers to PullRequest table", v1_17.AddAllowMaintainerEdit),
newMigration(214, "Add auto merge table", v1_17.AddAutoMergeTable),
newMigration(215, "allow to view files in PRs", v1_17.AddReviewViewedFiles),
newMigration(216, "No-op (Improve Action table indices v1)", noopMigration),
newMigration(217, "Alter hook_task table TEXT fields to LONGTEXT", v1_17.AlterHookTaskTextFieldsToLongText),
newMigration(218, "Improve Action table indices v2", v1_17.ImproveActionTableIndices),
newMigration(219, "Add sync_on_commit column to push_mirror table", v1_17.AddSyncOnCommitColForPushMirror),
newMigration(220, "Add container repository property", v1_17.AddContainerRepositoryProperty),
newMigration(221, "Store WebAuthentication CredentialID as bytes and increase size to at least 1024", v1_17.StoreWebauthnCredentialIDAsBytes),
newMigration(222, "Drop old CredentialID column", v1_17.DropOldCredentialIDColumn),
newMigration(223, "Rename CredentialIDBytes column to CredentialID", v1_17.RenameCredentialIDBytes),
// Gitea 1.17.0 ends at v224
// Gitea 1.17.0 ends at database version 224
// v224 -> v225
NewMigration("Add badges to users", v1_18.CreateUserBadgesTable),
// v225 -> v226
NewMigration("Alter gpg_key/public_key content TEXT fields to MEDIUMTEXT", v1_18.AlterPublicGPGKeyContentFieldsToMediumText),
// v226 -> v227
NewMigration("Conan and generic packages do not need to be semantically versioned", v1_18.FixPackageSemverField),
// v227 -> v228
NewMigration("Create key/value table for system settings", v1_18.CreateSystemSettingsTable),
// v228 -> v229
NewMigration("Add TeamInvite table", v1_18.AddTeamInviteTable),
// v229 -> v230
NewMigration("Update counts of all open milestones", v1_18.UpdateOpenMilestoneCounts),
// v230 -> v231
NewMigration("Add ConfidentialClient column (default true) to OAuth2Application table", v1_18.AddConfidentialClientColumnToOAuth2ApplicationTable),
newMigration(224, "Add badges to users", v1_18.CreateUserBadgesTable),
newMigration(225, "Alter gpg_key/public_key content TEXT fields to MEDIUMTEXT", v1_18.AlterPublicGPGKeyContentFieldsToMediumText),
newMigration(226, "Conan and generic packages do not need to be semantically versioned", v1_18.FixPackageSemverField),
newMigration(227, "Create key/value table for system settings", v1_18.CreateSystemSettingsTable),
newMigration(228, "Add TeamInvite table", v1_18.AddTeamInviteTable),
newMigration(229, "Update counts of all open milestones", v1_18.UpdateOpenMilestoneCounts),
newMigration(230, "Add ConfidentialClient column (default true) to OAuth2Application table", v1_18.AddConfidentialClientColumnToOAuth2ApplicationTable),
// Gitea 1.18.0 ends at v231
// Gitea 1.18.0 ends at database version 231
// v231 -> v232
NewMigration("Add index for hook_task", v1_19.AddIndexForHookTask),
// v232 -> v233
NewMigration("Alter package_version.metadata_json to LONGTEXT", v1_19.AlterPackageVersionMetadataToLongText),
// v233 -> v234
NewMigration("Add header_authorization_encrypted column to webhook table", v1_19.AddHeaderAuthorizationEncryptedColWebhook),
// v234 -> v235
NewMigration("Add package cleanup rule table", v1_19.CreatePackageCleanupRuleTable),
// v235 -> v236
NewMigration("Add index for access_token", v1_19.AddIndexForAccessToken),
// v236 -> v237
NewMigration("Create secrets table", v1_19.CreateSecretsTable),
// v237 -> v238
NewMigration("Drop ForeignReference table", v1_19.DropForeignReferenceTable),
// v238 -> v239
NewMigration("Add updated unix to LFSMetaObject", v1_19.AddUpdatedUnixToLFSMetaObject),
// v239 -> v240
NewMigration("Add scope for access_token", v1_19.AddScopeForAccessTokens),
// v240 -> v241
NewMigration("Add actions tables", v1_19.AddActionsTables),
// v241 -> v242
NewMigration("Add card_type column to project table", v1_19.AddCardTypeToProjectTable),
// v242 -> v243
NewMigration("Alter gpg_key_import content TEXT field to MEDIUMTEXT", v1_19.AlterPublicGPGKeyImportContentFieldToMediumText),
// v243 -> v244
NewMigration("Add exclusive label", v1_19.AddExclusiveLabel),
newMigration(231, "Add index for hook_task", v1_19.AddIndexForHookTask),
newMigration(232, "Alter package_version.metadata_json to LONGTEXT", v1_19.AlterPackageVersionMetadataToLongText),
newMigration(233, "Add header_authorization_encrypted column to webhook table", v1_19.AddHeaderAuthorizationEncryptedColWebhook),
newMigration(234, "Add package cleanup rule table", v1_19.CreatePackageCleanupRuleTable),
newMigration(235, "Add index for access_token", v1_19.AddIndexForAccessToken),
newMigration(236, "Create secrets table", v1_19.CreateSecretsTable),
newMigration(237, "Drop ForeignReference table", v1_19.DropForeignReferenceTable),
newMigration(238, "Add updated unix to LFSMetaObject", v1_19.AddUpdatedUnixToLFSMetaObject),
newMigration(239, "Add scope for access_token", v1_19.AddScopeForAccessTokens),
newMigration(240, "Add actions tables", v1_19.AddActionsTables),
newMigration(241, "Add card_type column to project table", v1_19.AddCardTypeToProjectTable),
newMigration(242, "Alter gpg_key_import content TEXT field to MEDIUMTEXT", v1_19.AlterPublicGPGKeyImportContentFieldToMediumText),
newMigration(243, "Add exclusive label", v1_19.AddExclusiveLabel),
// Gitea 1.19.0 ends at v244
// Gitea 1.19.0 ends at database version 244
// v244 -> v245
NewMigration("Add NeedApproval to actions tables", v1_20.AddNeedApprovalToActionRun),
// v245 -> v246
NewMigration("Rename Webhook org_id to owner_id", v1_20.RenameWebhookOrgToOwner),
// v246 -> v247
NewMigration("Add missed column owner_id for project table", v1_20.AddNewColumnForProject),
// v247 -> v248
NewMigration("Fix incorrect project type", v1_20.FixIncorrectProjectType),
// v248 -> v249
NewMigration("Add version column to action_runner table", v1_20.AddVersionToActionRunner),
// v249 -> v250
NewMigration("Improve Action table indices v3", v1_20.ImproveActionTableIndices),
// v250 -> v251
NewMigration("Change Container Metadata", v1_20.ChangeContainerMetadataMultiArch),
// v251 -> v252
NewMigration("Fix incorrect owner team unit access mode", v1_20.FixIncorrectOwnerTeamUnitAccessMode),
// v252 -> v253
NewMigration("Fix incorrect admin team unit access mode", v1_20.FixIncorrectAdminTeamUnitAccessMode),
// v253 -> v254
NewMigration("Fix ExternalTracker and ExternalWiki accessMode in owner and admin team", v1_20.FixExternalTrackerAndExternalWikiAccessModeInOwnerAndAdminTeam),
// v254 -> v255
NewMigration("Add ActionTaskOutput table", v1_20.AddActionTaskOutputTable),
// v255 -> v256
NewMigration("Add ArchivedUnix Column", v1_20.AddArchivedUnixToRepository),
// v256 -> v257
NewMigration("Add is_internal column to package", v1_20.AddIsInternalColumnToPackage),
// v257 -> v258
NewMigration("Add Actions Artifact table", v1_20.CreateActionArtifactTable),
// v258 -> v259
NewMigration("Add PinOrder Column", v1_20.AddPinOrderToIssue),
// v259 -> v260
NewMigration("Convert scoped access tokens", v1_20.ConvertScopedAccessTokens),
newMigration(244, "Add NeedApproval to actions tables", v1_20.AddNeedApprovalToActionRun),
newMigration(245, "Rename Webhook org_id to owner_id", v1_20.RenameWebhookOrgToOwner),
newMigration(246, "Add missed column owner_id for project table", v1_20.AddNewColumnForProject),
newMigration(247, "Fix incorrect project type", v1_20.FixIncorrectProjectType),
newMigration(248, "Add version column to action_runner table", v1_20.AddVersionToActionRunner),
newMigration(249, "Improve Action table indices v3", v1_20.ImproveActionTableIndices),
newMigration(250, "Change Container Metadata", v1_20.ChangeContainerMetadataMultiArch),
newMigration(251, "Fix incorrect owner team unit access mode", v1_20.FixIncorrectOwnerTeamUnitAccessMode),
newMigration(252, "Fix incorrect admin team unit access mode", v1_20.FixIncorrectAdminTeamUnitAccessMode),
newMigration(253, "Fix ExternalTracker and ExternalWiki accessMode in owner and admin team", v1_20.FixExternalTrackerAndExternalWikiAccessModeInOwnerAndAdminTeam),
newMigration(254, "Add ActionTaskOutput table", v1_20.AddActionTaskOutputTable),
newMigration(255, "Add ArchivedUnix Column", v1_20.AddArchivedUnixToRepository),
newMigration(256, "Add is_internal column to package", v1_20.AddIsInternalColumnToPackage),
newMigration(257, "Add Actions Artifact table", v1_20.CreateActionArtifactTable),
newMigration(258, "Add PinOrder Column", v1_20.AddPinOrderToIssue),
newMigration(259, "Convert scoped access tokens", v1_20.ConvertScopedAccessTokens),
// Gitea 1.20.0 ends at 260
// Gitea 1.20.0 ends at database version 260
// v260 -> v261
NewMigration("Drop custom_labels column of action_runner table", v1_21.DropCustomLabelsColumnOfActionRunner),
// v261 -> v262
NewMigration("Add variable table", v1_21.CreateVariableTable),
// v262 -> v263
NewMigration("Add TriggerEvent to action_run table", v1_21.AddTriggerEventToActionRun),
// v263 -> v264
NewMigration("Add git_size and lfs_size columns to repository table", v1_21.AddGitSizeAndLFSSizeToRepositoryTable),
// v264 -> v265
NewMigration("Add branch table", v1_21.AddBranchTable),
// v265 -> v266
NewMigration("Alter Actions Artifact table", v1_21.AlterActionArtifactTable),
// v266 -> v267
NewMigration("Reduce commit status", v1_21.ReduceCommitStatus),
// v267 -> v268
NewMigration("Add action_tasks_version table", v1_21.CreateActionTasksVersionTable),
// v268 -> v269
NewMigration("Update Action Ref", v1_21.UpdateActionsRefIndex),
// v269 -> v270
NewMigration("Drop deleted branch table", v1_21.DropDeletedBranchTable),
// v270 -> v271
NewMigration("Fix PackageProperty typo", v1_21.FixPackagePropertyTypo),
// v271 -> v272
NewMigration("Allow archiving labels", v1_21.AddArchivedUnixColumInLabelTable),
// v272 -> v273
NewMigration("Add Version to ActionRun table", v1_21.AddVersionToActionRunTable),
// v273 -> v274
NewMigration("Add Action Schedule Table", v1_21.AddActionScheduleTable),
// v274 -> v275
NewMigration("Add Actions artifacts expiration date", v1_21.AddExpiredUnixColumnInActionArtifactTable),
// v275 -> v276
NewMigration("Add ScheduleID for ActionRun", v1_21.AddScheduleIDForActionRun),
// v276 -> v277
NewMigration("Add RemoteAddress to mirrors", v1_21.AddRemoteAddressToMirrors),
// v277 -> v278
NewMigration("Add Index to issue_user.issue_id", v1_21.AddIndexToIssueUserIssueID),
// v278 -> v279
NewMigration("Add Index to comment.dependent_issue_id", v1_21.AddIndexToCommentDependentIssueID),
// v279 -> v280
NewMigration("Add Index to action.user_id", v1_21.AddIndexToActionUserID),
newMigration(260, "Drop custom_labels column of action_runner table", v1_21.DropCustomLabelsColumnOfActionRunner),
newMigration(261, "Add variable table", v1_21.CreateVariableTable),
newMigration(262, "Add TriggerEvent to action_run table", v1_21.AddTriggerEventToActionRun),
newMigration(263, "Add git_size and lfs_size columns to repository table", v1_21.AddGitSizeAndLFSSizeToRepositoryTable),
newMigration(264, "Add branch table", v1_21.AddBranchTable),
newMigration(265, "Alter Actions Artifact table", v1_21.AlterActionArtifactTable),
newMigration(266, "Reduce commit status", v1_21.ReduceCommitStatus),
newMigration(267, "Add action_tasks_version table", v1_21.CreateActionTasksVersionTable),
newMigration(268, "Update Action Ref", v1_21.UpdateActionsRefIndex),
newMigration(269, "Drop deleted branch table", v1_21.DropDeletedBranchTable),
newMigration(270, "Fix PackageProperty typo", v1_21.FixPackagePropertyTypo),
newMigration(271, "Allow archiving labels", v1_21.AddArchivedUnixColumInLabelTable),
newMigration(272, "Add Version to ActionRun table", v1_21.AddVersionToActionRunTable),
newMigration(273, "Add Action Schedule Table", v1_21.AddActionScheduleTable),
newMigration(274, "Add Actions artifacts expiration date", v1_21.AddExpiredUnixColumnInActionArtifactTable),
newMigration(275, "Add ScheduleID for ActionRun", v1_21.AddScheduleIDForActionRun),
newMigration(276, "Add RemoteAddress to mirrors", v1_21.AddRemoteAddressToMirrors),
newMigration(277, "Add Index to issue_user.issue_id", v1_21.AddIndexToIssueUserIssueID),
newMigration(278, "Add Index to comment.dependent_issue_id", v1_21.AddIndexToCommentDependentIssueID),
newMigration(279, "Add Index to action.user_id", v1_21.AddIndexToActionUserID),
// Gitea 1.21.0 ends at 280
// Gitea 1.21.0 ends at database version 280
// v280 -> v281
NewMigration("Rename user themes", v1_22.RenameUserThemes),
// v281 -> v282
NewMigration("Add auth_token table", v1_22.CreateAuthTokenTable),
// v282 -> v283
NewMigration("Add Index to pull_auto_merge.doer_id", v1_22.AddIndexToPullAutoMergeDoerID),
// v283 -> v284
NewMigration("Add combined Index to issue_user.uid and issue_id", v1_22.AddCombinedIndexToIssueUser),
// v284 -> v285
NewMigration("Add ignore stale approval column on branch table", v1_22.AddIgnoreStaleApprovalsColumnToProtectedBranchTable),
// v285 -> v286
NewMigration("Add PreviousDuration to ActionRun", v1_22.AddPreviousDurationToActionRun),
// v286 -> v287
NewMigration("Add support for SHA256 git repositories", v1_22.AdjustDBForSha256),
// v287 -> v288
NewMigration("Use Slug instead of ID for Badges", v1_22.UseSlugInsteadOfIDForBadges),
// v288 -> v289
NewMigration("Add user_blocking table", v1_22.AddUserBlockingTable),
// v289 -> v290
NewMigration("Add default_wiki_branch to repository table", v1_22.AddDefaultWikiBranch),
// v290 -> v291
NewMigration("Add PayloadVersion to HookTask", v1_22.AddPayloadVersionToHookTaskTable),
// v291 -> v292
NewMigration("Add Index to attachment.comment_id", v1_22.AddCommentIDIndexofAttachment),
// v292 -> v293
NewMigration("Ensure every project has exactly one default column - No Op", noopMigration),
// v293 -> v294
NewMigration("Ensure every project has exactly one default column", v1_22.CheckProjectColumnsConsistency),
newMigration(280, "Rename user themes", v1_22.RenameUserThemes),
newMigration(281, "Add auth_token table", v1_22.CreateAuthTokenTable),
newMigration(282, "Add Index to pull_auto_merge.doer_id", v1_22.AddIndexToPullAutoMergeDoerID),
newMigration(283, "Add combined Index to issue_user.uid and issue_id", v1_22.AddCombinedIndexToIssueUser),
newMigration(284, "Add ignore stale approval column on branch table", v1_22.AddIgnoreStaleApprovalsColumnToProtectedBranchTable),
newMigration(285, "Add PreviousDuration to ActionRun", v1_22.AddPreviousDurationToActionRun),
newMigration(286, "Add support for SHA256 git repositories", v1_22.AdjustDBForSha256),
newMigration(287, "Use Slug instead of ID for Badges", v1_22.UseSlugInsteadOfIDForBadges),
newMigration(288, "Add user_blocking table", v1_22.AddUserBlockingTable),
newMigration(289, "Add default_wiki_branch to repository table", v1_22.AddDefaultWikiBranch),
newMigration(290, "Add PayloadVersion to HookTask", v1_22.AddPayloadVersionToHookTaskTable),
newMigration(291, "Add Index to attachment.comment_id", v1_22.AddCommentIDIndexofAttachment),
newMigration(292, "Ensure every project has exactly one default column - No Op", noopMigration),
newMigration(293, "Ensure every project has exactly one default column", v1_22.CheckProjectColumnsConsistency),
// Gitea 1.22.0-rc0 ends at 294
// Gitea 1.22.0-rc0 ends at database version 294
// v294 -> v295
NewMigration("Add unique index for project issue table", v1_22.AddUniqueIndexForProjectIssue),
// v295 -> v296
NewMigration("Add commit status summary table", v1_22.AddCommitStatusSummary),
// v296 -> v297
NewMigration("Add missing field of commit status summary table", v1_22.AddCommitStatusSummary2),
// v297 -> v298
NewMigration("Add everyone_access_mode for repo_unit", noopMigration),
// v298 -> v299
NewMigration("Drop wrongly created table o_auth2_application", v1_22.DropWronglyCreatedTable),
newMigration(294, "Add unique index for project issue table", v1_22.AddUniqueIndexForProjectIssue),
newMigration(295, "Add commit status summary table", v1_22.AddCommitStatusSummary),
newMigration(296, "Add missing field of commit status summary table", v1_22.AddCommitStatusSummary2),
newMigration(297, "Add everyone_access_mode for repo_unit", noopMigration),
newMigration(298, "Drop wrongly created table o_auth2_application", v1_22.DropWronglyCreatedTable),
// Gitea 1.22.0-rc1 ends at 299
// Gitea 1.22.0-rc1 ends at migration ID number 298 (database version 299)
// v299 -> v300
NewMigration("Add content version to issue and comment table", v1_23.AddContentVersionToIssueAndComment),
// v300 -> v301
NewMigration("Add force-push branch protection support", v1_23.AddForcePushBranchProtection),
// v301 -> v302
NewMigration("Add skip_secondary_authorization option to oauth2 application table", v1_23.AddSkipSecondaryAuthColumnToOAuth2ApplicationTable),
// v302 -> v303
NewMigration("Add index to action_task stopped log_expired", v1_23.AddIndexToActionTaskStoppedLogExpired),
newMigration(299, "Add content version to issue and comment table", v1_23.AddContentVersionToIssueAndComment),
newMigration(300, "Add force-push branch protection support", v1_23.AddForcePushBranchProtection),
newMigration(301, "Add skip_secondary_authorization option to oauth2 application table", v1_23.AddSkipSecondaryAuthColumnToOAuth2ApplicationTable),
newMigration(302, "Add index to action_task stopped log_expired", v1_23.AddIndexToActionTaskStoppedLogExpired),
}
return preparedMigrations
}
// GetCurrentDBVersion returns the current db version
@ -618,9 +383,20 @@ func GetCurrentDBVersion(x *xorm.Engine) (int64, error) {
return currentVersion.Version, nil
}
// ExpectedVersion returns the expected db version
func ExpectedVersion() int64 {
return int64(minDBVersion + len(migrations))
func calcDBVersion(migrations []*migration) int64 {
dbVer := int64(minDBVersion + len(migrations))
if migrations[0].idNumber != minDBVersion {
panic("migrations should start at minDBVersion")
}
if dbVer != migrations[len(migrations)-1].idNumber+1 {
panic("migrations are not in order")
}
return dbVer
}
// ExpectedDBVersion returns the expected db version
func ExpectedDBVersion() int64 {
return calcDBVersion(prepareMigrationTasks())
}
// EnsureUpToDate will check if the db is at the correct version
@ -631,24 +407,35 @@ func EnsureUpToDate(x *xorm.Engine) error {
}
if currentDB < 0 {
return fmt.Errorf("Database has not been initialized")
return fmt.Errorf("database has not been initialized")
}
if minDBVersion > currentDB {
return fmt.Errorf("DB version %d (<= %d) is too old for auto-migration. Upgrade to Gitea 1.6.4 first then upgrade to this version", currentDB, minDBVersion)
}
expected := ExpectedVersion()
expectedDB := ExpectedDBVersion()
if currentDB != expected {
return fmt.Errorf(`Current database version %d is not equal to the expected version %d. Please run "forgejo [--config /path/to/app.ini] migrate" to update the database version`, currentDB, expected)
if currentDB != expectedDB {
return fmt.Errorf(`current database version %d is not equal to the expected version %d. Please run "forgejo [--config /path/to/app.ini] migrate" to update the database version`, currentDB, expectedDB)
}
return forgejo_migrations.EnsureUpToDate(x)
}
func getPendingMigrations(curDBVer int64, migrations []*migration) []*migration {
return migrations[curDBVer-minDBVersion:]
}
func migrationIDNumberToDBVersion(idNumber int64) int64 {
return idNumber + 1
}
// Migrate database to current version
func Migrate(x *xorm.Engine) error {
migrations := prepareMigrationTasks()
maxDBVer := calcDBVersion(migrations)
// Set a new clean the default mapper to GonicMapper as that is the default for Gitea.
x.SetMapper(names.GonicMapper{})
if err := x.Sync(new(Version)); err != nil {
@ -661,11 +448,10 @@ func Migrate(x *xorm.Engine) error {
if err != nil {
return fmt.Errorf("get: %w", err)
} else if !has {
// If the version record does not exist we think
// it is a fresh installation and we can skip all migrations.
// If the version record does not exist, it is a fresh installation, and we can skip all migrations.
// XORM model framework will create all tables when initializing.
currentVersion.ID = 0
currentVersion.Version = int64(minDBVersion + len(migrations))
currentVersion.Version = maxDBVer
if _, err = x.InsertOne(currentVersion); err != nil {
return fmt.Errorf("insert: %w", err)
}
@ -673,19 +459,20 @@ func Migrate(x *xorm.Engine) error {
previousVersion = currentVersion.Version
}
v := currentVersion.Version
if minDBVersion > v {
curDBVer := currentVersion.Version
// Outdated Forgejo database version is not supported
if curDBVer < minDBVersion {
log.Fatal(`Forgejo no longer supports auto-migration from your previously installed version.
Please try upgrading to a lower version first (suggested v1.6.4), then upgrade to this version.`)
return nil
}
// Downgrading Forgejo database version is not supported
if int(v-minDBVersion) > len(migrations) {
msg := fmt.Sprintf("Your database (migration version: %d) is for a newer Forgejo, you can not use the newer database for this old Forgejo release (%d).", v, minDBVersion+len(migrations))
// Downgrading Forgejo's database version not supported
if maxDBVer < curDBVer {
msg := fmt.Sprintf("Your database (migration version: %d) is for a newer Forgejo, you can not use the newer database for this old Forgejo release (%d).", curDBVer, maxDBVer)
msg += "\nForgejo will exit to keep your database safe and unchanged. Please use the correct Forgejo release, do not change the migration version manually (incorrect manual operation may lose data)."
if !setting.IsProd {
msg += fmt.Sprintf("\nIf you are in development and really know what you're doing, you can force changing the migration version by executing: UPDATE version SET version=%d WHERE id=1;", minDBVersion+len(migrations))
msg += fmt.Sprintf("\nIf you are in development and really know what you're doing, you can force changing the migration version by executing: UPDATE version SET version=%d WHERE id=1;", maxDBVer)
}
log.Fatal("Migration Error: %s", msg)
return nil
@ -703,14 +490,14 @@ Please try upgrading to a lower version first (suggested v1.6.4), then upgrade t
}
// Migrate
for i, m := range migrations[v-minDBVersion:] {
log.Info("Migration[%d]: %s", v+int64(i), m.Description())
for _, m := range getPendingMigrations(curDBVer, migrations) {
log.Info("Migration[%d]: %s", m.idNumber, m.description)
// Reset the mapper between each migration - migrations are not supposed to depend on each other
x.SetMapper(names.GonicMapper{})
if err = m.Migrate(x); err != nil {
return fmt.Errorf("migration[%d]: %s failed: %w", v+int64(i), m.Description(), err)
return fmt.Errorf("migration[%d]: %s failed: %w", m.idNumber, m.description, err)
}
currentVersion.Version = v + int64(i) + 1
currentVersion.Version = migrationIDNumberToDBVersion(m.idNumber)
if _, err = x.ID(1).Update(currentVersion); err != nil {
return err
}

View file

@ -0,0 +1,27 @@
// Copyright 2024 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package migrations
import (
"testing"
"code.gitea.io/gitea/modules/test"
"github.com/stretchr/testify/assert"
)
func TestMigrations(t *testing.T) {
defer test.MockVariableValue(&preparedMigrations, []*migration{
{idNumber: 70},
{idNumber: 71},
})()
assert.EqualValues(t, 72, calcDBVersion(preparedMigrations))
assert.EqualValues(t, 72, ExpectedDBVersion())
assert.EqualValues(t, 71, migrationIDNumberToDBVersion(70))
assert.EqualValues(t, []*migration{{idNumber: 70}, {idNumber: 71}}, getPendingMigrations(70, preparedMigrations))
assert.EqualValues(t, []*migration{{idNumber: 71}}, getPendingMigrations(71, preparedMigrations))
assert.EqualValues(t, []*migration{}, getPendingMigrations(72, preparedMigrations))
}

View file

@ -0,0 +1,10 @@
-
id: 1000
org_id: 1000
lower_name: owners
name: Owners
authorize: 4 # owner
num_repos: 0
num_members: 0
includes_all_repositories: true
can_create_org_repo: true

View file

@ -0,0 +1,59 @@
-
id: 1000
team_id: 1000
type: 1
access_mode: 0 # None
-
id: 1001
team_id: 1000
type: 2
access_mode: 0
-
id: 1002
team_id: 1000
type: 3
access_mode: 0
-
id: 1003
team_id: 1000
type: 4
access_mode: 0
-
id: 1004
team_id: 1000
type: 5
access_mode: 0
-
id: 1005
team_id: 1000
type: 6
access_mode: 0
-
id: 1006
team_id: 1000
type: 7
access_mode: 0
-
id: 1007
team_id: 1000
type: 8
access_mode: 0
-
id: 1008
team_id: 1000
type: 9
access_mode: 0
-
id: 1009
team_id: 1000
type: 10
access_mode: 0

View file

@ -11,6 +11,7 @@ import (
_ "code.gitea.io/gitea/models"
_ "code.gitea.io/gitea/models/actions"
_ "code.gitea.io/gitea/models/activities"
_ "code.gitea.io/gitea/models/forgefed"
_ "code.gitea.io/gitea/models/organization"
_ "code.gitea.io/gitea/models/repo"
_ "code.gitea.io/gitea/models/user"

View file

@ -299,8 +299,8 @@ func TestAccessibleReposEnv_RepoIDs(t *testing.T) {
require.NoError(t, err)
assert.Equal(t, expectedRepoIDs, repoIDs)
}
testSuccess(2, []int64{3, 5, 32})
testSuccess(4, []int64{3, 32})
testSuccess(2, []int64{32, 5, 3})
testSuccess(4, []int64{32, 3})
}
func TestAccessibleReposEnv_Repos(t *testing.T) {
@ -318,8 +318,8 @@ func TestAccessibleReposEnv_Repos(t *testing.T) {
}
assert.Equal(t, expectedRepos, repos)
}
testSuccess(2, []int64{3, 5, 32})
testSuccess(4, []int64{3, 32})
testSuccess(2, []int64{32, 5, 3})
testSuccess(4, []int64{32, 3})
}
func TestAccessibleReposEnv_MirrorRepos(t *testing.T) {

View file

@ -268,3 +268,43 @@ func IncrTeamRepoNum(ctx context.Context, teamID int64) error {
_, err := db.GetEngine(ctx).Incr("num_repos").ID(teamID).Update(new(Team))
return err
}
// CountInconsistentOwnerTeams returns the amount of owner teams that have all of
// their access modes set to "None".
func CountInconsistentOwnerTeams(ctx context.Context) (int64, error) {
return db.GetEngine(ctx).Table("team").
Join("INNER", "team_unit", "`team`.id = `team_unit`.team_id").
Where("`team`.lower_name = ?", strings.ToLower(OwnerTeamName)).
GroupBy("`team_unit`.team_id").
Having("SUM(`team_unit`.access_mode) = 0").
Count()
}
// FixInconsistentOwnerTeams fixes inconsistent owner teams that have all of
// their access modes set to "None", it sets it back to "Owner".
func FixInconsistentOwnerTeams(ctx context.Context) (int64, error) {
teamIDs := []int64{}
if err := db.GetEngine(ctx).Table("team").
Select("`team`.id").
Join("INNER", "team_unit", "`team`.id = `team_unit`.team_id").
Where("`team`.lower_name = ?", strings.ToLower(OwnerTeamName)).
GroupBy("`team_unit`.team_id").
Having("SUM(`team_unit`.access_mode) = 0").
Find(&teamIDs); err != nil {
return 0, err
}
if err := db.Iterate(ctx, builder.In("team_id", teamIDs), func(ctx context.Context, bean *TeamUnit) error {
if bean.Type == unit.TypeExternalTracker || bean.Type == unit.TypeExternalWiki {
bean.AccessMode = perm.AccessModeRead
} else {
bean.AccessMode = perm.AccessModeOwner
}
_, err := db.GetEngine(ctx).ID(bean.ID).Table("team_unit").Cols("access_mode").Update(bean)
return err
}); err != nil {
return 0, err
}
return int64(len(teamIDs)), nil
}

View file

@ -4,11 +4,14 @@
package organization_test
import (
"path/filepath"
"testing"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/organization"
"code.gitea.io/gitea/models/perm"
"code.gitea.io/gitea/models/unittest"
"code.gitea.io/gitea/modules/setting"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@ -198,3 +201,50 @@ func TestUsersInTeamsCount(t *testing.T) {
test([]int64{1, 2, 3, 4, 5}, []int64{2, 5}, 2) // userid 2,4
test([]int64{1, 2, 3, 4, 5}, []int64{2, 3, 5}, 3) // userid 2,4,5
}
func TestInconsistentOwnerTeam(t *testing.T) {
defer unittest.OverrideFixtures(
unittest.FixturesOptions{
Dir: filepath.Join(setting.AppWorkPath, "models/fixtures/"),
Base: setting.AppWorkPath,
Dirs: []string{"models/organization/TestInconsistentOwnerTeam/"},
},
)()
require.NoError(t, unittest.PrepareTestDatabase())
unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{ID: 1000, TeamID: 1000, AccessMode: perm.AccessModeNone})
unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{ID: 1001, TeamID: 1000, AccessMode: perm.AccessModeNone})
unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{ID: 1002, TeamID: 1000, AccessMode: perm.AccessModeNone})
unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{ID: 1003, TeamID: 1000, AccessMode: perm.AccessModeNone})
unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{ID: 1004, TeamID: 1000, AccessMode: perm.AccessModeNone})
unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{ID: 1005, TeamID: 1000, AccessMode: perm.AccessModeNone})
unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{ID: 1006, TeamID: 1000, AccessMode: perm.AccessModeNone})
unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{ID: 1007, TeamID: 1000, AccessMode: perm.AccessModeNone})
unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{ID: 1008, TeamID: 1000, AccessMode: perm.AccessModeNone})
unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{ID: 1009, TeamID: 1000, AccessMode: perm.AccessModeNone})
count, err := organization.CountInconsistentOwnerTeams(db.DefaultContext)
require.NoError(t, err)
require.EqualValues(t, 1, count)
count, err = organization.FixInconsistentOwnerTeams(db.DefaultContext)
require.NoError(t, err)
require.EqualValues(t, 1, count)
count, err = organization.CountInconsistentOwnerTeams(db.DefaultContext)
require.NoError(t, err)
require.EqualValues(t, 0, count)
unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{ID: 1000, AccessMode: perm.AccessModeOwner})
unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{ID: 1001, AccessMode: perm.AccessModeOwner})
unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{ID: 1002, AccessMode: perm.AccessModeOwner})
unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{ID: 1003, AccessMode: perm.AccessModeOwner})
unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{ID: 1004, AccessMode: perm.AccessModeOwner})
unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{ID: 1007, AccessMode: perm.AccessModeOwner})
unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{ID: 1008, AccessMode: perm.AccessModeOwner})
unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{ID: 1009, AccessMode: perm.AccessModeOwner})
// External wiki and issue
unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{ID: 1005, AccessMode: perm.AccessModeRead})
unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{ID: 1006, AccessMode: perm.AccessModeRead})
}

View file

@ -10,6 +10,7 @@ import (
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/packages"
debian_module "code.gitea.io/gitea/modules/packages/debian"
"code.gitea.io/gitea/modules/setting"
"xorm.io/builder"
)
@ -76,25 +77,41 @@ func ExistPackages(ctx context.Context, opts *PackageSearchOptions) (bool, error
// SearchPackages gets the packages matching the search options
func SearchPackages(ctx context.Context, opts *PackageSearchOptions, iter func(*packages.PackageFileDescriptor)) error {
return db.GetEngine(ctx).
var start int
batchSize := setting.Database.IterateBufferSize
for {
select {
case <-ctx.Done():
return ctx.Err()
default:
beans := make([]*packages.PackageFile, 0, batchSize)
if err := db.GetEngine(ctx).
Table("package_file").
Select("package_file.*").
Join("INNER", "package_version", "package_version.id = package_file.version_id").
Join("INNER", "package", "package.id = package_version.package_id").
Where(opts.toCond()).
Asc("package.lower_name", "package_version.created_unix").
Iterate(new(packages.PackageFile), func(_ int, bean any) error {
pf := bean.(*packages.PackageFile)
Limit(batchSize, start).
Find(&beans); err != nil {
return err
}
if len(beans) == 0 {
return nil
}
start += len(beans)
pfd, err := packages.GetPackageFileDescriptor(ctx, pf)
for _, bean := range beans {
pfd, err := packages.GetPackageFileDescriptor(ctx, bean)
if err != nil {
return err
}
iter(pfd)
return nil
})
}
}
}
}
// GetDistributions gets all available distributions

View file

@ -0,0 +1,94 @@
// Copyright 2024 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: GPL-3.0-or-later
package debian
import (
"strings"
"testing"
"code.gitea.io/gitea/models/db"
packages_model "code.gitea.io/gitea/models/packages"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/packages"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/test"
packages_service "code.gitea.io/gitea/services/packages"
_ "code.gitea.io/gitea/models"
_ "code.gitea.io/gitea/models/actions"
_ "code.gitea.io/gitea/models/activities"
_ "code.gitea.io/gitea/models/forgefed"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestMain(m *testing.M) {
unittest.MainTest(m)
}
func preparePackage(t *testing.T, owner *user_model.User, name string) {
t.Helper()
data, err := packages.CreateHashedBufferFromReader(strings.NewReader("data"))
require.NoError(t, err)
_, _, err = packages_service.CreatePackageOrAddFileToExisting(
db.DefaultContext,
&packages_service.PackageCreationInfo{
PackageInfo: packages_service.PackageInfo{
Owner: owner,
PackageType: packages_model.TypeDebian,
Name: name,
},
Creator: owner,
},
&packages_service.PackageFileCreationInfo{
PackageFileInfo: packages_service.PackageFileInfo{
Filename: name,
},
Data: data,
Creator: owner,
IsLead: true,
},
)
require.NoError(t, err)
}
func TestSearchPackages(t *testing.T) {
require.NoError(t, unittest.PrepareTestDatabase())
defer test.MockVariableValue(&setting.Database.IterateBufferSize, 1)()
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
user3 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3})
preparePackage(t, user2, "debian-1")
preparePackage(t, user2, "debian-2")
preparePackage(t, user3, "debian-1")
packageFiles := []string{}
require.NoError(t, SearchPackages(db.DefaultContext, &PackageSearchOptions{
OwnerID: user2.ID,
}, func(pfd *packages_model.PackageFileDescriptor) {
assert.NotNil(t, pfd)
packageFiles = append(packageFiles, pfd.File.Name)
}))
assert.Len(t, packageFiles, 2)
assert.Contains(t, packageFiles, "debian-1")
assert.Contains(t, packageFiles, "debian-2")
packageFiles = []string{}
require.NoError(t, SearchPackages(db.DefaultContext, &PackageSearchOptions{
OwnerID: user3.ID,
}, func(pfd *packages_model.PackageFileDescriptor) {
assert.NotNil(t, pfd)
packageFiles = append(packageFiles, pfd.File.Name)
}))
assert.Len(t, packageFiles, 1)
assert.Contains(t, packageFiles, "debian-1")
}

View file

@ -16,6 +16,7 @@ import (
_ "code.gitea.io/gitea/models"
_ "code.gitea.io/gitea/models/actions"
_ "code.gitea.io/gitea/models/activities"
_ "code.gitea.io/gitea/models/forgefed"
"github.com/stretchr/testify/require"
)

View file

@ -11,6 +11,7 @@ import (
_ "code.gitea.io/gitea/models"
_ "code.gitea.io/gitea/models/actions"
_ "code.gitea.io/gitea/models/activities"
_ "code.gitea.io/gitea/models/forgefed"
_ "code.gitea.io/gitea/models/repo"
_ "code.gitea.io/gitea/models/user"
)

View file

@ -5,7 +5,6 @@ package project
import (
"fmt"
"strings"
"testing"
"code.gitea.io/gitea/models/db"
@ -124,5 +123,5 @@ func Test_NewColumn(t *testing.T) {
ProjectID: project1.ID,
})
require.Error(t, err)
assert.True(t, strings.Contains(err.Error(), "maximum number of columns reached"))
assert.Contains(t, err.Error(), "maximum number of columns reached")
}

View file

@ -21,6 +21,7 @@ type AutoMerge struct {
Doer *user_model.User `xorm:"-"`
MergeStyle repo_model.MergeStyle `xorm:"varchar(30)"`
Message string `xorm:"LONGTEXT"`
DeleteBranchAfterMerge bool `xorm:"NOT NULL DEFAULT false"`
CreatedUnix timeutil.TimeStamp `xorm:"created"`
}
@ -49,7 +50,7 @@ func IsErrAlreadyScheduledToAutoMerge(err error) bool {
}
// ScheduleAutoMerge schedules a pull request to be merged when all checks succeed
func ScheduleAutoMerge(ctx context.Context, doer *user_model.User, pullID int64, style repo_model.MergeStyle, message string) error {
func ScheduleAutoMerge(ctx context.Context, doer *user_model.User, pullID int64, style repo_model.MergeStyle, message string, deleteBranch bool) error {
// Check if we already have a merge scheduled for that pull request
if exists, _, err := GetScheduledMergeByPullID(ctx, pullID); err != nil {
return err
@ -62,6 +63,7 @@ func ScheduleAutoMerge(ctx context.Context, doer *user_model.User, pullID int64,
PullID: pullID,
MergeStyle: style,
Message: message,
DeleteBranchAfterMerge: deleteBranch,
})
return err
}

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