mirror of
https://codeberg.org/forgejo/forgejo
synced 2024-11-25 11:16:11 +01:00
Merge remote-tracking branch 'upstream/forgejo' into syncfork
This commit is contained in:
commit
61fc854a44
|
@ -30,7 +30,6 @@ code.gitea.io/gitea/models/asymkey
|
||||||
|
|
||||||
code.gitea.io/gitea/models/auth
|
code.gitea.io/gitea/models/auth
|
||||||
GetSourceByName
|
GetSourceByName
|
||||||
GetWebAuthnCredentialByID
|
|
||||||
WebAuthnCredentials
|
WebAuthnCredentials
|
||||||
|
|
||||||
code.gitea.io/gitea/models/db
|
code.gitea.io/gitea/models/db
|
||||||
|
@ -75,10 +74,6 @@ code.gitea.io/gitea/models/project
|
||||||
|
|
||||||
code.gitea.io/gitea/models/repo
|
code.gitea.io/gitea/models/repo
|
||||||
DeleteAttachmentsByIssue
|
DeleteAttachmentsByIssue
|
||||||
releaseSorter.Len
|
|
||||||
releaseSorter.Less
|
|
||||||
releaseSorter.Swap
|
|
||||||
SortReleases
|
|
||||||
FindReposMapByIDs
|
FindReposMapByIDs
|
||||||
IsErrTopicNotExist
|
IsErrTopicNotExist
|
||||||
ErrTopicNotExist.Error
|
ErrTopicNotExist.Error
|
||||||
|
@ -87,7 +82,6 @@ code.gitea.io/gitea/models/repo
|
||||||
WatchRepoMode
|
WatchRepoMode
|
||||||
|
|
||||||
code.gitea.io/gitea/models/user
|
code.gitea.io/gitea/models/user
|
||||||
IsErrPrimaryEmailCannotDelete
|
|
||||||
ErrUserInactive.Error
|
ErrUserInactive.Error
|
||||||
ErrUserInactive.Unwrap
|
ErrUserInactive.Unwrap
|
||||||
IsErrExternalLoginUserAlreadyExist
|
IsErrExternalLoginUserAlreadyExist
|
||||||
|
@ -99,6 +93,10 @@ code.gitea.io/gitea/models/user
|
||||||
GetUserEmailsByNames
|
GetUserEmailsByNames
|
||||||
GetUserNamesByIDs
|
GetUserNamesByIDs
|
||||||
|
|
||||||
|
code.gitea.io/gitea/modules/activitypub
|
||||||
|
NewContext
|
||||||
|
Context.APClientFactory
|
||||||
|
|
||||||
code.gitea.io/gitea/modules/assetfs
|
code.gitea.io/gitea/modules/assetfs
|
||||||
Bindata
|
Bindata
|
||||||
|
|
||||||
|
@ -139,9 +137,6 @@ code.gitea.io/gitea/modules/git
|
||||||
AddChangesWithArgs
|
AddChangesWithArgs
|
||||||
CommitChanges
|
CommitChanges
|
||||||
CommitChangesWithArgs
|
CommitChangesWithArgs
|
||||||
IsErrExecTimeout
|
|
||||||
ErrExecTimeout.Error
|
|
||||||
ErrUnsupportedVersion.Error
|
|
||||||
SetUpdateHook
|
SetUpdateHook
|
||||||
openRepositoryWithDefaultContext
|
openRepositoryWithDefaultContext
|
||||||
IsTagExist
|
IsTagExist
|
||||||
|
@ -165,6 +160,9 @@ code.gitea.io/gitea/modules/graceful
|
||||||
code.gitea.io/gitea/modules/hcaptcha
|
code.gitea.io/gitea/modules/hcaptcha
|
||||||
WithHTTP
|
WithHTTP
|
||||||
|
|
||||||
|
code.gitea.io/gitea/modules/hostmatcher
|
||||||
|
HostMatchList.AppendPattern
|
||||||
|
|
||||||
code.gitea.io/gitea/modules/json
|
code.gitea.io/gitea/modules/json
|
||||||
StdJSON.Marshal
|
StdJSON.Marshal
|
||||||
StdJSON.Unmarshal
|
StdJSON.Unmarshal
|
||||||
|
@ -249,6 +247,9 @@ code.gitea.io/gitea/modules/translation
|
||||||
MockLocale.TrSize
|
MockLocale.TrSize
|
||||||
MockLocale.PrettyNumber
|
MockLocale.PrettyNumber
|
||||||
|
|
||||||
|
code.gitea.io/gitea/modules/util
|
||||||
|
OptionalArg
|
||||||
|
|
||||||
code.gitea.io/gitea/modules/util/filebuffer
|
code.gitea.io/gitea/modules/util/filebuffer
|
||||||
CreateFromReader
|
CreateFromReader
|
||||||
|
|
||||||
|
@ -262,6 +263,11 @@ code.gitea.io/gitea/modules/web
|
||||||
code.gitea.io/gitea/modules/web/middleware
|
code.gitea.io/gitea/modules/web/middleware
|
||||||
DeleteLocaleCookie
|
DeleteLocaleCookie
|
||||||
|
|
||||||
|
code.gitea.io/gitea/modules/zstd
|
||||||
|
NewWriter
|
||||||
|
Writer.Write
|
||||||
|
Writer.Close
|
||||||
|
|
||||||
code.gitea.io/gitea/routers/web
|
code.gitea.io/gitea/routers/web
|
||||||
NotFound
|
NotFound
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "Gitea DevContainer",
|
"name": "Gitea DevContainer",
|
||||||
"image": "mcr.microsoft.com/devcontainers/go:1.22-bullseye",
|
"image": "mcr.microsoft.com/devcontainers/go:1.23-bullseye",
|
||||||
"features": {
|
"features": {
|
||||||
// installs nodejs into container
|
// installs nodejs into container
|
||||||
"ghcr.io/devcontainers/features/node:1": {
|
"ghcr.io/devcontainers/features/node:1": {
|
||||||
"version": "20"
|
"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-contrib/features/poetry:2": {},
|
||||||
"ghcr.io/devcontainers/features/python:1": {
|
"ghcr.io/devcontainers/features/python:1": {
|
||||||
"version": "3.12"
|
"version": "3.12"
|
||||||
|
|
1
.envrc.example
Normal file
1
.envrc.example
Normal file
|
@ -0,0 +1 @@
|
||||||
|
use flake
|
846
.eslintrc.yaml
846
.eslintrc.yaml
|
@ -1,846 +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-jquery
|
|
||||||
- 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]
|
|
||||||
jquery/no-ajax-events: [2]
|
|
||||||
jquery/no-ajax: [2]
|
|
||||||
jquery/no-animate: [2]
|
|
||||||
jquery/no-attr: [2]
|
|
||||||
jquery/no-bind: [2]
|
|
||||||
jquery/no-class: [0]
|
|
||||||
jquery/no-clone: [2]
|
|
||||||
jquery/no-closest: [0]
|
|
||||||
jquery/no-css: [2]
|
|
||||||
jquery/no-data: [0]
|
|
||||||
jquery/no-deferred: [2]
|
|
||||||
jquery/no-delegate: [2]
|
|
||||||
jquery/no-each: [0]
|
|
||||||
jquery/no-extend: [2]
|
|
||||||
jquery/no-fade: [2]
|
|
||||||
jquery/no-filter: [0]
|
|
||||||
jquery/no-find: [0]
|
|
||||||
jquery/no-global-eval: [2]
|
|
||||||
jquery/no-grep: [2]
|
|
||||||
jquery/no-has: [2]
|
|
||||||
jquery/no-hide: [2]
|
|
||||||
jquery/no-html: [0]
|
|
||||||
jquery/no-in-array: [2]
|
|
||||||
jquery/no-is-array: [2]
|
|
||||||
jquery/no-is-function: [2]
|
|
||||||
jquery/no-is: [2]
|
|
||||||
jquery/no-load: [2]
|
|
||||||
jquery/no-map: [2]
|
|
||||||
jquery/no-merge: [2]
|
|
||||||
jquery/no-param: [2]
|
|
||||||
jquery/no-parent: [0]
|
|
||||||
jquery/no-parents: [2]
|
|
||||||
jquery/no-parse-html: [2]
|
|
||||||
jquery/no-prop: [2]
|
|
||||||
jquery/no-proxy: [2]
|
|
||||||
jquery/no-ready: [2]
|
|
||||||
jquery/no-serialize: [2]
|
|
||||||
jquery/no-show: [2]
|
|
||||||
jquery/no-size: [2]
|
|
||||||
jquery/no-sizzle: [0]
|
|
||||||
jquery/no-slide: [2]
|
|
||||||
jquery/no-submit: [2]
|
|
||||||
jquery/no-text: [0]
|
|
||||||
jquery/no-toggle: [2]
|
|
||||||
jquery/no-trigger: [0]
|
|
||||||
jquery/no-trim: [2]
|
|
||||||
jquery/no-val: [0]
|
|
||||||
jquery/no-when: [2]
|
|
||||||
jquery/no-wrap: [2]
|
|
||||||
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: [0]
|
|
||||||
no-jquery/no-class: [0]
|
|
||||||
no-jquery/no-clone: [2]
|
|
||||||
no-jquery/no-closest: [0]
|
|
||||||
no-jquery/no-constructor-attributes: [2]
|
|
||||||
no-jquery/no-contains: [2]
|
|
||||||
no-jquery/no-context-prop: [2]
|
|
||||||
no-jquery/no-css: [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: [0]
|
|
||||||
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-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-remove-event-listener: [2]
|
|
||||||
unicorn/no-keyword-prefix: [0]
|
|
||||||
unicorn/no-lonely-if: [2]
|
|
||||||
unicorn/no-negated-condition: [0]
|
|
||||||
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-replace-all: [0]
|
|
||||||
unicorn/prefer-string-slice: [0]
|
|
||||||
unicorn/prefer-string-starts-ends-with: [2]
|
|
||||||
unicorn/prefer-string-trim-start-end: [2]
|
|
||||||
unicorn/prefer-switch: [0]
|
|
||||||
unicorn/prefer-ternary: [0]
|
|
||||||
unicorn/prefer-text-content: [2]
|
|
||||||
unicorn/prefer-top-level-await: [0]
|
|
||||||
unicorn/prefer-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]
|
|
|
@ -18,6 +18,7 @@ if ! test -f forgejo/sources/$minor_version ; then
|
||||||
false
|
false
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
echo -n $minor_version >forgejo/build-from-sources
|
||||||
date >last-upgrade
|
date >last-upgrade
|
||||||
|
|
||||||
if test -f "$forgejo_pr_or_ref"; then
|
if test -f "$forgejo_pr_or_ref"; then
|
||||||
|
|
|
@ -15,8 +15,8 @@ if ! test -f $organizations ; then
|
||||||
false
|
false
|
||||||
fi
|
fi
|
||||||
#
|
#
|
||||||
# do not include forgejo-experimental so that 7.0-test is found
|
# Inverse the order of lookup because the goal in the release built
|
||||||
# in forgejo-integration where it was just built instead of
|
# pipeline is to test the latest build, if available, instead of the
|
||||||
# forgejo-experimental which was published by the previous build
|
# stable version by the same version.
|
||||||
#
|
#
|
||||||
echo forgejo forgejo-integration > $organizations
|
echo forgejo-integration forgejo-experimental forgejo >$organizations
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
contact_links:
|
contact_links:
|
||||||
- name: 🔓 Security Reports
|
- name: 🔓 Security Reports
|
||||||
url: mailto:security@forgejo.org
|
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
|
- name: 💬 Matrix Chat Room
|
||||||
url: https://matrix.to/#/#forgejo-chat:matrix.org
|
url: https://matrix.to/#/#forgejo-chat:matrix.org
|
||||||
about: Please ask questions and discuss configuration or deployment problems here.
|
about: Please ask questions and discuss configuration or deployment problems here.
|
33
.forgejo/pull_request_template.md
Normal file
33
.forgejo/pull_request_template.md
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
name: "Pull Request Template"
|
||||||
|
about: "Template for all Pull Requests"
|
||||||
|
labels:
|
||||||
|
|
||||||
|
- test/needed
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Checklist
|
||||||
|
|
||||||
|
The [contributor guide](https://forgejo.org/docs/next/contributor/) contains information that will be helpful to first time contributors. There also are a few [conditions for merging Pull Requests in Forgejo repositories](https://codeberg.org/forgejo/governance/src/branch/main/PullRequestsAgreement.md). You are also welcome to join the [Forgejo development chatroom](https://matrix.to/#/#forgejo-development:matrix.org).
|
||||||
|
|
||||||
|
### Tests
|
||||||
|
|
||||||
|
- I added test coverage for Go changes...
|
||||||
|
- [ ] in their respective `*_test.go` for unit tests.
|
||||||
|
- [ ] in the `tests/integration` directory if it involves interactions with a live Forgejo server.
|
||||||
|
- I added test coverage for JavaScript changes...
|
||||||
|
- [ ] in `web_src/js/*.test.js` if it can be unit tested.
|
||||||
|
- [ ] in `tests/e2e/*.test.e2e.js` if it requires interactions with a live Forgejo server (see also the [developer guide for JavaScript testing](https://codeberg.org/forgejo/forgejo/src/branch/forgejo/tests/e2e/README.md#end-to-end-tests)).
|
||||||
|
|
||||||
|
### Documentation
|
||||||
|
|
||||||
|
- [ ] I created a pull request [to the documentation](https://codeberg.org/forgejo/docs) to explain to Forgejo users how to use this change.
|
||||||
|
- [ ] I did not document these changes and I do not expect someone else to do it.
|
||||||
|
|
||||||
|
### Release notes
|
||||||
|
|
||||||
|
- [ ] I do not want this change to show in the release notes.
|
||||||
|
- [ ] I want the title to show in the release notes with a link to this pull request.
|
||||||
|
- [ ] I want the content of the `release-notes/<pull request number>.md` to be be used for the release notes instead of the title.
|
3
.forgejo/testdata/build-release/go.mod
vendored
Normal file
3
.forgejo/testdata/build-release/go.mod
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
module code.gitea.io/gitea
|
||||||
|
|
||||||
|
go 1.23.3
|
29
.forgejo/workflows-composite/apt-install-from/action.yaml
Normal file
29
.forgejo/workflows-composite/apt-install-from/action.yaml
Normal 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}}
|
15
.forgejo/workflows-composite/build-backend/action.yaml
Normal file
15
.forgejo/workflows-composite/build-backend/action.yaml
Normal 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
|
12
.forgejo/workflows-composite/setup-env/action.yaml
Normal file
12
.forgejo/workflows-composite/setup-env/action.yaml
Normal 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
|
|
@ -1,57 +0,0 @@
|
||||||
# Copyright 2024 The Forgejo Authors
|
|
||||||
# SPDX-License-Identifier: MIT
|
|
||||||
#
|
|
||||||
# To modify this workflow:
|
|
||||||
#
|
|
||||||
# - change pull_request_target: to pull_request:
|
|
||||||
# so that it runs from a pull request instead of the default branch
|
|
||||||
#
|
|
||||||
# - push it to the wip-ci-backport branch on the forgejo repository
|
|
||||||
# otherwise it will not have access to the secrets required to push
|
|
||||||
# the PR
|
|
||||||
#
|
|
||||||
# - open a pull request targetting wip-ci-backport that includes a change
|
|
||||||
# that can be backported without conflict in v1.21 and set the
|
|
||||||
# `backport/v1.21` label.
|
|
||||||
#
|
|
||||||
# - 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 a
|
|
||||||
# `backport/v1.21` label on a merged pull request that can be backported
|
|
||||||
# without conflict.
|
|
||||||
#
|
|
||||||
on:
|
|
||||||
pull_request_target:
|
|
||||||
types:
|
|
||||||
- closed
|
|
||||||
- labeled
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
backporting:
|
|
||||||
if: >
|
|
||||||
!startsWith(vars.ROLE, 'forgejo-') && (
|
|
||||||
github.event.pull_request.merged
|
|
||||||
&&
|
|
||||||
contains(toJSON(github.event.pull_request.labels), 'backport/v')
|
|
||||||
)
|
|
||||||
runs-on: docker
|
|
||||||
container:
|
|
||||||
image: 'docker.io/node:20-bookworm'
|
|
||||||
steps:
|
|
||||||
- name: event info
|
|
||||||
run: |
|
|
||||||
cat <<'EOF'
|
|
||||||
${{ toJSON(github) }}
|
|
||||||
EOF
|
|
||||||
- uses: https://code.forgejo.org/actions/git-backporting@v4.8.0
|
|
||||||
with:
|
|
||||||
target-branch-pattern: "^backport/(?<target>(v.*))$"
|
|
||||||
strategy: ort
|
|
||||||
strategy-option: find-renames
|
|
||||||
cherry-pick-options: -x
|
|
||||||
auth: ${{ secrets.BACKPORT_TOKEN }}
|
|
||||||
pull-request: ${{ github.event.pull_request.url }}
|
|
||||||
auto-no-squash: true
|
|
||||||
enable-err-notification: true
|
|
|
@ -22,10 +22,10 @@ on:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
release-simulation:
|
release-simulation:
|
||||||
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
if: vars.ROLE == 'forgejo-coding'
|
||||||
runs-on: self-hosted
|
runs-on: self-hosted
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- id: forgejo
|
- id: forgejo
|
||||||
uses: https://code.forgejo.org/actions/setup-forgejo@v1
|
uses: https://code.forgejo.org/actions/setup-forgejo@v1
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#
|
#
|
||||||
# See also https://forgejo.org/docs/next/developer/RELEASE/#release-process
|
# See also https://forgejo.org/docs/next/contributor/release/#stable-release-process
|
||||||
#
|
#
|
||||||
# https://codeberg.org/forgejo-integration/forgejo
|
# https://codeberg.org/forgejo-integration/forgejo
|
||||||
#
|
#
|
||||||
|
@ -27,7 +27,7 @@ jobs:
|
||||||
# root is used for testing, allow it
|
# root is used for testing, allow it
|
||||||
if: vars.ROLE == 'forgejo-integration' || github.repository_owner == 'root'
|
if: vars.ROLE == 'forgejo-integration' || github.repository_owner == 'root'
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
|
@ -37,14 +37,13 @@ jobs:
|
||||||
repository="${{ github.repository }}"
|
repository="${{ github.repository }}"
|
||||||
echo "value=${repository##*/}" >> "$GITHUB_OUTPUT"
|
echo "value=${repository##*/}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
- uses: https://code.forgejo.org/actions/setup-node@v3
|
- uses: https://code.forgejo.org/actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
|
|
||||||
- uses: https://code.forgejo.org/actions/setup-go@v4
|
- uses: https://code.forgejo.org/actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: "1.22"
|
go-version-file: "go.mod"
|
||||||
check-latest: true
|
|
||||||
|
|
||||||
- name: version from ref
|
- name: version from ref
|
||||||
id: release-info
|
id: release-info
|
||||||
|
@ -88,7 +87,7 @@ jobs:
|
||||||
|
|
||||||
- name: cache node_modules
|
- name: cache node_modules
|
||||||
id: node
|
id: node
|
||||||
uses: https://code.forgejo.org/actions/cache@v3
|
uses: https://code.forgejo.org/actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
node_modules
|
node_modules
|
||||||
|
@ -195,7 +194,7 @@ jobs:
|
||||||
verbose: ${{ vars.VERBOSE || secrets.VERBOSE || 'false' }}
|
verbose: ${{ vars.VERBOSE || secrets.VERBOSE || 'false' }}
|
||||||
|
|
||||||
- name: end-to-end tests
|
- 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
|
uses: https://code.forgejo.org/actions/cascading-pr@v2
|
||||||
with:
|
with:
|
||||||
origin-url: ${{ env.GITHUB_SERVER_URL }}
|
origin-url: ${{ env.GITHUB_SERVER_URL }}
|
||||||
|
|
|
@ -1,74 +0,0 @@
|
||||||
# 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
|
|
||||||
#
|
|
||||||
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: 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:
|
|
||||||
if: >
|
|
||||||
!startsWith(vars.ROLE, 'forgejo-') && (
|
|
||||||
github.event_name == 'push' ||
|
|
||||||
(
|
|
||||||
github.event.action == 'label_updated' && contains(github.event.pull_request.labels.*.name, 'run-end-to-end-tests')
|
|
||||||
)
|
|
||||||
)
|
|
||||||
runs-on: docker
|
|
||||||
container:
|
|
||||||
image: node:20-bookworm
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: '0'
|
|
||||||
show-progress: 'false'
|
|
||||||
- uses: actions/cascading-pr@v2
|
|
||||||
with:
|
|
||||||
origin-url: ${{ env.GITHUB_SERVER_URL }}
|
|
||||||
origin-repo: ${{ github.repository }}
|
|
||||||
origin-token: ${{ secrets.END_TO_END_CASCADING_PR_ORIGIN }}
|
|
||||||
origin-pr: ${{ github.event.pull_request.number }}
|
|
||||||
origin-ref: ${{ github.event_name == 'push' && github.event.ref || '' }}
|
|
||||||
destination-url: https://code.forgejo.org
|
|
||||||
destination-fork-repo: cascading-pr/end-to-end
|
|
||||||
destination-repo: forgejo/end-to-end
|
|
||||||
destination-branch: main
|
|
||||||
destination-token: ${{ secrets.END_TO_END_CASCADING_PR_DESTINATION }}
|
|
||||||
close-merge: true
|
|
||||||
update: .forgejo/cascading-pr-end-to-end
|
|
|
@ -1,39 +0,0 @@
|
||||||
name: e2e
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- Makefile
|
|
||||||
- playwright.config.js
|
|
||||||
- .forgejo/workflows/e2e.yml
|
|
||||||
- tests/e2e/**
|
|
||||||
- web_src/js/**
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
test-e2e:
|
|
||||||
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
|
||||||
runs-on: docker
|
|
||||||
container:
|
|
||||||
image: 'docker.io/node:20-bookworm'
|
|
||||||
steps:
|
|
||||||
- uses: https://code.forgejo.org/actions/checkout@v4
|
|
||||||
- uses: https://code.forgejo.org/actions/setup-go@v4
|
|
||||||
with:
|
|
||||||
go-version: "1.22"
|
|
||||||
check-latest: true
|
|
||||||
- run: |
|
|
||||||
apt-get -qq update
|
|
||||||
apt-get -qq install -q sudo
|
|
||||||
sed -i -e 's/%sudo.*/%sudo ALL=(ALL:ALL) NOPASSWD:ALL/' /etc/sudoers
|
|
||||||
git config --add safe.directory '*'
|
|
||||||
adduser --quiet --comment forgejo --disabled-password forgejo
|
|
||||||
adduser forgejo sudo
|
|
||||||
chown -R forgejo:forgejo .
|
|
||||||
- run: |
|
|
||||||
su forgejo -c 'make deps-frontend frontend deps-backend'
|
|
||||||
- run: |
|
|
||||||
su forgejo -c 'make generate test-e2e-sqlite'
|
|
||||||
timeout-minutes: 40
|
|
||||||
env:
|
|
||||||
DEPS_PLAYWRIGHT: 1
|
|
||||||
USE_REPO_TEST_DIR: 1
|
|
39
.forgejo/workflows/forgejo-integration-cleanup.yml
Normal file
39
.forgejo/workflows/forgejo-integration-cleanup.yml
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
schedule:
|
||||||
|
- cron: '@daily'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
integration-cleanup:
|
||||||
|
if: vars.ROLE == 'forgejo-integration'
|
||||||
|
runs-on: docker
|
||||||
|
container:
|
||||||
|
image: 'code.forgejo.org/oci/node:20-bookworm'
|
||||||
|
steps:
|
||||||
|
|
||||||
|
- name: apt install curl jq
|
||||||
|
run: |
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
apt-get update -qq
|
||||||
|
apt-get -q install -qq -y curl jq
|
||||||
|
|
||||||
|
- name: remove old releases and tags
|
||||||
|
run: |
|
||||||
|
url=https://any:${{ secrets.TOKEN }}@codeberg.org
|
||||||
|
curl -sS "$url/api/v1/repos/forgejo-integration/forgejo/releases" | jq -r '.[] | "\(.published_at) \(.tag_name)"' | sort | while read published_at version ; do
|
||||||
|
if echo $version | grep -e '-test$' >/dev/null; then
|
||||||
|
old="18 months"
|
||||||
|
else
|
||||||
|
old="1 day"
|
||||||
|
fi
|
||||||
|
too_old=$(env -i date --date="- $old" +%F)
|
||||||
|
too_old_seconds=$(env -i date --date="- $old" +%s)
|
||||||
|
published_at_seconds=$(env -i date --date="$published_at" +%s)
|
||||||
|
if test $published_at_seconds -le $too_old_seconds ; then
|
||||||
|
echo "$version was published more than $old ago ($published_at <= $too_old) and will be removed"
|
||||||
|
curl -X DELETE -sS "$url/api/v1/repos/forgejo-integration/forgejo/releases/tags/$version"
|
||||||
|
else
|
||||||
|
echo "$version was published less than $old ago"
|
||||||
|
fi
|
||||||
|
done
|
205
.forgejo/workflows/issue-labels.yml
Normal file
205
.forgejo/workflows/issue-labels.yml
Normal file
|
@ -0,0 +1,205 @@
|
||||||
|
# Copyright 2024 The Forgejo Authors
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
#
|
||||||
|
# To modify the pull_request_target jobs:
|
||||||
|
#
|
||||||
|
# - push it to the wip-ci-issue-labels branch on the forgejo repository
|
||||||
|
# otherwise it will not have access to the required secrets.
|
||||||
|
#
|
||||||
|
# - 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 changing the labels
|
||||||
|
# to trigger the job.
|
||||||
|
#
|
||||||
|
name: issue-labels
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- 'wip-ci-issue-labels'
|
||||||
|
|
||||||
|
pull_request_target:
|
||||||
|
types:
|
||||||
|
- closed
|
||||||
|
- edited
|
||||||
|
- labeled
|
||||||
|
- synchronize
|
||||||
|
|
||||||
|
pull_request:
|
||||||
|
types:
|
||||||
|
- edited
|
||||||
|
- labeled
|
||||||
|
- opened
|
||||||
|
- synchronize
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
info:
|
||||||
|
if: vars.ROLE == 'forgejo-coding'
|
||||||
|
runs-on: docker
|
||||||
|
container:
|
||||||
|
image: code.forgejo.org/oci/node:20-bookworm
|
||||||
|
steps:
|
||||||
|
- name: Debug info
|
||||||
|
run: |
|
||||||
|
cat <<'EOF'
|
||||||
|
${{ toJSON(github) }}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
end-to-end:
|
||||||
|
if: >
|
||||||
|
vars.ROLE == 'forgejo-coding' &&
|
||||||
|
|
||||||
|
secrets.END_TO_END_CASCADING_PR_DESTINATION != '' &&
|
||||||
|
secrets.END_TO_END_CASCADING_PR_ORIGIN != '' &&
|
||||||
|
|
||||||
|
(
|
||||||
|
github.event_name == 'push' ||
|
||||||
|
(
|
||||||
|
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'
|
||||||
|
show-progress: 'false'
|
||||||
|
- uses: actions/cascading-pr@v2
|
||||||
|
with:
|
||||||
|
origin-url: ${{ env.GITHUB_SERVER_URL }}
|
||||||
|
origin-repo: ${{ github.repository }}
|
||||||
|
origin-token: ${{ secrets.END_TO_END_CASCADING_PR_ORIGIN }}
|
||||||
|
origin-pr: ${{ github.event.pull_request.number }}
|
||||||
|
origin-ref: ${{ github.event_name == 'push' && github.event.ref || '' }}
|
||||||
|
destination-url: https://code.forgejo.org
|
||||||
|
destination-fork-repo: cascading-pr/end-to-end
|
||||||
|
destination-repo: forgejo/end-to-end
|
||||||
|
destination-branch: main
|
||||||
|
destination-token: ${{ secrets.END_TO_END_CASCADING_PR_DESTINATION }}
|
||||||
|
close-merge: true
|
||||||
|
update: .forgejo/cascading-pr-end-to-end
|
||||||
|
|
||||||
|
backporting:
|
||||||
|
if: >
|
||||||
|
vars.ROLE == 'forgejo-coding' &&
|
||||||
|
|
||||||
|
secrets.BACKPORT_TOKEN != '' &&
|
||||||
|
|
||||||
|
github.event_name == 'pull_request_target' &&
|
||||||
|
(
|
||||||
|
github.event.pull_request.merged &&
|
||||||
|
contains(toJSON(github.event.pull_request.labels), 'backport/v')
|
||||||
|
)
|
||||||
|
runs-on: docker
|
||||||
|
container:
|
||||||
|
image: 'code.forgejo.org/oci/node:20-bookworm'
|
||||||
|
steps:
|
||||||
|
- name: Debug info
|
||||||
|
run: |
|
||||||
|
cat <<'EOF'
|
||||||
|
${{ toJSON(github) }}
|
||||||
|
EOF
|
||||||
|
- uses: https://code.forgejo.org/actions/git-backporting@v4.8.4
|
||||||
|
with:
|
||||||
|
target-branch-pattern: "^backport/(?<target>(v.*))$"
|
||||||
|
strategy: ort
|
||||||
|
strategy-option: find-renames
|
||||||
|
cherry-pick-options: -x
|
||||||
|
auth: ${{ secrets.BACKPORT_TOKEN }}
|
||||||
|
pull-request: ${{ github.event.pull_request.url }}
|
||||||
|
auto-no-squash: true
|
||||||
|
enable-err-notification: true
|
||||||
|
git-user: forgejo-backport-action
|
||||||
|
git-email: forgejo-backport-action@noreply.codeberg.org
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
release-notes:
|
||||||
|
if: >
|
||||||
|
vars.ROLE == 'forgejo-coding' &&
|
||||||
|
|
||||||
|
secrets.RELEASE_NOTES_ASSISTANT_TOKEN != '' &&
|
||||||
|
|
||||||
|
github.event_name == 'pull_request_target' &&
|
||||||
|
contains(github.event.pull_request.labels.*.name, 'worth a release-note') &&
|
||||||
|
(
|
||||||
|
github.event.action == 'label_updated' ||
|
||||||
|
github.event.action == 'edited' ||
|
||||||
|
github.event.action == 'synchronized'
|
||||||
|
)
|
||||||
|
|
||||||
|
runs-on: docker
|
||||||
|
container:
|
||||||
|
image: 'code.forgejo.org/oci/node:20-bookworm'
|
||||||
|
steps:
|
||||||
|
- name: Debug info
|
||||||
|
run: |
|
||||||
|
cat <<'EOF'
|
||||||
|
${{ toJSON(github) }}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
- uses: https://code.forgejo.org/actions/checkout@v4
|
||||||
|
|
||||||
|
- uses: https://code.forgejo.org/actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version-file: "go.mod"
|
||||||
|
cache: false
|
||||||
|
|
||||||
|
- name: apt install jq
|
||||||
|
run: |
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
apt-get update -qq
|
||||||
|
apt-get -q install -y -qq jq
|
||||||
|
|
||||||
|
- name: release-notes-assistant preview
|
||||||
|
run: |
|
||||||
|
go run code.forgejo.org/forgejo/release-notes-assistant@v1.1.1 --config .release-notes-assistant.yaml --storage pr --storage-location ${{ github.event.pull_request.number }} --forgejo-url $GITHUB_SERVER_URL --repository $GITHUB_REPOSITORY --token ${{ secrets.RELEASE_NOTES_ASSISTANT_TOKEN }} preview ${{ github.event.pull_request.number }}
|
|
@ -1,6 +1,8 @@
|
||||||
name: mirror
|
name: mirror
|
||||||
|
|
||||||
on:
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '@daily'
|
- cron: '@daily'
|
||||||
|
|
||||||
|
@ -9,7 +11,7 @@ jobs:
|
||||||
if: ${{ secrets.MIRROR_TOKEN != '' }}
|
if: ${{ secrets.MIRROR_TOKEN != '' }}
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
container:
|
container:
|
||||||
image: 'docker.io/node:20-bookworm'
|
image: 'code.forgejo.org/oci/node:20-bookworm'
|
||||||
steps:
|
steps:
|
||||||
- name: git push {v*/,}forgejo
|
- name: git push {v*/,}forgejo
|
||||||
run: |
|
run: |
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# SPDX-License-Identifier: MIT
|
# SPDX-License-Identifier: MIT
|
||||||
#
|
#
|
||||||
# See also https://forgejo.org/docs/next/developer/RELEASE/#release-process
|
# See also https://forgejo.org/docs/next/contributor/release/#stable-release-process
|
||||||
#
|
#
|
||||||
# https://codeberg.org/forgejo-experimental/forgejo
|
# https://codeberg.org/forgejo-experimental/forgejo
|
||||||
#
|
#
|
||||||
|
@ -39,7 +39,7 @@ jobs:
|
||||||
runs-on: self-hosted
|
runs-on: self-hosted
|
||||||
if: vars.DOER != '' && vars.FORGEJO != '' && vars.TO_OWNER != '' && vars.FROM_OWNER != '' && secrets.TOKEN != ''
|
if: vars.DOER != '' && vars.FORGEJO != '' && vars.TO_OWNER != '' && vars.FROM_OWNER != '' && secrets.TOKEN != ''
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: copy & sign
|
- name: copy & sign
|
||||||
uses: https://code.forgejo.org/forgejo/forgejo-build-publish/publish@v5
|
uses: https://code.forgejo.org/forgejo/forgejo-build-publish/publish@v5
|
||||||
|
@ -59,23 +59,37 @@ jobs:
|
||||||
gpg-passphrase: ${{ secrets.GPG_PASSPHRASE }}
|
gpg-passphrase: ${{ secrets.GPG_PASSPHRASE }}
|
||||||
verbose: ${{ vars.VERBOSE }}
|
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
|
- name: upgrade v*.next.forgejo.org
|
||||||
run: |
|
uses: https://code.forgejo.org/infrastructure/next-digest@v1.1.0
|
||||||
export DEBIAN_FRONTEND=noninteractive
|
with:
|
||||||
apt-get update -qq
|
url: https://placeholder:${{ secrets.TOKEN_NEXT_DIGEST }}@code.forgejo.org/infrastructure/next-digest
|
||||||
apt-get -q install -y -qq curl
|
ref_name: '${{ github.ref_name }}'
|
||||||
version="${{ github.ref_name }}"
|
image: 'codeberg.org/forgejo-experimental/forgejo'
|
||||||
version=${version##*v}
|
tag_suffix: '-rootless'
|
||||||
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
|
|
||||||
|
|
||||||
- name: set up go for the DNS update below
|
- name: set up go for the DNS update below
|
||||||
if: vars.ROLE == 'forgejo-experimental' && secrets.OVH_APP_KEY != ''
|
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:
|
with:
|
||||||
go-version: "1.22"
|
go-version-file: "go.mod"
|
||||||
check-latest: true
|
|
||||||
- name: update the _release.experimental DNS record
|
- name: update the _release.experimental DNS record
|
||||||
if: vars.ROLE == 'forgejo-experimental' && secrets.OVH_APP_KEY != ''
|
if: vars.ROLE == 'forgejo-experimental' && secrets.OVH_APP_KEY != ''
|
||||||
uses: https://code.forgejo.org/actions/ovh-dns-update@v1
|
uses: https://code.forgejo.org/actions/ovh-dns-update@v1
|
||||||
|
|
33
.forgejo/workflows/release-notes-assistant-milestones.yml
Normal file
33
.forgejo/workflows/release-notes-assistant-milestones.yml
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
schedule:
|
||||||
|
- cron: '@daily'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
release-notes:
|
||||||
|
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@v4
|
||||||
|
|
||||||
|
- uses: https://code.forgejo.org/actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version-file: "go.mod"
|
||||||
|
cache: false
|
||||||
|
|
||||||
|
- name: apt install jq
|
||||||
|
run: |
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
apt-get update -qq
|
||||||
|
apt-get -q install -y -qq jq
|
||||||
|
|
||||||
|
- name: update open milestones
|
||||||
|
run: |
|
||||||
|
set -x
|
||||||
|
curl -sS $GITHUB_SERVER_URL/api/v1/repos/$GITHUB_REPOSITORY/milestones?state=open | jq -r '.[] | .title' | while read forgejo version ; do
|
||||||
|
milestone="$forgejo $version"
|
||||||
|
go run code.forgejo.org/forgejo/release-notes-assistant@v1.1.1 --config .release-notes-assistant.yaml --storage milestone --storage-location "$milestone" --forgejo-url $GITHUB_SERVER_URL --repository $GITHUB_REPOSITORY --token ${{ secrets.RELEASE_NOTES_ASSISTANT_TOKEN }} release $version
|
||||||
|
done
|
|
@ -8,9 +8,12 @@ name: renovate
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- 'renovate/**' # self-test updates
|
- renovate/** # self-test updates
|
||||||
|
paths:
|
||||||
|
- .forgejo/workflows/renovate.yml
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '0 0/2 * * *'
|
- cron: '0 0/2 * * *'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
env:
|
env:
|
||||||
RENOVATE_DRY_RUN: ${{ (github.event_name != 'schedule' && github.ref_name != github.event.repository.default_branch) && 'full' || '' }}
|
RENOVATE_DRY_RUN: ${{ (github.event_name != 'schedule' && github.ref_name != github.event.repository.default_branch) && 'full' || '' }}
|
||||||
|
@ -18,15 +21,15 @@ env:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
renovate:
|
renovate:
|
||||||
if: ${{ secrets.RENOVATE_TOKEN != '' }}
|
if: vars.ROLE == 'forgejo-coding' && secrets.RENOVATE_TOKEN != ''
|
||||||
|
|
||||||
runs-on: docker
|
runs-on: docker-runner-one
|
||||||
container:
|
container:
|
||||||
image: ghcr.io/visualon/renovate:37.431.4
|
image: code.forgejo.org/forgejo-contrib/renovate:39.19.1
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Load renovate repo cache
|
- 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:
|
with:
|
||||||
path: |
|
path: |
|
||||||
.tmp/cache/renovate/repository
|
.tmp/cache/renovate/repository
|
||||||
|
@ -59,7 +62,7 @@ jobs:
|
||||||
|
|
||||||
- name: Save renovate repo cache
|
- name: Save renovate repo cache
|
||||||
if: always() && env.RENOVATE_DRY_RUN != 'full'
|
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:
|
with:
|
||||||
path: |
|
path: |
|
||||||
.tmp/cache/renovate/repository
|
.tmp/cache/renovate/repository
|
||||||
|
|
|
@ -6,280 +6,262 @@ on:
|
||||||
branches:
|
branches:
|
||||||
- 'forgejo*'
|
- 'forgejo*'
|
||||||
- 'v*/forgejo*'
|
- 'v*/forgejo*'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
backend-checks:
|
backend-checks:
|
||||||
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
if: vars.ROLE == 'forgejo-coding' || vars.ROLE == 'forgejo-testing'
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
container:
|
container:
|
||||||
image: 'docker.io/node:20-bookworm'
|
image: 'code.forgejo.org/oci/node:20-bookworm'
|
||||||
steps:
|
steps:
|
||||||
- name: event info
|
- name: event info
|
||||||
run: |
|
run: |
|
||||||
cat <<'EOF'
|
cat <<'EOF'
|
||||||
${{ toJSON(github) }}
|
${{ toJSON(github) }}
|
||||||
EOF
|
EOF
|
||||||
- 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: ./.forgejo/workflows-composite/setup-env
|
||||||
with:
|
- run: su forgejo -c 'make deps-backend deps-tools'
|
||||||
go-version: "1.22"
|
- 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
|
||||||
check-latest: true
|
- uses: ./.forgejo/workflows-composite/build-backend
|
||||||
- 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
|
|
||||||
frontend-checks:
|
frontend-checks:
|
||||||
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
if: vars.ROLE == 'forgejo-coding' || vars.ROLE == 'forgejo-testing'
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
container:
|
container:
|
||||||
image: 'docker.io/node:20-bookworm'
|
image: 'code.forgejo.org/oci/node:20-bookworm'
|
||||||
steps:
|
steps:
|
||||||
- uses: https://code.forgejo.org/actions/checkout@v3
|
- uses: https://code.forgejo.org/actions/checkout@v4
|
||||||
- run: make deps-frontend
|
- run: make deps-frontend
|
||||||
- run: make lint-frontend
|
- run: make lint-frontend
|
||||||
- run: make checks-frontend
|
- run: make checks-frontend
|
||||||
- run: make test-frontend-coverage
|
- run: make test-frontend-coverage
|
||||||
- run: make frontend
|
- 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:
|
test-unit:
|
||||||
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
if: vars.ROLE == 'forgejo-coding' || vars.ROLE == 'forgejo-testing'
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
needs: [backend-checks, frontend-checks]
|
needs: [backend-checks, frontend-checks]
|
||||||
container:
|
container:
|
||||||
image: 'docker.io/node:20-bookworm'
|
image: 'code.forgejo.org/oci/node:20-bookworm'
|
||||||
services:
|
services:
|
||||||
elasticsearch:
|
elasticsearch:
|
||||||
image: elasticsearch:7.17.22
|
image: code.forgejo.org/oci/bitnami/elasticsearch:7
|
||||||
|
options: --tmpfs /bitnami/elasticsearch/data
|
||||||
env:
|
env:
|
||||||
discovery.type: single-node
|
discovery.type: single-node
|
||||||
ES_JAVA_OPTS: "-Xms512m -Xmx512m"
|
ES_JAVA_OPTS: "-Xms512m -Xmx512m"
|
||||||
minio:
|
minio:
|
||||||
image: bitnami/minio:2024.3.30
|
image: code.forgejo.org/oci/bitnami/minio:2024.8.17
|
||||||
options: >-
|
options: >-
|
||||||
--hostname gitea.minio
|
--hostname gitea.minio --tmpfs /bitnami/minio/data
|
||||||
env:
|
env:
|
||||||
MINIO_DOMAIN: minio
|
MINIO_DOMAIN: minio
|
||||||
MINIO_ROOT_USER: 123456
|
MINIO_ROOT_USER: 123456
|
||||||
MINIO_ROOT_PASSWORD: 12345678
|
MINIO_ROOT_PASSWORD: 12345678
|
||||||
steps:
|
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: ./.forgejo/workflows-composite/setup-env
|
||||||
with:
|
|
||||||
go-version: "1.22"
|
|
||||||
- run: |
|
|
||||||
git config --add safe.directory '*'
|
|
||||||
adduser --quiet --comment forgejo --disabled-password forgejo
|
|
||||||
chown -R forgejo:forgejo .
|
|
||||||
- name: install git >= 2.42
|
- name: install git >= 2.42
|
||||||
|
uses: ./.forgejo/workflows-composite/apt-install-from
|
||||||
|
with:
|
||||||
|
packages: git
|
||||||
|
- name: test release-notes-assistant.sh
|
||||||
run: |
|
run: |
|
||||||
export DEBIAN_FRONTEND=noninteractive
|
apt-get -q install -qq -y jq
|
||||||
echo deb http://deb.debian.org/debian/ testing main > /etc/apt/sources.list.d/testing.list
|
./release-notes-assistant.sh test_main
|
||||||
apt-get update -qq
|
- uses: ./.forgejo/workflows-composite/build-backend
|
||||||
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'
|
|
||||||
- run: |
|
|
||||||
su forgejo -c 'make backend'
|
|
||||||
env:
|
|
||||||
TAGS: bindata
|
|
||||||
- run: |
|
- run: |
|
||||||
su forgejo -c 'make test-backend test-check'
|
su forgejo -c 'make test-backend test-check'
|
||||||
timeout-minutes: 50
|
timeout-minutes: 120
|
||||||
env:
|
env:
|
||||||
RACE_ENABLED: 'true'
|
RACE_ENABLED: 'true'
|
||||||
TAGS: bindata
|
TAGS: bindata
|
||||||
TEST_ELASTICSEARCH_URL: http://elasticsearch:9200
|
TEST_ELASTICSEARCH_URL: http://elasticsearch:9200
|
||||||
test-remote-cacher:
|
test-e2e:
|
||||||
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
if: vars.ROLE == 'forgejo-coding' || vars.ROLE == 'forgejo-testing'
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
needs: [backend-checks, frontend-checks]
|
needs: [backend-checks, frontend-checks]
|
||||||
container:
|
container:
|
||||||
image: 'docker.io/node:20-bookworm'
|
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:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
cacher:
|
cacher:
|
||||||
# redis
|
- name: redis
|
||||||
- image: redis:7.2
|
image: code.forgejo.org/oci/bitnami/redis:7.2
|
||||||
port: 6379
|
options: --tmpfs /bitnami/redis/data
|
||||||
# redict
|
- name: redict
|
||||||
- image: registry.redict.io/redict:7.3.0-scratch
|
image: registry.redict.io/redict:7.3.0-scratch
|
||||||
port: 6379
|
options: --tmpfs /data
|
||||||
# valkey
|
- name: valkey
|
||||||
- image: docker.io/valkey/valkey:7.2.5-alpine3.19
|
image: code.forgejo.org/oci/bitnami/valkey:7.2
|
||||||
port: 6379
|
options: --tmpfs /bitnami/redis/data
|
||||||
# garnet
|
- name: garnet
|
||||||
- image: ghcr.io/microsoft/garnet-alpine:1.0.14
|
image: ghcr.io/microsoft/garnet-alpine:1.0.14
|
||||||
port: 6379
|
options: --tmpfs /data
|
||||||
services:
|
services:
|
||||||
cacher:
|
cacher:
|
||||||
image: ${{ matrix.cacher.image }}
|
image: ${{ matrix.cacher.image }}
|
||||||
options: ${{ matrix.cacher.options }}
|
options: ${{ matrix.cacher.options }}
|
||||||
steps:
|
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: ./.forgejo/workflows-composite/setup-env
|
||||||
with:
|
|
||||||
go-version: "1.22"
|
|
||||||
- run: |
|
|
||||||
git config --add safe.directory '*'
|
|
||||||
adduser --quiet --comment forgejo --disabled-password forgejo
|
|
||||||
chown -R forgejo:forgejo .
|
|
||||||
- name: install git >= 2.42
|
- name: install git >= 2.42
|
||||||
run: |
|
uses: ./.forgejo/workflows-composite/apt-install-from
|
||||||
export DEBIAN_FRONTEND=noninteractive
|
with:
|
||||||
echo deb http://deb.debian.org/debian/ testing main > /etc/apt/sources.list.d/testing.list
|
packages: git
|
||||||
apt-get update -qq
|
- uses: ./.forgejo/workflows-composite/build-backend
|
||||||
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'
|
|
||||||
- run: |
|
|
||||||
su forgejo -c 'make backend'
|
|
||||||
env:
|
|
||||||
TAGS: bindata
|
|
||||||
- run: |
|
- run: |
|
||||||
su forgejo -c 'make test-remote-cacher test-check'
|
su forgejo -c 'make test-remote-cacher test-check'
|
||||||
timeout-minutes: 50
|
timeout-minutes: 120
|
||||||
env:
|
env:
|
||||||
RACE_ENABLED: 'true'
|
RACE_ENABLED: 'true'
|
||||||
TAGS: bindata
|
TAGS: bindata
|
||||||
TEST_REDIS_SERVER: cacher:${{ matrix.cacher.port }}
|
TEST_REDIS_SERVER: cacher:${{ matrix.cacher.port }}
|
||||||
test-mysql:
|
test-mysql:
|
||||||
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
if: vars.ROLE == 'forgejo-coding' || vars.ROLE == 'forgejo-testing'
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
needs: [backend-checks, frontend-checks]
|
needs: [backend-checks, frontend-checks]
|
||||||
container:
|
container:
|
||||||
image: 'docker.io/node:20-bookworm'
|
image: 'code.forgejo.org/oci/node:20-bookworm'
|
||||||
services:
|
services:
|
||||||
mysql:
|
mysql:
|
||||||
image: 'docker.io/mysql:8-debian'
|
image: 'code.forgejo.org/oci/bitnami/mysql:8.4'
|
||||||
env:
|
env:
|
||||||
MYSQL_ALLOW_EMPTY_PASSWORD: yes
|
ALLOW_EMPTY_PASSWORD: yes
|
||||||
MYSQL_DATABASE: testgitea
|
MYSQL_DATABASE: testgitea
|
||||||
#
|
#
|
||||||
# See also https://codeberg.org/forgejo/forgejo/issues/976
|
# See also https://codeberg.org/forgejo/forgejo/issues/976
|
||||||
#
|
#
|
||||||
cmd: ['mysqld', '--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:
|
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: ./.forgejo/workflows-composite/setup-env
|
||||||
with:
|
|
||||||
go-version: "1.22"
|
|
||||||
- name: install dependencies & git >= 2.42
|
- name: install dependencies & git >= 2.42
|
||||||
run: |
|
uses: ./.forgejo/workflows-composite/apt-install-from
|
||||||
export DEBIAN_FRONTEND=noninteractive
|
with:
|
||||||
echo deb http://deb.debian.org/debian/ testing main > /etc/apt/sources.list.d/testing.list
|
packages: git git-lfs
|
||||||
apt-get update -qq
|
- uses: ./.forgejo/workflows-composite/build-backend
|
||||||
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'
|
|
||||||
- run: |
|
|
||||||
su forgejo -c 'make backend'
|
|
||||||
env:
|
|
||||||
TAGS: bindata
|
|
||||||
- run: |
|
- run: |
|
||||||
su forgejo -c 'make test-mysql-migration test-mysql'
|
su forgejo -c 'make test-mysql-migration test-mysql'
|
||||||
timeout-minutes: 50
|
timeout-minutes: 120
|
||||||
env:
|
env:
|
||||||
TAGS: bindata
|
|
||||||
USE_REPO_TEST_DIR: 1
|
USE_REPO_TEST_DIR: 1
|
||||||
test-pgsql:
|
test-pgsql:
|
||||||
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
if: vars.ROLE == 'forgejo-coding' || vars.ROLE == 'forgejo-testing'
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
needs: [backend-checks, frontend-checks]
|
needs: [backend-checks, frontend-checks]
|
||||||
container:
|
container:
|
||||||
image: 'docker.io/node:20-bookworm'
|
image: 'code.forgejo.org/oci/node:20-bookworm'
|
||||||
services:
|
services:
|
||||||
minio:
|
minio:
|
||||||
image: bitnami/minio:2024.3.30
|
image: code.forgejo.org/oci/bitnami/minio:2024.8.17
|
||||||
env:
|
env:
|
||||||
MINIO_ROOT_USER: 123456
|
MINIO_ROOT_USER: 123456
|
||||||
MINIO_ROOT_PASSWORD: 12345678
|
MINIO_ROOT_PASSWORD: 12345678
|
||||||
|
options: --tmpfs /bitnami/minio/data
|
||||||
ldap:
|
ldap:
|
||||||
image: docker.io/gitea/test-openldap:latest
|
image: code.forgejo.org/oci/test-openldap:latest
|
||||||
pgsql:
|
pgsql:
|
||||||
image: 'docker.io/postgres:15'
|
image: code.forgejo.org/oci/bitnami/postgresql:15
|
||||||
env:
|
env:
|
||||||
POSTGRES_DB: test
|
POSTGRESQL_DATABASE: test
|
||||||
POSTGRES_PASSWORD: postgres
|
POSTGRESQL_PASSWORD: postgres
|
||||||
|
POSTGRESQL_FSYNC: off
|
||||||
|
POSTGRESQL_EXTRA_FLAGS: -c full_page_writes=off
|
||||||
|
options: --tmpfs /bitnami/postgresql
|
||||||
steps:
|
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: ./.forgejo/workflows-composite/setup-env
|
||||||
with:
|
|
||||||
go-version: "1.22"
|
|
||||||
- name: install dependencies & git >= 2.42
|
- name: install dependencies & git >= 2.42
|
||||||
run: |
|
uses: ./.forgejo/workflows-composite/apt-install-from
|
||||||
export DEBIAN_FRONTEND=noninteractive
|
with:
|
||||||
echo deb http://deb.debian.org/debian/ testing main > /etc/apt/sources.list.d/testing.list
|
packages: git git-lfs
|
||||||
apt-get update -qq
|
- uses: ./.forgejo/workflows-composite/build-backend
|
||||||
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'
|
|
||||||
- run: |
|
|
||||||
su forgejo -c 'make backend'
|
|
||||||
env:
|
|
||||||
TAGS: bindata
|
|
||||||
- run: |
|
- run: |
|
||||||
su forgejo -c 'make test-pgsql-migration test-pgsql'
|
su forgejo -c 'make test-pgsql-migration test-pgsql'
|
||||||
timeout-minutes: 50
|
timeout-minutes: 120
|
||||||
env:
|
env:
|
||||||
TAGS: bindata
|
|
||||||
RACE_ENABLED: true
|
RACE_ENABLED: true
|
||||||
USE_REPO_TEST_DIR: 1
|
USE_REPO_TEST_DIR: 1
|
||||||
TEST_LDAP: 1
|
TEST_LDAP: 1
|
||||||
test-sqlite:
|
test-sqlite:
|
||||||
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
if: vars.ROLE == 'forgejo-coding' || vars.ROLE == 'forgejo-testing'
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
needs: [backend-checks, frontend-checks]
|
needs: [backend-checks, frontend-checks]
|
||||||
container:
|
container:
|
||||||
image: 'docker.io/node:20-bookworm'
|
image: 'code.forgejo.org/oci/node:20-bookworm'
|
||||||
steps:
|
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: ./.forgejo/workflows-composite/setup-env
|
||||||
with:
|
|
||||||
go-version: "1.22"
|
|
||||||
- name: install dependencies & git >= 2.42
|
- name: install dependencies & git >= 2.42
|
||||||
run: |
|
uses: ./.forgejo/workflows-composite/apt-install-from
|
||||||
export DEBIAN_FRONTEND=noninteractive
|
with:
|
||||||
echo deb http://deb.debian.org/debian/ testing main > /etc/apt/sources.list.d/testing.list
|
packages: git git-lfs
|
||||||
apt-get update -qq
|
- uses: ./.forgejo/workflows-composite/build-backend
|
||||||
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'
|
|
||||||
- run: |
|
|
||||||
su forgejo -c 'make backend'
|
|
||||||
env:
|
|
||||||
TAGS: bindata sqlite sqlite_unlock_notify
|
|
||||||
- run: |
|
- run: |
|
||||||
su forgejo -c 'make test-sqlite-migration test-sqlite'
|
su forgejo -c 'make test-sqlite-migration test-sqlite'
|
||||||
timeout-minutes: 50
|
timeout-minutes: 120
|
||||||
env:
|
env:
|
||||||
TAGS: bindata sqlite sqlite_unlock_notify
|
TAGS: sqlite sqlite_unlock_notify
|
||||||
RACE_ENABLED: true
|
RACE_ENABLED: true
|
||||||
TEST_TAGS: sqlite sqlite_unlock_notify
|
TEST_TAGS: sqlite sqlite_unlock_notify
|
||||||
USE_REPO_TEST_DIR: 1
|
USE_REPO_TEST_DIR: 1
|
||||||
security-check:
|
security-check:
|
||||||
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
if: vars.ROLE == 'forgejo-coding' || vars.ROLE == 'forgejo-testing'
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
needs:
|
needs:
|
||||||
- test-sqlite
|
- test-sqlite
|
||||||
|
@ -288,12 +270,9 @@ jobs:
|
||||||
- test-remote-cacher
|
- test-remote-cacher
|
||||||
- test-unit
|
- test-unit
|
||||||
container:
|
container:
|
||||||
image: 'docker.io/node:20-bookworm'
|
image: 'code.forgejo.org/oci/node:20-bookworm'
|
||||||
steps:
|
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: ./.forgejo/workflows-composite/setup-env
|
||||||
with:
|
- run: su forgejo -c 'make deps-backend deps-tools'
|
||||||
go-version: "1.22"
|
- run: su forgejo -c 'make security-check'
|
||||||
check-latest: true
|
|
||||||
- run: make deps-backend deps-tools
|
|
||||||
- run: make security-check
|
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
---
|
|
||||||
|
|
||||||
name: "Pull Request Template"
|
|
||||||
about: "Template for all Pull Requests"
|
|
||||||
labels:
|
|
||||||
|
|
||||||
- test/needed
|
|
||||||
|
|
||||||
---
|
|
||||||
<!--
|
|
||||||
Before submitting a PR, please read the contributing guidelines:
|
|
||||||
https://codeberg.org/forgejo/forgejo/src/branch/forgejo/CONTRIBUTING.md
|
|
||||||
-->
|
|
6
.gitignore
vendored
6
.gitignore
vendored
|
@ -115,6 +115,12 @@ prime/
|
||||||
*_source.tar.bz2
|
*_source.tar.bz2
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
|
# Direnv configuration
|
||||||
|
/.envrc
|
||||||
|
|
||||||
|
# nix-direnv generated files
|
||||||
|
.direnv/
|
||||||
|
|
||||||
# Make evidence files
|
# Make evidence files
|
||||||
/.make_evidence
|
/.make_evidence
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ linters:
|
||||||
- staticcheck
|
- staticcheck
|
||||||
- stylecheck
|
- stylecheck
|
||||||
- tenv
|
- tenv
|
||||||
|
- testifylint
|
||||||
- typecheck
|
- typecheck
|
||||||
- unconvert
|
- unconvert
|
||||||
- unused
|
- unused
|
||||||
|
@ -28,10 +29,6 @@ linters:
|
||||||
|
|
||||||
run:
|
run:
|
||||||
timeout: 10m
|
timeout: 10m
|
||||||
skip-dirs:
|
|
||||||
- node_modules
|
|
||||||
- public
|
|
||||||
- web_src
|
|
||||||
|
|
||||||
output:
|
output:
|
||||||
sort-results: true
|
sort-results: true
|
||||||
|
@ -46,7 +43,6 @@ linters-settings:
|
||||||
gocritic:
|
gocritic:
|
||||||
disabled-checks:
|
disabled-checks:
|
||||||
- ifElseChain
|
- ifElseChain
|
||||||
- singleCaseSwitch # Every time this occurred in the code, there was no other way.
|
|
||||||
revive:
|
revive:
|
||||||
severity: error
|
severity: error
|
||||||
rules:
|
rules:
|
||||||
|
@ -81,6 +77,8 @@ linters-settings:
|
||||||
- name: unreachable-code
|
- name: unreachable-code
|
||||||
- name: var-declaration
|
- name: var-declaration
|
||||||
- name: var-naming
|
- name: var-naming
|
||||||
|
- name: redefines-builtin-id
|
||||||
|
disabled: true
|
||||||
gofumpt:
|
gofumpt:
|
||||||
extra-rules: true
|
extra-rules: true
|
||||||
depguard:
|
depguard:
|
||||||
|
@ -101,6 +99,9 @@ linters-settings:
|
||||||
desc: do not use the ini package, use gitea's config system instead
|
desc: do not use the ini package, use gitea's config system instead
|
||||||
- pkg: github.com/minio/sha256-simd
|
- pkg: github.com/minio/sha256-simd
|
||||||
desc: use crypto/sha256 instead, see https://codeberg.org/forgejo/forgejo/pulls/1528
|
desc: use crypto/sha256 instead, see https://codeberg.org/forgejo/forgejo/pulls/1528
|
||||||
|
testifylint:
|
||||||
|
disable:
|
||||||
|
- go-require
|
||||||
|
|
||||||
issues:
|
issues:
|
||||||
max-issues-per-linter: 0
|
max-issues-per-linter: 0
|
||||||
|
|
2
.mailmap
Normal file
2
.mailmap
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
Unknwon <u@gogs.io> <joe2010xtmf@163.com>
|
||||||
|
Unknwon <u@gogs.io> 无闻 <u@gogs.io>
|
27
.release-notes-assistant.yaml
Normal file
27
.release-notes-assistant.yaml
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
categorize: './release-notes-assistant.sh'
|
||||||
|
branch-development: 'forgejo'
|
||||||
|
branch-pattern: 'v*/forgejo'
|
||||||
|
branch-find-version: 'v(?P<version>\d+\.\d+)/forgejo'
|
||||||
|
branch-to-version: '${version}.0'
|
||||||
|
branch-from-version: 'v%[1]d.%[2]d/forgejo'
|
||||||
|
tag-from-version: 'v%[1]d.%[2]d.%[3]d'
|
||||||
|
branch-known:
|
||||||
|
- 'v7.0/forgejo'
|
||||||
|
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: |
|
||||||
|
|
||||||
|
## Release notes
|
||||||
|
comment: |
|
||||||
|
<details>
|
||||||
|
<summary>Where does that come from?</summary>
|
||||||
|
The following is a preview of the release notes for this pull request, as they will appear in the upcoming release. They are derived from the content of the `%[2]s/%[3]s.md` file, if it exists, or the title of the pull request. They were also added at the bottom of the description of this pull request for easier reference.
|
||||||
|
|
||||||
|
This message and the release notes originate from a call to the [release-notes-assistant](https://code.forgejo.org/forgejo/release-notes-assistant).
|
||||||
|
|
||||||
|
```diff
|
||||||
|
%[4]s
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
%[1]s
|
12
CODEOWNERS
12
CODEOWNERS
|
@ -6,9 +6,6 @@
|
||||||
|
|
||||||
# Please mind the alphabetic order of reviewers.
|
# Please mind the alphabetic order of reviewers.
|
||||||
|
|
||||||
# Files related to the CI of the Forgejo project.
|
|
||||||
.forgejo/.* @dachary @earl-warren
|
|
||||||
|
|
||||||
# Files related to frontend development.
|
# Files related to frontend development.
|
||||||
|
|
||||||
# Javascript and CSS code.
|
# Javascript and CSS code.
|
||||||
|
@ -19,19 +16,22 @@ templates/.* @caesar @crystal @gusted
|
||||||
## the issue sidebar was touched by fnetx
|
## the issue sidebar was touched by fnetx
|
||||||
templates/repo/issue/view_content/sidebar.* @fnetx
|
templates/repo/issue/view_content/sidebar.* @fnetx
|
||||||
|
|
||||||
|
# Playwright tests
|
||||||
|
tests/e2e/.* @fnetx
|
||||||
|
|
||||||
# Files related to Go development.
|
# Files related to Go development.
|
||||||
|
|
||||||
# The modules usually don't require much knowledge about Forgejo and could
|
# The modules usually don't require much knowledge about Forgejo and could
|
||||||
# be reviewed by Go developers.
|
# be reviewed by Go developers.
|
||||||
modules/.* @dachary @earl-warren @gusted
|
modules/.* @gusted
|
||||||
|
|
||||||
# Models has code related to SQL queries, general database knowledge and XORM.
|
# Models has code related to SQL queries, general database knowledge and XORM.
|
||||||
models/.* @dachary @earl-warren @gusted
|
models/.* @gusted
|
||||||
|
|
||||||
# The routers directory contains the most amount code that requires a good grasp
|
# The routers directory contains the most amount code that requires a good grasp
|
||||||
# of how Forgejo comes together. It's tedious to write good integration testing
|
# of how Forgejo comes together. It's tedious to write good integration testing
|
||||||
# for code that lives in here.
|
# for code that lives in here.
|
||||||
routers/.* @dachary @earl-warren @gusted
|
routers/.* @gusted
|
||||||
|
|
||||||
# Let new strings be checked by the translation team.
|
# Let new strings be checked by the translation team.
|
||||||
options/locale/locale_en-US.ini @0ko
|
options/locale/locale_en-US.ini @0ko
|
||||||
|
|
|
@ -4,4 +4,4 @@ The Forgejo project is run by a community of people who are expected to follow t
|
||||||
|
|
||||||
Sensitive security-related issues should be reported to [security@forgejo.org](mailto:security@forgejo.org) using [encryption](https://keyoxide.org/security@forgejo.org).
|
Sensitive security-related issues should be reported to [security@forgejo.org](mailto:security@forgejo.org) using [encryption](https://keyoxide.org/security@forgejo.org).
|
||||||
|
|
||||||
You can find links to the different aspects of Developer documentation on this page: [Forgejo developer guide](https://forgejo.org/docs/next/developer/).
|
You can find links to the different aspects of Developer documentation on this page: [Forgejo Contributor Guide](https://forgejo.org/docs/next/contributor/).
|
||||||
|
|
11
Dockerfile
11
Dockerfile
|
@ -1,6 +1,6 @@
|
||||||
FROM --platform=$BUILDPLATFORM docker.io/tonistiigi/xx AS xx
|
FROM --platform=$BUILDPLATFORM code.forgejo.org/oci/xx AS xx
|
||||||
|
|
||||||
FROM --platform=$BUILDPLATFORM code.forgejo.org/oci/golang:1.22-alpine3.20 as build-env
|
FROM --platform=$BUILDPLATFORM code.forgejo.org/oci/golang:1.23-alpine3.20 as build-env
|
||||||
|
|
||||||
ARG GOPROXY
|
ARG GOPROXY
|
||||||
ENV GOPROXY=${GOPROXY:-direct}
|
ENV GOPROXY=${GOPROXY:-direct}
|
||||||
|
@ -36,7 +36,7 @@ WORKDIR ${GOPATH}/src/code.gitea.io/gitea
|
||||||
RUN make clean
|
RUN make clean
|
||||||
RUN make frontend
|
RUN make frontend
|
||||||
RUN go build contrib/environment-to-ini/environment-to-ini.go && xx-verify environment-to-ini
|
RUN go build contrib/environment-to-ini/environment-to-ini.go && xx-verify environment-to-ini
|
||||||
RUN make RELEASE_VERSION=$RELEASE_VERSION go-check generate-backend static-executable && xx-verify gitea
|
RUN LDFLAGS="-buildid=" make RELEASE_VERSION=$RELEASE_VERSION GOFLAGS="-trimpath" go-check generate-backend static-executable && xx-verify gitea
|
||||||
|
|
||||||
# Copy local files
|
# Copy local files
|
||||||
COPY docker/root /tmp/local
|
COPY docker/root /tmp/local
|
||||||
|
@ -51,7 +51,7 @@ RUN chmod 755 /tmp/local/usr/bin/entrypoint \
|
||||||
/go/src/code.gitea.io/gitea/environment-to-ini
|
/go/src/code.gitea.io/gitea/environment-to-ini
|
||||||
RUN chmod 644 /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete
|
RUN chmod 644 /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete
|
||||||
|
|
||||||
FROM code.forgejo.org/oci/golang:1.22-alpine3.20
|
FROM code.forgejo.org/oci/alpine:3.20
|
||||||
ARG RELEASE_VERSION
|
ARG RELEASE_VERSION
|
||||||
LABEL maintainer="contact@forgejo.org" \
|
LABEL maintainer="contact@forgejo.org" \
|
||||||
org.opencontainers.image.authors="Forgejo" \
|
org.opencontainers.image.authors="Forgejo" \
|
||||||
|
@ -60,7 +60,7 @@ LABEL maintainer="contact@forgejo.org" \
|
||||||
org.opencontainers.image.source="https://codeberg.org/forgejo/forgejo" \
|
org.opencontainers.image.source="https://codeberg.org/forgejo/forgejo" \
|
||||||
org.opencontainers.image.version="${RELEASE_VERSION}" \
|
org.opencontainers.image.version="${RELEASE_VERSION}" \
|
||||||
org.opencontainers.image.vendor="Forgejo" \
|
org.opencontainers.image.vendor="Forgejo" \
|
||||||
org.opencontainers.image.licenses="MIT" \
|
org.opencontainers.image.licenses="GPL-3.0-or-later" \
|
||||||
org.opencontainers.image.title="Forgejo. Beyond coding. We forge." \
|
org.opencontainers.image.title="Forgejo. Beyond coding. We forge." \
|
||||||
org.opencontainers.image.description="Forgejo is a self-hosted lightweight software forge. Easy to install and low maintenance, it just does the job."
|
org.opencontainers.image.description="Forgejo is a self-hosted lightweight software forge. Easy to install and low maintenance, it just does the job."
|
||||||
|
|
||||||
|
@ -103,5 +103,6 @@ CMD ["/bin/s6-svscan", "/etc/s6"]
|
||||||
COPY --from=build-env /tmp/local /
|
COPY --from=build-env /tmp/local /
|
||||||
RUN cd /usr/local/bin ; ln -s gitea forgejo
|
RUN cd /usr/local/bin ; ln -s gitea forgejo
|
||||||
COPY --from=build-env /go/src/code.gitea.io/gitea/gitea /app/gitea/gitea
|
COPY --from=build-env /go/src/code.gitea.io/gitea/gitea /app/gitea/gitea
|
||||||
|
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/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
|
COPY --from=build-env /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete /etc/profile.d/gitea_bash_autocomplete.sh
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
FROM --platform=$BUILDPLATFORM docker.io/tonistiigi/xx AS xx
|
FROM --platform=$BUILDPLATFORM code.forgejo.org/oci/xx AS xx
|
||||||
|
|
||||||
FROM --platform=$BUILDPLATFORM code.forgejo.org/oci/golang:1.22-alpine3.20 as build-env
|
FROM --platform=$BUILDPLATFORM code.forgejo.org/oci/golang:1.23-alpine3.20 as build-env
|
||||||
|
|
||||||
ARG GOPROXY
|
ARG GOPROXY
|
||||||
ENV GOPROXY=${GOPROXY:-direct}
|
ENV GOPROXY=${GOPROXY:-direct}
|
||||||
|
@ -49,7 +49,7 @@ RUN chmod 755 /tmp/local/usr/local/bin/docker-entrypoint.sh \
|
||||||
/go/src/code.gitea.io/gitea/environment-to-ini
|
/go/src/code.gitea.io/gitea/environment-to-ini
|
||||||
RUN chmod 644 /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete
|
RUN chmod 644 /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete
|
||||||
|
|
||||||
FROM code.forgejo.org/oci/golang:1.22-alpine3.20
|
FROM code.forgejo.org/oci/alpine:3.20
|
||||||
LABEL maintainer="contact@forgejo.org" \
|
LABEL maintainer="contact@forgejo.org" \
|
||||||
org.opencontainers.image.authors="Forgejo" \
|
org.opencontainers.image.authors="Forgejo" \
|
||||||
org.opencontainers.image.url="https://forgejo.org" \
|
org.opencontainers.image.url="https://forgejo.org" \
|
||||||
|
@ -57,7 +57,7 @@ LABEL maintainer="contact@forgejo.org" \
|
||||||
org.opencontainers.image.source="https://codeberg.org/forgejo/forgejo" \
|
org.opencontainers.image.source="https://codeberg.org/forgejo/forgejo" \
|
||||||
org.opencontainers.image.version="${RELEASE_VERSION}" \
|
org.opencontainers.image.version="${RELEASE_VERSION}" \
|
||||||
org.opencontainers.image.vendor="Forgejo" \
|
org.opencontainers.image.vendor="Forgejo" \
|
||||||
org.opencontainers.image.licenses="MIT" \
|
org.opencontainers.image.licenses="GPL-3.0-or-later" \
|
||||||
org.opencontainers.image.title="Forgejo. Beyond coding. We forge." \
|
org.opencontainers.image.title="Forgejo. Beyond coding. We forge." \
|
||||||
org.opencontainers.image.description="Forgejo is a self-hosted lightweight software forge. Easy to install and low maintenance, it just does the job."
|
org.opencontainers.image.description="Forgejo is a self-hosted lightweight software forge. Easy to install and low maintenance, it just does the job."
|
||||||
|
|
||||||
|
@ -90,6 +90,7 @@ RUN chown git:git /var/lib/gitea /etc/gitea
|
||||||
COPY --from=build-env /tmp/local /
|
COPY --from=build-env /tmp/local /
|
||||||
RUN cd /usr/local/bin ; ln -s gitea forgejo
|
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
|
COPY --from=build-env --chown=root:root /go/src/code.gitea.io/gitea/gitea /app/gitea/gitea
|
||||||
|
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 --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
|
COPY --from=build-env /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete /etc/profile.d/gitea_bash_autocomplete.sh
|
||||||
|
|
||||||
|
@ -111,4 +112,3 @@ WORKDIR /var/lib/gitea
|
||||||
|
|
||||||
ENTRYPOINT ["/usr/bin/dumb-init", "--", "/usr/local/bin/docker-entrypoint.sh"]
|
ENTRYPOINT ["/usr/bin/dumb-init", "--", "/usr/local/bin/docker-entrypoint.sh"]
|
||||||
CMD []
|
CMD []
|
||||||
|
|
||||||
|
|
689
LICENSE
689
LICENSE
|
@ -1,21 +1,674 @@
|
||||||
Copyright (c) 2022 The Forgejo Authors
|
GNU GENERAL PUBLIC LICENSE
|
||||||
Copyright (c) 2016 The Gitea Authors
|
Version 3, 29 June 2007
|
||||||
Copyright (c) 2015 The Gogs Authors
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
in the Software without restriction, including without limitation the rights
|
of this license document, but changing it is not allowed.
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
Preamble
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
The GNU General Public License is a free, copyleft license for
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
software and other kinds of works.
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
The licenses for most software and other practical works are designed
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
to take away your freedom to share and change the works. By contrast,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
the GNU General Public License is intended to guarantee your freedom to
|
||||||
THE SOFTWARE.
|
share and change all versions of a program--to make sure it remains free
|
||||||
|
software for all its users. We, the Free Software Foundation, use the
|
||||||
|
GNU General Public License for most of our software; it applies also to
|
||||||
|
any other work released this way by its authors. You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
them if you wish), that you receive source code or can get it if you
|
||||||
|
want it, that you can change the software or use pieces of it in new
|
||||||
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to prevent others from denying you
|
||||||
|
these rights or asking you to surrender the rights. Therefore, you have
|
||||||
|
certain responsibilities if you distribute copies of the software, or if
|
||||||
|
you modify it: responsibilities to respect the freedom of others.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must pass on to the recipients the same
|
||||||
|
freedoms that you received. You must make sure that they, too, receive
|
||||||
|
or can get the source code. And you must show them these terms so they
|
||||||
|
know their rights.
|
||||||
|
|
||||||
|
Developers that use the GNU GPL protect your rights with two steps:
|
||||||
|
(1) assert copyright on the software, and (2) offer you this License
|
||||||
|
giving you legal permission to copy, distribute and/or modify it.
|
||||||
|
|
||||||
|
For the developers' and authors' protection, the GPL clearly explains
|
||||||
|
that there is no warranty for this free software. For both users' and
|
||||||
|
authors' sake, the GPL requires that modified versions be marked as
|
||||||
|
changed, so that their problems will not be attributed erroneously to
|
||||||
|
authors of previous versions.
|
||||||
|
|
||||||
|
Some devices are designed to deny users access to install or run
|
||||||
|
modified versions of the software inside them, although the manufacturer
|
||||||
|
can do so. This is fundamentally incompatible with the aim of
|
||||||
|
protecting users' freedom to change the software. The systematic
|
||||||
|
pattern of such abuse occurs in the area of products for individuals to
|
||||||
|
use, which is precisely where it is most unacceptable. Therefore, we
|
||||||
|
have designed this version of the GPL to prohibit the practice for those
|
||||||
|
products. If such problems arise substantially in other domains, we
|
||||||
|
stand ready to extend this provision to those domains in future versions
|
||||||
|
of the GPL, as needed to protect the freedom of users.
|
||||||
|
|
||||||
|
Finally, every program is threatened constantly by software patents.
|
||||||
|
States should not allow patents to restrict development and use of
|
||||||
|
software on general-purpose computers, but in those that do, we wish to
|
||||||
|
avoid the special danger that patents applied to a free program could
|
||||||
|
make it effectively proprietary. To prevent this, the GPL assures that
|
||||||
|
patents cannot be used to render the program non-free.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
0. Definitions.
|
||||||
|
|
||||||
|
"This License" refers to version 3 of the GNU General Public License.
|
||||||
|
|
||||||
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
|
works, such as semiconductor masks.
|
||||||
|
|
||||||
|
"The Program" refers to any copyrightable work licensed under this
|
||||||
|
License. Each licensee is addressed as "you". "Licensees" and
|
||||||
|
"recipients" may be individuals or organizations.
|
||||||
|
|
||||||
|
To "modify" a work means to copy from or adapt all or part of the work
|
||||||
|
in a fashion requiring copyright permission, other than the making of an
|
||||||
|
exact copy. The resulting work is called a "modified version" of the
|
||||||
|
earlier work or a work "based on" the earlier work.
|
||||||
|
|
||||||
|
A "covered work" means either the unmodified Program or a work based
|
||||||
|
on the Program.
|
||||||
|
|
||||||
|
To "propagate" a work means to do anything with it that, without
|
||||||
|
permission, would make you directly or secondarily liable for
|
||||||
|
infringement under applicable copyright law, except executing it on a
|
||||||
|
computer or modifying a private copy. Propagation includes copying,
|
||||||
|
distribution (with or without modification), making available to the
|
||||||
|
public, and in some countries other activities as well.
|
||||||
|
|
||||||
|
To "convey" a work means any kind of propagation that enables other
|
||||||
|
parties to make or receive copies. Mere interaction with a user through
|
||||||
|
a computer network, with no transfer of a copy, is not conveying.
|
||||||
|
|
||||||
|
An interactive user interface displays "Appropriate Legal Notices"
|
||||||
|
to the extent that it includes a convenient and prominently visible
|
||||||
|
feature that (1) displays an appropriate copyright notice, and (2)
|
||||||
|
tells the user that there is no warranty for the work (except to the
|
||||||
|
extent that warranties are provided), that licensees may convey the
|
||||||
|
work under this License, and how to view a copy of this License. If
|
||||||
|
the interface presents a list of user commands or options, such as a
|
||||||
|
menu, a prominent item in the list meets this criterion.
|
||||||
|
|
||||||
|
1. Source Code.
|
||||||
|
|
||||||
|
The "source code" for a work means the preferred form of the work
|
||||||
|
for making modifications to it. "Object code" means any non-source
|
||||||
|
form of a work.
|
||||||
|
|
||||||
|
A "Standard Interface" means an interface that either is an official
|
||||||
|
standard defined by a recognized standards body, or, in the case of
|
||||||
|
interfaces specified for a particular programming language, one that
|
||||||
|
is widely used among developers working in that language.
|
||||||
|
|
||||||
|
The "System Libraries" of an executable work include anything, other
|
||||||
|
than the work as a whole, that (a) is included in the normal form of
|
||||||
|
packaging a Major Component, but which is not part of that Major
|
||||||
|
Component, and (b) serves only to enable use of the work with that
|
||||||
|
Major Component, or to implement a Standard Interface for which an
|
||||||
|
implementation is available to the public in source code form. A
|
||||||
|
"Major Component", in this context, means a major essential component
|
||||||
|
(kernel, window system, and so on) of the specific operating system
|
||||||
|
(if any) on which the executable work runs, or a compiler used to
|
||||||
|
produce the work, or an object code interpreter used to run it.
|
||||||
|
|
||||||
|
The "Corresponding Source" for a work in object code form means all
|
||||||
|
the source code needed to generate, install, and (for an executable
|
||||||
|
work) run the object code and to modify the work, including scripts to
|
||||||
|
control those activities. However, it does not include the work's
|
||||||
|
System Libraries, or general-purpose tools or generally available free
|
||||||
|
programs which are used unmodified in performing those activities but
|
||||||
|
which are not part of the work. For example, Corresponding Source
|
||||||
|
includes interface definition files associated with source files for
|
||||||
|
the work, and the source code for shared libraries and dynamically
|
||||||
|
linked subprograms that the work is specifically designed to require,
|
||||||
|
such as by intimate data communication or control flow between those
|
||||||
|
subprograms and other parts of the work.
|
||||||
|
|
||||||
|
The Corresponding Source need not include anything that users
|
||||||
|
can regenerate automatically from other parts of the Corresponding
|
||||||
|
Source.
|
||||||
|
|
||||||
|
The Corresponding Source for a work in source code form is that
|
||||||
|
same work.
|
||||||
|
|
||||||
|
2. Basic Permissions.
|
||||||
|
|
||||||
|
All rights granted under this License are granted for the term of
|
||||||
|
copyright on the Program, and are irrevocable provided the stated
|
||||||
|
conditions are met. This License explicitly affirms your unlimited
|
||||||
|
permission to run the unmodified Program. The output from running a
|
||||||
|
covered work is covered by this License only if the output, given its
|
||||||
|
content, constitutes a covered work. This License acknowledges your
|
||||||
|
rights of fair use or other equivalent, as provided by copyright law.
|
||||||
|
|
||||||
|
You may make, run and propagate covered works that you do not
|
||||||
|
convey, without conditions so long as your license otherwise remains
|
||||||
|
in force. You may convey covered works to others for the sole purpose
|
||||||
|
of having them make modifications exclusively for you, or provide you
|
||||||
|
with facilities for running those works, provided that you comply with
|
||||||
|
the terms of this License in conveying all material for which you do
|
||||||
|
not control copyright. Those thus making or running the covered works
|
||||||
|
for you must do so exclusively on your behalf, under your direction
|
||||||
|
and control, on terms that prohibit them from making any copies of
|
||||||
|
your copyrighted material outside their relationship with you.
|
||||||
|
|
||||||
|
Conveying under any other circumstances is permitted solely under
|
||||||
|
the conditions stated below. Sublicensing is not allowed; section 10
|
||||||
|
makes it unnecessary.
|
||||||
|
|
||||||
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
|
|
||||||
|
No covered work shall be deemed part of an effective technological
|
||||||
|
measure under any applicable law fulfilling obligations under article
|
||||||
|
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||||
|
similar laws prohibiting or restricting circumvention of such
|
||||||
|
measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid
|
||||||
|
circumvention of technological measures to the extent such circumvention
|
||||||
|
is effected by exercising rights under this License with respect to
|
||||||
|
the covered work, and you disclaim any intention to limit operation or
|
||||||
|
modification of the work as a means of enforcing, against the work's
|
||||||
|
users, your or third parties' legal rights to forbid circumvention of
|
||||||
|
technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey verbatim copies of the Program's source code as you
|
||||||
|
receive it, in any medium, provided that you conspicuously and
|
||||||
|
appropriately publish on each copy an appropriate copyright notice;
|
||||||
|
keep intact all notices stating that this License and any
|
||||||
|
non-permissive terms added in accord with section 7 apply to the code;
|
||||||
|
keep intact all notices of the absence of any warranty; and give all
|
||||||
|
recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey,
|
||||||
|
and you may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to
|
||||||
|
produce it from the Program, in the form of source code under the
|
||||||
|
terms of section 4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified
|
||||||
|
it, and giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is
|
||||||
|
released under this License and any conditions added under section
|
||||||
|
7. This requirement modifies the requirement in section 4 to
|
||||||
|
"keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this
|
||||||
|
License to anyone who comes into possession of a copy. This
|
||||||
|
License will therefore apply, along with any applicable section 7
|
||||||
|
additional terms, to the whole of the work, and all its parts,
|
||||||
|
regardless of how they are packaged. This License gives no
|
||||||
|
permission to license the work in any other way, but it does not
|
||||||
|
invalidate such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display
|
||||||
|
Appropriate Legal Notices; however, if the Program has interactive
|
||||||
|
interfaces that do not display Appropriate Legal Notices, your
|
||||||
|
work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent
|
||||||
|
works, which are not by their nature extensions of the covered work,
|
||||||
|
and which are not combined with it such as to form a larger program,
|
||||||
|
in or on a volume of a storage or distribution medium, is called an
|
||||||
|
"aggregate" if the compilation and its resulting copyright are not
|
||||||
|
used to limit the access or legal rights of the compilation's users
|
||||||
|
beyond what the individual works permit. Inclusion of a covered work
|
||||||
|
in an aggregate does not cause this License to apply to the other
|
||||||
|
parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms
|
||||||
|
of sections 4 and 5, provided that you also convey the
|
||||||
|
machine-readable Corresponding Source under the terms of this License,
|
||||||
|
in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by the
|
||||||
|
Corresponding Source fixed on a durable physical medium
|
||||||
|
customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by a
|
||||||
|
written offer, valid for at least three years and valid for as
|
||||||
|
long as you offer spare parts or customer support for that product
|
||||||
|
model, to give anyone who possesses the object code either (1) a
|
||||||
|
copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical
|
||||||
|
medium customarily used for software interchange, for a price no
|
||||||
|
more than your reasonable cost of physically performing this
|
||||||
|
conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the
|
||||||
|
written offer to provide the Corresponding Source. This
|
||||||
|
alternative is allowed only occasionally and noncommercially, and
|
||||||
|
only if you received the object code with such an offer, in accord
|
||||||
|
with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated
|
||||||
|
place (gratis or for a charge), and offer equivalent access to the
|
||||||
|
Corresponding Source in the same way through the same place at no
|
||||||
|
further charge. You need not require recipients to copy the
|
||||||
|
Corresponding Source along with the object code. If the place to
|
||||||
|
copy the object code is a network server, the Corresponding Source
|
||||||
|
may be on a different server (operated by you or a third party)
|
||||||
|
that supports equivalent copying facilities, provided you maintain
|
||||||
|
clear directions next to the object code saying where to find the
|
||||||
|
Corresponding Source. Regardless of what server hosts the
|
||||||
|
Corresponding Source, you remain obligated to ensure that it is
|
||||||
|
available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided
|
||||||
|
you inform other peers where the object code and Corresponding
|
||||||
|
Source of the work are being offered to the general public at no
|
||||||
|
charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded
|
||||||
|
from the Corresponding Source as a System Library, need not be
|
||||||
|
included in conveying the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any
|
||||||
|
tangible personal property which is normally used for personal, family,
|
||||||
|
or household purposes, or (2) anything designed or sold for incorporation
|
||||||
|
into a dwelling. In determining whether a product is a consumer product,
|
||||||
|
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||||
|
product received by a particular user, "normally used" refers to a
|
||||||
|
typical or common use of that class of product, regardless of the status
|
||||||
|
of the particular user or of the way in which the particular user
|
||||||
|
actually uses, or expects or is expected to use, the product. A product
|
||||||
|
is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent
|
||||||
|
the only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods,
|
||||||
|
procedures, authorization keys, or other information required to install
|
||||||
|
and execute modified versions of a covered work in that User Product from
|
||||||
|
a modified version of its Corresponding Source. The information must
|
||||||
|
suffice to ensure that the continued functioning of the modified object
|
||||||
|
code is in no case prevented or interfered with solely because
|
||||||
|
modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or
|
||||||
|
specifically for use in, a User Product, and the conveying occurs as
|
||||||
|
part of a transaction in which the right of possession and use of the
|
||||||
|
User Product is transferred to the recipient in perpetuity or for a
|
||||||
|
fixed term (regardless of how the transaction is characterized), the
|
||||||
|
Corresponding Source conveyed under this section must be accompanied
|
||||||
|
by the Installation Information. But this requirement does not apply
|
||||||
|
if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has
|
||||||
|
been installed in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a
|
||||||
|
requirement to continue to provide support service, warranty, or updates
|
||||||
|
for a work that has been modified or installed by the recipient, or for
|
||||||
|
the User Product in which it has been modified or installed. Access to a
|
||||||
|
network may be denied when the modification itself materially and
|
||||||
|
adversely affects the operation of the network or violates the rules and
|
||||||
|
protocols for communication across the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided,
|
||||||
|
in accord with this section must be in a format that is publicly
|
||||||
|
documented (and with an implementation available to the public in
|
||||||
|
source code form), and must require no special password or key for
|
||||||
|
unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this
|
||||||
|
License by making exceptions from one or more of its conditions.
|
||||||
|
Additional permissions that are applicable to the entire Program shall
|
||||||
|
be treated as though they were included in this License, to the extent
|
||||||
|
that they are valid under applicable law. If additional permissions
|
||||||
|
apply only to part of the Program, that part may be used separately
|
||||||
|
under those permissions, but the entire Program remains governed by
|
||||||
|
this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option
|
||||||
|
remove any additional permissions from that copy, or from any part of
|
||||||
|
it. (Additional permissions may be written to require their own
|
||||||
|
removal in certain cases when you modify the work.) You may place
|
||||||
|
additional permissions on material, added by you to a covered work,
|
||||||
|
for which you have or can give appropriate copyright permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you
|
||||||
|
add to a covered work, you may (if authorized by the copyright holders of
|
||||||
|
that material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the
|
||||||
|
terms of sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or
|
||||||
|
author attributions in that material or in the Appropriate Legal
|
||||||
|
Notices displayed by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or
|
||||||
|
requiring that modified versions of such material be marked in
|
||||||
|
reasonable ways as different from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or
|
||||||
|
authors of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some
|
||||||
|
trade names, trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that
|
||||||
|
material by anyone who conveys the material (or modified versions of
|
||||||
|
it) with contractual assumptions of liability to the recipient, for
|
||||||
|
any liability that these contractual assumptions directly impose on
|
||||||
|
those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further
|
||||||
|
restrictions" within the meaning of section 10. If the Program as you
|
||||||
|
received it, or any part of it, contains a notice stating that it is
|
||||||
|
governed by this License along with a term that is a further
|
||||||
|
restriction, you may remove that term. If a license document contains
|
||||||
|
a further restriction but permits relicensing or conveying under this
|
||||||
|
License, you may add to a covered work material governed by the terms
|
||||||
|
of that license document, provided that the further restriction does
|
||||||
|
not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you
|
||||||
|
must place, in the relevant source files, a statement of the
|
||||||
|
additional terms that apply to those files, or a notice indicating
|
||||||
|
where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the
|
||||||
|
form of a separately written license, or stated as exceptions;
|
||||||
|
the above requirements apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly
|
||||||
|
provided under this License. Any attempt otherwise to propagate or
|
||||||
|
modify it is void, and will automatically terminate your rights under
|
||||||
|
this License (including any patent licenses granted under the third
|
||||||
|
paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your
|
||||||
|
license from a particular copyright holder is reinstated (a)
|
||||||
|
provisionally, unless and until the copyright holder explicitly and
|
||||||
|
finally terminates your license, and (b) permanently, if the copyright
|
||||||
|
holder fails to notify you of the violation by some reasonable means
|
||||||
|
prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is
|
||||||
|
reinstated permanently if the copyright holder notifies you of the
|
||||||
|
violation by some reasonable means, this is the first time you have
|
||||||
|
received notice of violation of this License (for any work) from that
|
||||||
|
copyright holder, and you cure the violation prior to 30 days after
|
||||||
|
your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the
|
||||||
|
licenses of parties who have received copies or rights from you under
|
||||||
|
this License. If your rights have been terminated and not permanently
|
||||||
|
reinstated, you do not qualify to receive new licenses for the same
|
||||||
|
material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or
|
||||||
|
run a copy of the Program. Ancillary propagation of a covered work
|
||||||
|
occurring solely as a consequence of using peer-to-peer transmission
|
||||||
|
to receive a copy likewise does not require acceptance. However,
|
||||||
|
nothing other than this License grants you permission to propagate or
|
||||||
|
modify any covered work. These actions infringe copyright if you do
|
||||||
|
not accept this License. Therefore, by modifying or propagating a
|
||||||
|
covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically
|
||||||
|
receives a license from the original licensors, to run, modify and
|
||||||
|
propagate that work, subject to this License. You are not responsible
|
||||||
|
for enforcing compliance by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an
|
||||||
|
organization, or substantially all assets of one, or subdividing an
|
||||||
|
organization, or merging organizations. If propagation of a covered
|
||||||
|
work results from an entity transaction, each party to that
|
||||||
|
transaction who receives a copy of the work also receives whatever
|
||||||
|
licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the
|
||||||
|
Corresponding Source of the work from the predecessor in interest, if
|
||||||
|
the predecessor has it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the
|
||||||
|
rights granted or affirmed under this License. For example, you may
|
||||||
|
not impose a license fee, royalty, or other charge for exercise of
|
||||||
|
rights granted under this License, and you may not initiate litigation
|
||||||
|
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||||
|
any patent claim is infringed by making, using, selling, offering for
|
||||||
|
sale, or importing the Program or any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this
|
||||||
|
License of the Program or a work on which the Program is based. The
|
||||||
|
work thus licensed is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims
|
||||||
|
owned or controlled by the contributor, whether already acquired or
|
||||||
|
hereafter acquired, that would be infringed by some manner, permitted
|
||||||
|
by this License, of making, using, or selling its contributor version,
|
||||||
|
but do not include claims that would be infringed only as a
|
||||||
|
consequence of further modification of the contributor version. For
|
||||||
|
purposes of this definition, "control" includes the right to grant
|
||||||
|
patent sublicenses in a manner consistent with the requirements of
|
||||||
|
this License.
|
||||||
|
|
||||||
|
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||||
|
patent license under the contributor's essential patent claims, to
|
||||||
|
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||||
|
propagate the contents of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express
|
||||||
|
agreement or commitment, however denominated, not to enforce a patent
|
||||||
|
(such as an express permission to practice a patent or covenant not to
|
||||||
|
sue for patent infringement). To "grant" such a patent license to a
|
||||||
|
party means to make such an agreement or commitment not to enforce a
|
||||||
|
patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license,
|
||||||
|
and the Corresponding Source of the work is not available for anyone
|
||||||
|
to copy, free of charge and under the terms of this License, through a
|
||||||
|
publicly available network server or other readily accessible means,
|
||||||
|
then you must either (1) cause the Corresponding Source to be so
|
||||||
|
available, or (2) arrange to deprive yourself of the benefit of the
|
||||||
|
patent license for this particular work, or (3) arrange, in a manner
|
||||||
|
consistent with the requirements of this License, to extend the patent
|
||||||
|
license to downstream recipients. "Knowingly relying" means you have
|
||||||
|
actual knowledge that, but for the patent license, your conveying the
|
||||||
|
covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that
|
||||||
|
country that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or
|
||||||
|
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||||
|
covered work, and grant a patent license to some of the parties
|
||||||
|
receiving the covered work authorizing them to use, propagate, modify
|
||||||
|
or convey a specific copy of the covered work, then the patent license
|
||||||
|
you grant is automatically extended to all recipients of the covered
|
||||||
|
work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within
|
||||||
|
the scope of its coverage, prohibits the exercise of, or is
|
||||||
|
conditioned on the non-exercise of one or more of the rights that are
|
||||||
|
specifically granted under this License. You may not convey a covered
|
||||||
|
work if you are a party to an arrangement with a third party that is
|
||||||
|
in the business of distributing software, under which you make payment
|
||||||
|
to the third party based on the extent of your activity of conveying
|
||||||
|
the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory
|
||||||
|
patent license (a) in connection with copies of the covered work
|
||||||
|
conveyed by you (or copies made from those copies), or (b) primarily
|
||||||
|
for and in connection with specific products or compilations that
|
||||||
|
contain the covered work, unless you entered into that arrangement,
|
||||||
|
or that patent license was granted, prior to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting
|
||||||
|
any implied license or other defenses to infringement that may
|
||||||
|
otherwise be available to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot convey a
|
||||||
|
covered work so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you may
|
||||||
|
not convey it at all. For example, if you agree to terms that obligate you
|
||||||
|
to collect a royalty for further conveying from those to whom you convey
|
||||||
|
the Program, the only way you could satisfy both those terms and this
|
||||||
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
|
13. Use with the GNU Affero General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, you have
|
||||||
|
permission to link or combine any covered work with a work licensed
|
||||||
|
under version 3 of the GNU Affero General Public License into a single
|
||||||
|
combined work, and to convey the resulting work. The terms of this
|
||||||
|
License will continue to apply to the part which is the covered work,
|
||||||
|
but the special requirements of the GNU Affero General Public License,
|
||||||
|
section 13, concerning interaction through a network will apply to the
|
||||||
|
combination as such.
|
||||||
|
|
||||||
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
|
the GNU General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Program specifies that a certain numbered version of the GNU General
|
||||||
|
Public License "or any later version" applies to it, you have the
|
||||||
|
option of following the terms and conditions either of that numbered
|
||||||
|
version or of any later version published by the Free Software
|
||||||
|
Foundation. If the Program does not specify a version number of the
|
||||||
|
GNU General Public License, you may choose any version ever published
|
||||||
|
by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Program specifies that a proxy can decide which future
|
||||||
|
versions of the GNU General Public License can be used, that proxy's
|
||||||
|
public statement of acceptance of a version permanently authorizes you
|
||||||
|
to choose that version for the Program.
|
||||||
|
|
||||||
|
Later license versions may give you additional or different
|
||||||
|
permissions. However, no additional obligations are imposed on any
|
||||||
|
author or copyright holder as a result of your choosing to follow a
|
||||||
|
later version.
|
||||||
|
|
||||||
|
15. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||||
|
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||||
|
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||||
|
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||||
|
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||||
|
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. Limitation of Liability.
|
||||||
|
|
||||||
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||||
|
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||||
|
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||||
|
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||||
|
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||||
|
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||||
|
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGES.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided
|
||||||
|
above cannot be given local legal effect according to their terms,
|
||||||
|
reviewing courts shall apply local law that most closely approximates
|
||||||
|
an absolute waiver of all civil liability in connection with the
|
||||||
|
Program, unless a warranty or assumption of liability accompanies a
|
||||||
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
state the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program does terminal interaction, make it output a short
|
||||||
|
notice like this when it starts in an interactive mode:
|
||||||
|
|
||||||
|
<program> Copyright (C) <year> <name of author>
|
||||||
|
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, your program's commands
|
||||||
|
might be different; for a GUI interface, you would use an "about box".
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
|
For more information on this, and how to apply and follow the GNU GPL, see
|
||||||
|
<https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
The GNU General Public License does not permit incorporating your program
|
||||||
|
into proprietary programs. If your program is a subroutine library, you
|
||||||
|
may consider it more useful to permit linking proprietary applications with
|
||||||
|
the library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License. But first, please read
|
||||||
|
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||||||
|
|
196
Makefile
196
Makefile
|
@ -24,26 +24,32 @@ HAS_GO := $(shell hash $(GO) > /dev/null 2>&1 && echo yes)
|
||||||
COMMA := ,
|
COMMA := ,
|
||||||
DIFF ?= diff --unified
|
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
|
XGO_VERSION := go-1.21.x
|
||||||
|
|
||||||
AIR_PACKAGE ?= github.com/air-verse/air@v1 # renovate: datasource=go
|
AIR_PACKAGE ?= github.com/air-verse/air@v1 # renovate: datasource=go
|
||||||
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/v2/cmd/editorconfig-checker@2.8.0 # 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.6.0 # 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.59.1 # 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
|
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
|
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
|
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.31.0 # renovate: datasource=go
|
||||||
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
|
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
|
||||||
GO_LICENSES_PACKAGE ?= github.com/google/go-licenses@v1.6.0 # renovate: datasource=go
|
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
|
GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@v1 # renovate: datasource=go
|
||||||
DEADCODE_PACKAGE ?= golang.org/x/tools/cmd/deadcode@v0.23.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
|
GOMOCK_PACKAGE ?= go.uber.org/mock/mockgen@v0.4.0 # renovate: datasource=go
|
||||||
GOPLS_PACKAGE ?= golang.org/x/tools/gopls@v0.16.1 # renovate: datasource=go
|
GOPLS_PACKAGE ?= golang.org/x/tools/gopls@v0.16.2 # renovate: datasource=go
|
||||||
RENOVATE_NPM_PACKAGE ?= renovate@37.431.4 # renovate: datasource=docker packageName=ghcr.io/visualon/renovate
|
RENOVATE_NPM_PACKAGE ?= renovate@39.19.1 # renovate: datasource=docker packageName=code.forgejo.org/forgejo-contrib/renovate
|
||||||
|
|
||||||
DOCKER_IMAGE ?= gitea/gitea
|
|
||||||
DOCKER_TAG ?= latest
|
|
||||||
DOCKER_REF := $(DOCKER_IMAGE):$(DOCKER_TAG)
|
|
||||||
|
|
||||||
ifeq ($(HAS_GO), yes)
|
ifeq ($(HAS_GO), yes)
|
||||||
CGO_EXTRA_CFLAGS := -DSQLITE_MAX_VARIABLE_NUMBER=32766
|
CGO_EXTRA_CFLAGS := -DSQLITE_MAX_VARIABLE_NUMBER=32766
|
||||||
|
@ -123,7 +129,7 @@ LDFLAGS := $(LDFLAGS) -X "main.ReleaseVersion=$(RELEASE_VERSION)" -X "main.MakeV
|
||||||
LINUX_ARCHS ?= linux/amd64,linux/386,linux/arm-5,linux/arm-6,linux/arm64
|
LINUX_ARCHS ?= linux/amd64,linux/386,linux/arm-5,linux/arm-6,linux/arm64
|
||||||
|
|
||||||
ifeq ($(HAS_GO), yes)
|
ifeq ($(HAS_GO), yes)
|
||||||
GO_TEST_PACKAGES ?= $(filter-out $(shell $(GO) list code.gitea.io/gitea/models/migrations/...) $(shell $(GO) list code.gitea.io/gitea/models/forgejo_migrations/...) code.gitea.io/gitea/tests/integration/migration-test code.gitea.io/gitea/tests code.gitea.io/gitea/tests/integration code.gitea.io/gitea/tests/e2e,$(shell $(GO) list ./... | grep -v /vendor/))
|
GO_TEST_PACKAGES ?= $(filter-out $(shell $(GO) list code.gitea.io/gitea/models/migrations/...) $(shell $(GO) list code.gitea.io/gitea/models/forgejo_migrations/...) code.gitea.io/gitea/tests/integration/migration-test code.gitea.io/gitea/tests code.gitea.io/gitea/tests/integration code.gitea.io/gitea/tests/e2e,$(shell $(GO) list ./...))
|
||||||
endif
|
endif
|
||||||
REMOTE_CACHER_MODULES ?= cache nosql session queue
|
REMOTE_CACHER_MODULES ?= cache nosql session queue
|
||||||
GO_TEST_REMOTE_CACHER_PACKAGES ?= $(addprefix code.gitea.io/gitea/modules/,$(REMOTE_CACHER_MODULES))
|
GO_TEST_REMOTE_CACHER_PACKAGES ?= $(addprefix code.gitea.io/gitea/modules/,$(REMOTE_CACHER_MODULES))
|
||||||
|
@ -158,9 +164,8 @@ TAR_EXCLUDES := .git data indexers queues log node_modules $(EXECUTABLE) $(FOMAN
|
||||||
GO_DIRS := build cmd models modules routers services tests
|
GO_DIRS := build cmd models modules routers services tests
|
||||||
WEB_DIRS := web_src/js web_src/css
|
WEB_DIRS := web_src/js web_src/css
|
||||||
|
|
||||||
ESLINT_FILES := web_src/js tools *.js tests/e2e
|
|
||||||
STYLELINT_FILES := web_src/css web_src/js/components/*.vue
|
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 := $(wildcard *.go)
|
||||||
GO_SOURCES += $(shell find $(GO_DIRS) -type f -name "*.go" ! -path modules/options/bindata.go ! -path modules/public/bindata.go ! -path modules/templates/bindata.go)
|
GO_SOURCES += $(shell find $(GO_DIRS) -type f -name "*.go" ! -path modules/options/bindata.go ! -path modules/public/bindata.go ! -path modules/templates/bindata.go)
|
||||||
|
@ -189,6 +194,7 @@ SWAGGER_SPEC_S_JSON := s|"basePath": *"{{AppSubUrl \| JSEscape}}/api/v1"|"basePa
|
||||||
SWAGGER_EXCLUDE := code.gitea.io/sdk
|
SWAGGER_EXCLUDE := code.gitea.io/sdk
|
||||||
SWAGGER_NEWLINE_COMMAND := -e '$$a\'
|
SWAGGER_NEWLINE_COMMAND := -e '$$a\'
|
||||||
SWAGGER_SPEC_BRANDING := s|Gitea API|Forgejo API|g
|
SWAGGER_SPEC_BRANDING := s|Gitea API|Forgejo API|g
|
||||||
|
SWAGGER_SPEC_LICENSE := s|"name": "MIT"|"name": "This file is distributed under the MIT license for the purpose of interoperability"|
|
||||||
|
|
||||||
TEST_MYSQL_HOST ?= mysql:3306
|
TEST_MYSQL_HOST ?= mysql:3306
|
||||||
TEST_MYSQL_DBNAME ?= testgitea?multiStatements=true
|
TEST_MYSQL_DBNAME ?= testgitea?multiStatements=true
|
||||||
|
@ -272,6 +278,11 @@ help:
|
||||||
@echo " - tidy run go mod tidy"
|
@echo " - tidy run go mod tidy"
|
||||||
@echo " - test[\#TestSpecificName] run unit test"
|
@echo " - test[\#TestSpecificName] run unit test"
|
||||||
@echo " - test-sqlite[\#TestSpecificName] run integration test for sqlite"
|
@echo " - test-sqlite[\#TestSpecificName] run integration test for sqlite"
|
||||||
|
@echo " - reproduce-build\#version build a reproducible binary for the specified release version"
|
||||||
|
|
||||||
|
###
|
||||||
|
# Check system and environment requirements
|
||||||
|
###
|
||||||
|
|
||||||
.PHONY: go-check
|
.PHONY: go-check
|
||||||
go-check:
|
go-check:
|
||||||
|
@ -279,14 +290,14 @@ go-check:
|
||||||
$(eval MIN_GO_VERSION := $(shell printf "%03d%03d" $(shell echo '$(MIN_GO_VERSION_STR)' | tr '.' ' ')))
|
$(eval MIN_GO_VERSION := $(shell printf "%03d%03d" $(shell echo '$(MIN_GO_VERSION_STR)' | tr '.' ' ')))
|
||||||
$(eval GO_VERSION := $(shell printf "%03d%03d" $(shell $(GO) version | grep -Eo '[0-9]+\.[0-9]+' | tr '.' ' ');))
|
$(eval GO_VERSION := $(shell printf "%03d%03d" $(shell $(GO) version | grep -Eo '[0-9]+\.[0-9]+' | tr '.' ' ');))
|
||||||
@if [ "$(GO_VERSION)" -lt "$(MIN_GO_VERSION)" ]; then \
|
@if [ "$(GO_VERSION)" -lt "$(MIN_GO_VERSION)" ]; then \
|
||||||
echo "Gitea requires Go $(MIN_GO_VERSION_STR) or greater to build. You can get it at https://go.dev/dl/"; \
|
echo "Forgejo requires Go $(MIN_GO_VERSION_STR) or greater to build. You can get it at https://go.dev/dl/"; \
|
||||||
exit 1; \
|
exit 1; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
.PHONY: git-check
|
.PHONY: git-check
|
||||||
git-check:
|
git-check:
|
||||||
@if git lfs >/dev/null 2>&1 ; then : ; else \
|
@if git lfs >/dev/null 2>&1 ; then : ; else \
|
||||||
echo "Gitea requires git with lfs support to run tests." ; \
|
echo "Forgejo requires git with lfs support to run tests." ; \
|
||||||
exit 1; \
|
exit 1; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -297,10 +308,14 @@ node-check:
|
||||||
$(eval NODE_VERSION := $(shell printf "%03d%03d%03d" $(shell node -v | cut -c2- | tr '.' ' ');))
|
$(eval NODE_VERSION := $(shell printf "%03d%03d%03d" $(shell node -v | cut -c2- | tr '.' ' ');))
|
||||||
$(eval NPM_MISSING := $(shell hash npm > /dev/null 2>&1 || echo 1))
|
$(eval NPM_MISSING := $(shell hash npm > /dev/null 2>&1 || echo 1))
|
||||||
@if [ "$(NODE_VERSION)" -lt "$(MIN_NODE_VERSION)" -o "$(NPM_MISSING)" = "1" ]; then \
|
@if [ "$(NODE_VERSION)" -lt "$(MIN_NODE_VERSION)" -o "$(NPM_MISSING)" = "1" ]; then \
|
||||||
echo "Gitea requires Node.js $(MIN_NODE_VERSION_STR) or greater and npm to build. You can get it at https://nodejs.org/en/download/"; \
|
echo "Forgejo requires Node.js $(MIN_NODE_VERSION_STR) or greater and npm to build. You can get it at https://nodejs.org/en/download/"; \
|
||||||
exit 1; \
|
exit 1; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
###
|
||||||
|
# Basic maintenance, check and lint targets
|
||||||
|
###
|
||||||
|
|
||||||
.PHONY: clean-all
|
.PHONY: clean-all
|
||||||
clean-all: clean
|
clean-all: clean
|
||||||
rm -rf $(WEBPACK_DEST_ENTRIES) node_modules
|
rm -rf $(WEBPACK_DEST_ENTRIES) node_modules
|
||||||
|
@ -367,6 +382,7 @@ $(SWAGGER_SPEC): $(GO_SOURCES_NO_BINDATA)
|
||||||
$(SED_INPLACE) '$(SWAGGER_SPEC_S_TMPL)' './$(SWAGGER_SPEC)'
|
$(SED_INPLACE) '$(SWAGGER_SPEC_S_TMPL)' './$(SWAGGER_SPEC)'
|
||||||
$(SED_INPLACE) $(SWAGGER_NEWLINE_COMMAND) './$(SWAGGER_SPEC)'
|
$(SED_INPLACE) $(SWAGGER_NEWLINE_COMMAND) './$(SWAGGER_SPEC)'
|
||||||
$(SED_INPLACE) '$(SWAGGER_SPEC_BRANDING)' './$(SWAGGER_SPEC)'
|
$(SED_INPLACE) '$(SWAGGER_SPEC_BRANDING)' './$(SWAGGER_SPEC)'
|
||||||
|
$(SED_INPLACE) '$(SWAGGER_SPEC_LICENSE)' './$(SWAGGER_SPEC)'
|
||||||
|
|
||||||
.PHONY: swagger-check
|
.PHONY: swagger-check
|
||||||
swagger-check: generate-swagger
|
swagger-check: generate-swagger
|
||||||
|
@ -401,7 +417,7 @@ lint-frontend: lint-js lint-css
|
||||||
lint-frontend-fix: lint-js-fix lint-css-fix
|
lint-frontend-fix: lint-js-fix lint-css-fix
|
||||||
|
|
||||||
.PHONY: lint-backend
|
.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
|
.PHONY: lint-backend-fix
|
||||||
lint-backend-fix: lint-go-fix lint-go-vet lint-editorconfig
|
lint-backend-fix: lint-go-fix lint-go-vet lint-editorconfig
|
||||||
|
@ -420,11 +436,11 @@ lint-codespell-fix-i:
|
||||||
|
|
||||||
.PHONY: lint-js
|
.PHONY: lint-js
|
||||||
lint-js: node_modules
|
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
|
.PHONY: lint-js-fix
|
||||||
lint-js-fix: node_modules
|
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
|
.PHONY: lint-css
|
||||||
lint-css: node_modules
|
lint-css: node_modules
|
||||||
|
@ -444,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
|
@if grep --quiet --extended-regexp -e '^( WARN:|ERROR:)' .lint-renovate ; then cat .lint-renovate ; rm .lint-renovate ; exit 1 ; fi
|
||||||
@rm .lint-renovate
|
@rm .lint-renovate
|
||||||
|
|
||||||
|
.PHONY: lint-locale
|
||||||
|
lint-locale:
|
||||||
|
$(GO) run build/lint-locale.go
|
||||||
|
|
||||||
.PHONY: lint-md
|
.PHONY: lint-md
|
||||||
lint-md: node_modules
|
lint-md: node_modules
|
||||||
npx markdownlint docs *.md
|
npx markdownlint docs *.md
|
||||||
|
@ -500,6 +520,14 @@ lint-templates: .venv node_modules
|
||||||
lint-yaml: .venv
|
lint-yaml: .venv
|
||||||
@poetry run yamllint .
|
@poetry run yamllint .
|
||||||
|
|
||||||
|
.PHONY: security-check
|
||||||
|
security-check:
|
||||||
|
go run $(GOVULNCHECK_PACKAGE) ./...
|
||||||
|
|
||||||
|
###
|
||||||
|
# Development and testing targets
|
||||||
|
###
|
||||||
|
|
||||||
.PHONY: watch
|
.PHONY: watch
|
||||||
watch:
|
watch:
|
||||||
@bash tools/watch.sh
|
@bash tools/watch.sh
|
||||||
|
@ -519,12 +547,12 @@ test: test-frontend test-backend
|
||||||
.PHONY: test-backend
|
.PHONY: test-backend
|
||||||
test-backend:
|
test-backend:
|
||||||
@echo "Running go test with $(GOTESTFLAGS) -tags '$(TEST_TAGS)'..."
|
@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
|
.PHONY: test-remote-cacher
|
||||||
test-remote-cacher:
|
test-remote-cacher:
|
||||||
@echo "Running go test with $(GOTESTFLAGS) -tags '$(TEST_TAGS)'..."
|
@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
|
.PHONY: test-frontend
|
||||||
test-frontend: node_modules
|
test-frontend: node_modules
|
||||||
|
@ -549,7 +577,7 @@ test-check:
|
||||||
.PHONY: test\#%
|
.PHONY: test\#%
|
||||||
test\#%:
|
test\#%:
|
||||||
@echo "Running go test with -tags '$(TEST_TAGS)'..."
|
@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
|
.PHONY: coverage
|
||||||
coverage:
|
coverage:
|
||||||
|
@ -560,7 +588,7 @@ coverage:
|
||||||
.PHONY: unit-test-coverage
|
.PHONY: unit-test-coverage
|
||||||
unit-test-coverage:
|
unit-test-coverage:
|
||||||
@echo "Running unit-test-coverage $(GOTESTFLAGS) -tags '$(TEST_TAGS)'..."
|
@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
|
.PHONY: tidy
|
||||||
tidy:
|
tidy:
|
||||||
|
@ -581,7 +609,7 @@ tidy-check: tidy
|
||||||
go-licenses: $(GO_LICENSE_FILE)
|
go-licenses: $(GO_LICENSE_FILE)
|
||||||
|
|
||||||
$(GO_LICENSE_FILE): go.mod go.sum
|
$(GO_LICENSE_FILE): go.mod go.sum
|
||||||
-$(shell $(GO) env GOROOT)/bin/go run $(GO_LICENSES_PACKAGE) save . --force --save_path=$(GO_LICENSE_TMP_DIR) 2>/dev/null
|
-$(shell $(GO) env GOROOT)/bin/go run $(GO_LICENSES_PACKAGE) save . --force --ignore code.gitea.io/gitea --save_path=$(GO_LICENSE_TMP_DIR) 2>/dev/null
|
||||||
$(GO) run build/generate-go-licenses.go $(GO_LICENSE_TMP_DIR) $(GO_LICENSE_FILE)
|
$(GO) run build/generate-go-licenses.go $(GO_LICENSE_TMP_DIR) $(GO_LICENSE_FILE)
|
||||||
@rm -rf $(GO_LICENSE_TMP_DIR)
|
@rm -rf $(GO_LICENSE_TMP_DIR)
|
||||||
|
|
||||||
|
@ -593,11 +621,11 @@ generate-ini-sqlite:
|
||||||
|
|
||||||
.PHONY: test-sqlite
|
.PHONY: test-sqlite
|
||||||
test-sqlite: integrations.sqlite.test generate-ini-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\#%
|
.PHONY: test-sqlite\#%
|
||||||
test-sqlite\#%: integrations.sqlite.test generate-ini-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
|
.PHONY: test-sqlite-migration
|
||||||
test-sqlite-migration: migrations.sqlite.test migrations.individual.sqlite.test
|
test-sqlite-migration: migrations.sqlite.test migrations.individual.sqlite.test
|
||||||
|
@ -614,11 +642,11 @@ generate-ini-mysql:
|
||||||
|
|
||||||
.PHONY: test-mysql
|
.PHONY: test-mysql
|
||||||
test-mysql: integrations.mysql.test generate-ini-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\#%
|
.PHONY: test-mysql\#%
|
||||||
test-mysql\#%: integrations.mysql.test generate-ini-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
|
.PHONY: test-mysql-migration
|
||||||
test-mysql-migration: migrations.mysql.test migrations.individual.mysql.test
|
test-mysql-migration: migrations.mysql.test migrations.individual.mysql.test
|
||||||
|
@ -632,15 +660,16 @@ generate-ini-pgsql:
|
||||||
-e 's|{{REPO_TEST_DIR}}|${REPO_TEST_DIR}|g' \
|
-e 's|{{REPO_TEST_DIR}}|${REPO_TEST_DIR}|g' \
|
||||||
-e 's|{{TEST_LOGGER}}|$(or $(TEST_LOGGER),test$(COMMA)file)|g' \
|
-e 's|{{TEST_LOGGER}}|$(or $(TEST_LOGGER),test$(COMMA)file)|g' \
|
||||||
-e 's|{{TEST_TYPE}}|$(or $(TEST_TYPE),integration)|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
|
tests/pgsql.ini.tmpl > tests/pgsql.ini
|
||||||
|
|
||||||
.PHONY: test-pgsql
|
.PHONY: test-pgsql
|
||||||
test-pgsql: integrations.pgsql.test generate-ini-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\#%
|
.PHONY: test-pgsql\#%
|
||||||
test-pgsql\#%: integrations.pgsql.test generate-ini-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
|
.PHONY: test-pgsql-migration
|
||||||
test-pgsql-migration: migrations.pgsql.test migrations.individual.pgsql.test
|
test-pgsql-migration: migrations.pgsql.test migrations.individual.pgsql.test
|
||||||
|
@ -659,35 +688,34 @@ test-e2e: test-e2e-sqlite
|
||||||
|
|
||||||
.PHONY: test-e2e-sqlite
|
.PHONY: test-e2e-sqlite
|
||||||
test-e2e-sqlite: playwright e2e.sqlite.test generate-ini-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\#%
|
.PHONY: test-e2e-sqlite\#%
|
||||||
test-e2e-sqlite\#%: playwright e2e.sqlite.test generate-ini-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\#%
|
.PHONY: test-e2e-sqlite-firefox\#%
|
||||||
test-e2e-sqlite-firefox\#%: playwright e2e.sqlite.test generate-ini-sqlite
|
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
|
.PHONY: test-e2e-mysql
|
||||||
test-e2e-mysql: playwright e2e.mysql.test generate-ini-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\#%
|
.PHONY: test-e2e-mysql\#%
|
||||||
test-e2e-mysql\#%: playwright e2e.mysql.test generate-ini-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
|
.PHONY: test-e2e-pgsql
|
||||||
test-e2e-pgsql: playwright e2e.pgsql.test generate-ini-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\#%
|
.PHONY: test-e2e-pgsql\#%
|
||||||
test-e2e-pgsql\#%: playwright e2e.pgsql.test generate-ini-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
|
.PHONY: test-e2e-debugserver
|
||||||
test-e2e-debugserver: e2e.sqlite.test generate-ini-sqlite
|
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
|
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./e2e.sqlite.test -test.run TestDebugserver -test.timeout 24h
|
||||||
|
|
||||||
.PHONY: bench-sqlite
|
.PHONY: bench-sqlite
|
||||||
|
@ -711,77 +739,81 @@ 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
|
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./integrations.cover.sqlite.test -test.coverprofile=integration.coverage.out
|
||||||
|
|
||||||
integrations.mysql.test: git-check $(GO_SOURCES)
|
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)
|
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)
|
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)
|
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)
|
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
|
.PHONY: migrations.mysql.test
|
||||||
migrations.mysql.test: $(GO_SOURCES) generate-ini-mysql
|
migrations.mysql.test: $(GO_SOURCES) generate-ini-mysql
|
||||||
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration/migration-test -o 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 ./migrations.mysql.test
|
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini $(GOTESTCOMPILEDRUNPREFIX) ./migrations.mysql.test $(GOTESTCOMPILEDRUNSUFFIX)
|
||||||
|
|
||||||
.PHONY: migrations.pgsql.test
|
.PHONY: migrations.pgsql.test
|
||||||
migrations.pgsql.test: $(GO_SOURCES) generate-ini-pgsql
|
migrations.pgsql.test: $(GO_SOURCES) generate-ini-pgsql
|
||||||
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration/migration-test -o 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 ./migrations.pgsql.test
|
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini $(GOTESTCOMPILEDRUNPREFIX) ./migrations.pgsql.test $(GOTESTCOMPILEDRUNSUFFIX)
|
||||||
|
|
||||||
.PHONY: migrations.sqlite.test
|
.PHONY: migrations.sqlite.test
|
||||||
migrations.sqlite.test: $(GO_SOURCES) generate-ini-sqlite
|
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)'
|
$(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 ./migrations.sqlite.test
|
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini $(GOTESTCOMPILEDRUNPREFIX) ./migrations.sqlite.test $(GOTESTCOMPILEDRUNSUFFIX)
|
||||||
|
|
||||||
.PHONY: migrations.individual.mysql.test
|
.PHONY: migrations.individual.mysql.test
|
||||||
migrations.individual.mysql.test: $(GO_SOURCES)
|
migrations.individual.mysql.test: $(GO_SOURCES)
|
||||||
for pkg in $(MIGRATION_PACKAGES); do \
|
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
|
done
|
||||||
|
|
||||||
.PHONY: migrations.individual.sqlite.test\#%
|
.PHONY: migrations.individual.sqlite.test\#%
|
||||||
migrations.individual.sqlite.test\#%: $(GO_SOURCES) generate-ini-sqlite
|
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
|
.PHONY: migrations.individual.pgsql.test
|
||||||
migrations.individual.pgsql.test: $(GO_SOURCES)
|
migrations.individual.pgsql.test: $(GO_SOURCES)
|
||||||
for pkg in $(MIGRATION_PACKAGES); do \
|
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
|
done
|
||||||
|
|
||||||
.PHONY: migrations.individual.pgsql.test\#%
|
.PHONY: migrations.individual.pgsql.test\#%
|
||||||
migrations.individual.pgsql.test\#%: $(GO_SOURCES) generate-ini-pgsql
|
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
|
.PHONY: migrations.individual.sqlite.test
|
||||||
migrations.individual.sqlite.test: $(GO_SOURCES) generate-ini-sqlite
|
migrations.individual.sqlite.test: $(GO_SOURCES) generate-ini-sqlite
|
||||||
for pkg in $(MIGRATION_PACKAGES); do \
|
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
|
done
|
||||||
|
|
||||||
.PHONY: migrations.individual.sqlite.test\#%
|
.PHONY: migrations.individual.sqlite.test\#%
|
||||||
migrations.individual.sqlite.test\#%: $(GO_SOURCES) generate-ini-sqlite
|
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)
|
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)
|
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)
|
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
|
.PHONY: check
|
||||||
check: test
|
check: test
|
||||||
|
|
||||||
|
###
|
||||||
|
# Production / build targets
|
||||||
|
###
|
||||||
|
|
||||||
.PHONY: install $(TAGS_PREREQ)
|
.PHONY: install $(TAGS_PREREQ)
|
||||||
install: $(wildcard *.go)
|
install: $(wildcard *.go)
|
||||||
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) install -v -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)'
|
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) install -v -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)'
|
||||||
|
@ -811,10 +843,6 @@ generate-go: $(TAGS_PREREQ)
|
||||||
merge-locales:
|
merge-locales:
|
||||||
@echo "NOT NEEDED: THIS IS A NOOP AS OF Forgejo 7.0 BUT KEPT FOR BACKWARD COMPATIBILITY"
|
@echo "NOT NEEDED: THIS IS A NOOP AS OF Forgejo 7.0 BUT KEPT FOR BACKWARD COMPATIBILITY"
|
||||||
|
|
||||||
.PHONY: security-check
|
|
||||||
security-check:
|
|
||||||
go run $(GOVULNCHECK_PACKAGE) ./...
|
|
||||||
|
|
||||||
$(EXECUTABLE): $(GO_SOURCES) $(TAGS_PREREQ)
|
$(EXECUTABLE): $(GO_SOURCES) $(TAGS_PREREQ)
|
||||||
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) build $(GOFLAGS) $(EXTRA_GOFLAGS) -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)' -o $@
|
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) build $(GOFLAGS) $(EXTRA_GOFLAGS) -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)' -o $@
|
||||||
|
|
||||||
|
@ -836,9 +864,6 @@ $(DIST_DIRS):
|
||||||
.PHONY: release-windows
|
.PHONY: release-windows
|
||||||
release-windows: | $(DIST_DIRS)
|
release-windows: | $(DIST_DIRS)
|
||||||
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -buildmode exe -dest $(DIST)/binaries -tags 'osusergo $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets 'windows/*' -out gitea-$(VERSION) .
|
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -buildmode exe -dest $(DIST)/binaries -tags 'osusergo $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets 'windows/*' -out gitea-$(VERSION) .
|
||||||
ifeq (,$(findstring gogit,$(TAGS)))
|
|
||||||
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) run $(XGO_PACKAGE) -go $(XGO_VERSION) -buildmode exe -dest $(DIST)/binaries -tags 'osusergo gogit $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets 'windows/*' -out gitea-$(VERSION)-gogit .
|
|
||||||
endif
|
|
||||||
|
|
||||||
.PHONY: release-linux
|
.PHONY: release-linux
|
||||||
release-linux: | $(DIST_DIRS)
|
release-linux: | $(DIST_DIRS)
|
||||||
|
@ -881,6 +906,30 @@ release-sources: | $(DIST_DIRS)
|
||||||
release-docs: | $(DIST_DIRS) docs
|
release-docs: | $(DIST_DIRS) docs
|
||||||
tar -czf $(DIST)/release/gitea-docs-$(VERSION).tar.gz -C ./docs .
|
tar -czf $(DIST)/release/gitea-docs-$(VERSION).tar.gz -C ./docs .
|
||||||
|
|
||||||
|
.PHONY: reproduce-build
|
||||||
|
reproduce-build:
|
||||||
|
# Start building the Dockerfile with the RELEASE_VERSION tag set. GOPROXY is set
|
||||||
|
# for convience, because the default of the Dockerfile is `direct` which can be
|
||||||
|
# quite slow.
|
||||||
|
@docker build --build-arg="RELEASE_VERSION=$(RELEASE_VERSION)" --build-arg="GOPROXY=$(shell $(GO) env GOPROXY)" --tag "forgejo-reproducibility" .
|
||||||
|
@id=$$(docker create forgejo-reproducibility); \
|
||||||
|
docker cp $$id:/app/gitea/gitea ./forgejo; \
|
||||||
|
docker rm -v $$id; \
|
||||||
|
docker image rm forgejo-reproducibility:latest
|
||||||
|
|
||||||
|
.PHONY: reproduce-build\#%
|
||||||
|
reproduce-build\#%:
|
||||||
|
@git switch -d "$*"
|
||||||
|
# All the current variables are based on information before the git checkout happened.
|
||||||
|
# Call the makefile again, so these variables are correct and can be used for building
|
||||||
|
# a reproducible binary. Always execute git switch -, to go back to the previous branch.
|
||||||
|
@make reproduce-build; \
|
||||||
|
(code=$$?; git switch -; exit $${code})
|
||||||
|
|
||||||
|
###
|
||||||
|
# Dependency management
|
||||||
|
###
|
||||||
|
|
||||||
.PHONY: deps
|
.PHONY: deps
|
||||||
deps: deps-frontend deps-backend deps-tools deps-py
|
deps: deps-frontend deps-backend deps-tools deps-py
|
||||||
|
|
||||||
|
@ -957,16 +1006,6 @@ lockfile-check:
|
||||||
@git diff --exit-code --color=always package-lock.json \
|
@git diff --exit-code --color=always package-lock.json \
|
||||||
|| (code=$$?; echo "Please run 'npm install --package-lock-only' and commit the result"; exit $${code})
|
|| (code=$$?; echo "Please run 'npm install --package-lock-only' and commit the result"; exit $${code})
|
||||||
|
|
||||||
.PHONY: update-translations
|
|
||||||
update-translations:
|
|
||||||
mkdir -p ./translations
|
|
||||||
cd ./translations && curl -L https://crowdin.com/download/project/gitea.zip > gitea.zip && unzip gitea.zip
|
|
||||||
rm ./translations/gitea.zip
|
|
||||||
$(SED_INPLACE) -e 's/="/=/g' -e 's/"$$//g' ./translations/*.ini
|
|
||||||
$(SED_INPLACE) -e 's/\\"/"/g' ./translations/*.ini
|
|
||||||
mv ./translations/*.ini ./options/locale/
|
|
||||||
rmdir ./translations
|
|
||||||
|
|
||||||
.PHONY: generate-license
|
.PHONY: generate-license
|
||||||
generate-license:
|
generate-license:
|
||||||
$(GO) run build/generate-licenses.go
|
$(GO) run build/generate-licenses.go
|
||||||
|
@ -977,7 +1016,7 @@ generate-gitignore:
|
||||||
|
|
||||||
.PHONY: generate-gomock
|
.PHONY: generate-gomock
|
||||||
generate-gomock:
|
generate-gomock:
|
||||||
$(GO) run $(GOMOCK_PACKAGE) -package mock -destination ./modules/queue/mock/redisuniversalclient.go github.com/redis/go-redis/v9 UniversalClient
|
$(GO) run $(GOMOCK_PACKAGE) -package mock -destination ./modules/queue/mock/redisuniversalclient.go code.gitea.io/gitea/modules/nosql RedisClient
|
||||||
|
|
||||||
.PHONY: generate-images
|
.PHONY: generate-images
|
||||||
generate-images: | node_modules
|
generate-images: | node_modules
|
||||||
|
@ -992,11 +1031,6 @@ generate-manpage:
|
||||||
@gzip -9 man/man1/gitea.1 && echo man/man1/gitea.1.gz created
|
@gzip -9 man/man1/gitea.1 && echo man/man1/gitea.1.gz created
|
||||||
@#TODO A small script that formats config-cheat-sheet.en-us.md nicely for use as a config man page
|
@#TODO A small script that formats config-cheat-sheet.en-us.md nicely for use as a config man page
|
||||||
|
|
||||||
.PHONY: docker
|
|
||||||
docker:
|
|
||||||
docker build --disable-content-trust=false -t $(DOCKER_REF) .
|
|
||||||
# support also build args docker build --build-arg GITEA_VERSION=v1.2.3 --build-arg TAGS="bindata sqlite sqlite_unlock_notify" .
|
|
||||||
|
|
||||||
# This endif closes the if at the top of the file
|
# This endif closes the if at the top of the file
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
<img src="./assets/logo.svg" alt="" width="192" align="center" />
|
<img src="./assets/logo.svg" alt="" width="192" align="center" />
|
||||||
<h1 align="center">Welcome to Forgejo</h1>
|
<h1 align="center">Welcome to Forgejo</h1>
|
||||||
|
@ -41,6 +40,11 @@ If you like any of the following, Forgejo is literally meant for you:
|
||||||
|
|
||||||
Dive into the [documentation](https://forgejo.org/docs/latest/), subscribe to releases and blog post on [our website](https://forgejo.org), <a href="https://floss.social/@forgejo" rel="me">find us on the Fediverse</a> or hop into [our Matrix room](https://matrix.to/#/#forgejo-chat:matrix.org) if you have any questions or want to get involved.
|
Dive into the [documentation](https://forgejo.org/docs/latest/), subscribe to releases and blog post on [our website](https://forgejo.org), <a href="https://floss.social/@forgejo" rel="me">find us on the Fediverse</a> or hop into [our Matrix room](https://matrix.to/#/#forgejo-chat:matrix.org) if you have any questions or want to get involved.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Forgejo is distributed under the terms of the [GPL version 3.0](LICENSE) or any later version.
|
||||||
|
|
||||||
|
The agreement for this license [was documented in June 2023](https://codeberg.org/forgejo/governance/pulls/24) and implemented during the development of Forgejo v9.0. All Forgejo versions before v9.0 are distributed under the MIT license.
|
||||||
|
|
||||||
## Get involved
|
## Get involved
|
||||||
|
|
||||||
|
|
227
RELEASE-NOTES.md
227
RELEASE-NOTES.md
|
@ -4,79 +4,105 @@ A minor or major Forgejo release is published every [three months](https://forge
|
||||||
|
|
||||||
A [patch or minor release](https://semver.org/spec/v2.0.0.html) (e.g. upgrading from v7.0.0 to v7.0.1 or v7.1.0) does not require manual intervention. But [major releases](https://semver.org/spec/v2.0.0.html#spec-item-8) where the first version number changes (e.g. upgrading from v1.21 to v7.0) contain breaking changes and the release notes explain how to deal with them.
|
A [patch or minor release](https://semver.org/spec/v2.0.0.html) (e.g. upgrading from v7.0.0 to v7.0.1 or v7.1.0) does not require manual intervention. But [major releases](https://semver.org/spec/v2.0.0.html#spec-item-8) where the first version number changes (e.g. upgrading from v1.21 to v7.0) contain breaking changes and the release notes explain how to deal with them.
|
||||||
|
|
||||||
## Upcoming releases (not available yet)
|
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.0](release-notes/9.0.0/)
|
## 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).
|
||||||
|
|
||||||
|
## 8.0.2
|
||||||
|
|
||||||
|
The Forgejo v8.0.2 release notes are [available in the v8.0.2 milestone](https://codeberg.org/forgejo/forgejo/milestone/7728).
|
||||||
|
|
||||||
|
## 8.0.1
|
||||||
|
|
||||||
|
The Forgejo v8.0.1 release notes are [available in the v8.0.1 milestone](https://codeberg.org/forgejo/forgejo/milestone/7682).
|
||||||
|
|
||||||
## 8.0.0
|
## 8.0.0
|
||||||
|
|
||||||
A [companion blog post](https://forgejo.org/2024-07-release-v8-0/) provides additional context on this release. In addition to the pull requests listed below, you will find a complete list in the [v8.0 milestone](https://codeberg.org/forgejo/forgejo/milestone/6042).
|
A [companion blog post](https://forgejo.org/2024-07-release-v8-0/) provides additional context on this release. In addition to the pull requests listed below, you will find a complete list in the [v8.0 milestone](https://codeberg.org/forgejo/forgejo/milestone/6042).
|
||||||
|
|
||||||
|
- Two frontend features were removed because a license incompatibility was discovered. [Read more in the dedicated blog post](https://forgejo.org/2024-07-non-free-dependency-found/).
|
||||||
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4670): [Mermaid](https://mermaid.js.org/) rendering: `%%{init: {"flowchart": {"defaultRenderer": "elk"}} }%%` will now fail because [ELK](https://github.com/kieler/elkjs) is no longer included.
|
||||||
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4595): Repository citation: Removed the ability to export citations in APA format.
|
||||||
<!--start release-notes-assistant-->
|
<!--start release-notes-assistant-->
|
||||||
<!--URL:https://codeberg.org/forgejo/forgejo-->
|
<!--URL:https://codeberg.org/forgejo/forgejo-->
|
||||||
- **Breaking**
|
- **Breaking**
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3040)</a>: <!--number 3040 --><!--number--><!--description -->remove Microsoft SQL Server support see [the discussion](https://codeberg.org/forgejo/discussions/issues/122).<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3040): <!--number 3040 --><!--number--><!--description -->remove Microsoft SQL Server support see [the discussion](https://codeberg.org/forgejo/discussions/issues/122).<!--description-->
|
||||||
- **User interface features & enhancements**
|
- **User interface features & enhancements**
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4201)</a>: <!--number 4201 --><!--number--><!--description Make tooltip of Author label in comments more clear-->make the tooltip of the author label in comments clearer.<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4590) ([backported from](https://codeberg.org/forgejo/forgejo/pulls/4571)): <!--number 4590 --><!--number--><!--description -->Replace `vue-bar-graph` with `chart.js`<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4189)</a>: <!--number 4189 --><!--number--><!--description User profiles: only show RSS feed button and Public activity tab when the activity can be accessed, add messages about visibility-->only show the RSS feed button and Public activity tab in user profiles when the activity can be accessed and add messages about visibility.<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4201): <!--number 4201 --><!--number--><!--description Make tooltip of Author label in comments more clear-->make the tooltip of the author label in comments clearer.<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4139)</a>: <!--number 4139 --><!--number--><!--description reorder repo tabs for better UX: (i) `Actions` is now the last tab (ii) `Packages` are located after Releases (iii) this puts Projects after Pull requests. (tab positions may depend on which units are enabled in the repo).-->reorder repo tabs for better UX: (i) `Actions` is now the last tab (ii) `Packages` are located after Releases (iii) this puts Projects after Pull requests. (tab positions may depend on which units are enabled in the repo).<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4189): <!--number 4189 --><!--number--><!--description User profiles: only show RSS feed button and Public activity tab when the activity can be accessed, add messages about visibility-->only show the RSS feed button and Public activity tab in user profiles when the activity can be accessed and add messages about visibility.<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4134)</a>: <!--number 4134 --><!--number--><!--description Code Search results are now displayed in a foldable box-->code search results are now displayed in a foldable box.<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4139): <!--number 4139 --><!--number--><!--description reorder repo tabs for better UX: (i) `Actions` is now the last tab (ii) `Packages` are located after Releases (iii) this puts Projects after Pull requests. (tab positions may depend on which units are enabled in the repo).-->reorder repo tabs for better UX: (i) `Actions` is now the last tab (ii) `Packages` are located after Releases (iii) this puts Projects after Pull requests. (tab positions may depend on which units are enabled in the repo).<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4095)</a>: <!--number 4095 --><!--number--><!--description Disable Subscribe button for guest users.-->disable the `Subscribe` button for guest users.<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4134): <!--number 4134 --><!--number--><!--description Code Search results are now displayed in a foldable box-->code search results are now displayed in a foldable box.<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4072)</a>: <!--number 4072 --><!--number--><!--description multine placeholder-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4095): <!--number 4095 --><!--number--><!--description Disable Subscribe button for guest users.-->disable the `Subscribe` button for guest users.<!--description-->
|
||||||
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4072): <!--number 4072 --><!--number--><!--description multine placeholder-->
|
||||||
- Added Enter key handling to the new Markdown editor: Pressing Enter while in a list, quote or code block will copy the prefix to the new line - Ordered list index will be increased for the new line, and task list "checkbox" will be unchecked.
|
- Added Enter key handling to the new Markdown editor: Pressing Enter while in a list, quote or code block will copy the prefix to the new line - Ordered list index will be increased for the new line, and task list "checkbox" will be unchecked.
|
||||||
- Added indent/unindent function for a line or selection. Currently available as toolbar buttons ([#4263](https://codeberg.org/forgejo/forgejo/pulls/4263)).<!--description-->
|
- Added indent/unindent function for a line or selection. Currently available as toolbar buttons ([#4263](https://codeberg.org/forgejo/forgejo/pulls/4263)).<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3985)</a>: <!--number 3985 --><!--number--><!--description Added support for displaying images based on the users current color code by using an anchor of `#dark-mode-only` or `#light-mode-only` respectively. Also supporting the github variants (e.g. `#gh-dark-mode-only`).-->added support for displaying images based on the users current color code by using an anchor of `#dark-mode-only` or `#light-mode-only` respectively. Also supporting the github variants (e.g. `#gh-dark-mode-only`).<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3985): <!--number 3985 --><!--number--><!--description Added support for displaying images based on the users current color code by using an anchor of `#dark-mode-only` or `#light-mode-only` respectively. Also supporting the github variants (e.g. `#gh-dark-mode-only`).-->added support for displaying images based on the users current color code by using an anchor of `#dark-mode-only` or `#light-mode-only` respectively. Also supporting the github variants (e.g. `#gh-dark-mode-only`).<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3870)</a>: <!--number 3870 --><!--number--><!--description Use CSS-native pattern for image diff background, add dark theme support-->use CSS-native pattern for image diff background, add dark theme support.<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3870): <!--number 3870 --><!--number--><!--description Use CSS-native pattern for image diff background, add dark theme support-->use CSS-native pattern for image diff background, add dark theme support.<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3642)</a>: <!--number 3642 --><!--number--><!--description Allow navigating to the organization dashboard from the organization view-->allow navigating to the organization dashboard from the organization view.<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3642): <!--number 3642 --><!--number--><!--description Allow navigating to the organization dashboard from the organization view-->allow navigating to the organization dashboard from the organization view.<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3434)</a>: <!--number 3434 --><!--number--><!--description When PDFs are displayed in the repository, the [full height of the screen](https://codeberg.org/forgejo/forgejo/pulls/3434) is now used instead of a predefined fixed height-->when PDFs are displayed in the repository, the full height of the screen is now used instead of a predefined fixed height.<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3434): <!--number 3434 --><!--number--><!--description When PDFs are displayed in the repository, the [full height of the screen](https://codeberg.org/forgejo/forgejo/pulls/3434) is now used instead of a predefined fixed height-->when PDFs are displayed in the repository, the full height of the screen is now used instead of a predefined fixed height.<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3337)</a>: <!--number 3337 --><!--number--><!--description Added support for grouping of log-lines inside steps between the special `::group::{title}` and `::endgroup::` workflow commands. A runner of v3.4.2 or later is needed.-->added support for grouping of log-lines inside steps between the special `::group::{title}` and `::endgroup::` workflow commands. A runner of v3.4.2 or later is needed.<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3337): <!--number 3337 --><!--number--><!--description Added support for grouping of log-lines inside steps between the special `::group::{title}` and `::endgroup::` workflow commands. A runner of v3.4.2 or later is needed.-->added support for grouping of log-lines inside steps between the special `::group::{title}` and `::endgroup::` workflow commands. A runner of v3.4.2 or later is needed.<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3285)</a>: <!--number 3285 --><!--number--><!--description The default for `[repository].USE_COMPAT_SSH_URI` has been changed to `true`. With this change, Forgejo defaults to using the same URL style for SSH clone URLs as for HTTPS ones, instead of the former scp-style.-->the default for `[repository].USE_COMPAT_SSH_URI` has been changed to `true`. With this change, Forgejo defaults to using the same URL style for SSH clone URLs as for HTTPS ones, instead of the former scp-style.<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3285): <!--number 3285 --><!--number--><!--description The default for `[repository].USE_COMPAT_SSH_URI` has been changed to `true`. With this change, Forgejo defaults to using the same URL style for SSH clone URLs as for HTTPS ones, instead of the former scp-style.-->the default for `[repository].USE_COMPAT_SSH_URI` has been changed to `true`. With this change, Forgejo defaults to using the same URL style for SSH clone URLs as for HTTPS ones, instead of the former scp-style.<!--description-->
|
||||||
- **Features & Enhancements**
|
- **Features & Enhancements**
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4283)</a> ([backport](https://codeberg.org/forgejo/forgejo/pulls/4266)): <!--number 4283 --><!--number--><!--description - add support for LFS server implementations which have batch API responses in an older/deprecated schema-->add support for LFS server implementations which have batch API responses in an older/deprecated schema.<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4283) ([backported from](https://codeberg.org/forgejo/forgejo/pulls/4266)): <!--number 4283 --><!--number--><!--description - add support for LFS server implementations which have batch API responses in an older/deprecated schema-->add support for LFS server implementations which have batch API responses in an older/deprecated schema.<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4262)</a>: <!--number 4262 --><!--number--><!--description Introduced branch/tag dropdown in code search page if using git-grep.-->introduce a branch/tag dropdown in the code search page if using git-grep.<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4262): <!--number 4262 --><!--number--><!--description Introduced branch/tag dropdown in code search page if using git-grep.-->introduce a branch/tag dropdown in the code search page if using git-grep.<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4160)</a>: <!--number 4160 --><!--number--><!--description Added support for fuzzy searching issues and pulls - support for `/issues` and `/pulls` were ported from [`gitea#be5be0ac81`](https://github.com/go-gitea/gitea/commit/be5be0ac81ce50ad5adb079af6ca4e8c396aaece) - support for `/user/repo/issues` and `/user/repo/pulls` were added-->added support for fuzzy searching in `/user/repo/issues` and `/user/repo/pulls`.<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4160): <!--number 4160 --><!--number--><!--description Added support for fuzzy searching issues and pulls - support for `/issues` and `/pulls` were ported from [`gitea#be5be0ac81`](https://github.com/go-gitea/gitea/commit/be5be0ac81ce50ad5adb079af6ca4e8c396aaece) - support for `/user/repo/issues` and `/user/repo/pulls` were added-->added support for fuzzy searching in `/user/repo/issues` and `/user/repo/pulls`.<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4145)</a>: <!--number 4145 --><!--number--><!--description multine placeholder-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4145): <!--number 4145 --><!--number--><!--description multine placeholder-->
|
||||||
- feat(perf): [commit](https://codeberg.org/forgejo/forgejo/commit/358cd67c4f316f2d4f1d3be6dcb891dc04a2ff07) reduce memory usage for chunked artifact uploads to S3.
|
- feat(perf): [commit](https://codeberg.org/forgejo/forgejo/commit/358cd67c4f316f2d4f1d3be6dcb891dc04a2ff07) reduce memory usage for chunked artifact uploads to S3.
|
||||||
- feat: [commit](https://codeberg.org/forgejo/forgejo/commit/b60e3ac7b4aeeb9b8760f43eea9576c0e23309e9) allow downloading draft releases assets.
|
- feat: [commit](https://codeberg.org/forgejo/forgejo/commit/b60e3ac7b4aeeb9b8760f43eea9576c0e23309e9) allow downloading draft releases assets.
|
||||||
- feat: [commit](https://codeberg.org/forgejo/forgejo/commit/1fca15529ac8fefb60d86b0c1f4bec8dae9a8566) API endpoints for managing tag protection.
|
- feat: [commit](https://codeberg.org/forgejo/forgejo/commit/1fca15529ac8fefb60d86b0c1f4bec8dae9a8566) API endpoints for managing tag protection.
|
||||||
- feat: [commit](https://codeberg.org/forgejo/forgejo/commit/4334c705b5f9388b16af23c7e75a69d027d07d5e) extract and display readme and comments for Composer packages.
|
- feat: [commit](https://codeberg.org/forgejo/forgejo/commit/4334c705b5f9388b16af23c7e75a69d027d07d5e) extract and display readme and comments for Composer packages.
|
||||||
- fix: [commit](https://codeberg.org/forgejo/forgejo/commit/364922c6e4f28264add9e2501a352c25ad6a0993) when a repository is adopted, its object format is not set in the database.
|
- fix: [commit](https://codeberg.org/forgejo/forgejo/commit/364922c6e4f28264add9e2501a352c25ad6a0993) when a repository is adopted, its object format is not set in the database.
|
||||||
- fix: [commit](https://codeberg.org/forgejo/forgejo/commit/e7f332a55d6a48a3f3b4f2bfa43d18455ac00acc) during a migration from bitbucket, LFS downloads fail.<!--description-->
|
- fix: [commit](https://codeberg.org/forgejo/forgejo/commit/e7f332a55d6a48a3f3b4f2bfa43d18455ac00acc) during a migration from bitbucket, LFS downloads fail.<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4143)</a>: <!--number 4143 --><!--number--><!--description a help overlay, triggered by "?" key can be displayed when viewing [asciinema](https://asciinema.org/) files (.cast extension) and [SGR color sequence](https://github.com/asciinema/avt/issues/9) are supported.-->a help overlay, triggered by "?" key can be displayed when viewing [asciinema](https://asciinema.org/) files (.cast extension) and [SGR color sequence](https://github.com/asciinema/avt/issues/9) are supported.<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4143): <!--number 4143 --><!--number--><!--description a help overlay, triggered by "?" key can be displayed when viewing [asciinema](https://asciinema.org/) files (.cast extension) and [SGR color sequence](https://github.com/asciinema/avt/issues/9) are supported.-->a help overlay, triggered by "?" key can be displayed when viewing [asciinema](https://asciinema.org/) files (.cast extension) and [SGR color sequence](https://github.com/asciinema/avt/issues/9) are supported.<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4136)</a>: <!--number 4136 --><!--number--><!--description - strikethrough in markdown can be achieved with [a single ~ in addition to ~~](https://github.github.com/gfm/#strikethrough-extension-)-->strikethrough in markdown can be achieved with [a single ~ in addition to ~~](https://github.github.com/gfm/#strikethrough-extension-).<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4136): <!--number 4136 --><!--number--><!--description - strikethrough in markdown can be achieved with [a single ~ in addition to ~~](https://github.github.com/gfm/#strikethrough-extension-)-->strikethrough in markdown can be achieved with [a single ~ in addition to ~~](https://github.github.com/gfm/#strikethrough-extension-).<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4083)</a>: <!--number 4083 --><!--number--><!--description multine placeholder-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4083): <!--number 4083 --><!--number--><!--description multine placeholder-->
|
||||||
- feat: add [Reviewed-on and Reviewed-by variables](https://codeberg.org/forgejo/forgejo/commit/4ddd9af50fbfcfb2ebf629697a803b3bce56c4af) to the merge template.
|
- feat: add [Reviewed-on and Reviewed-by variables](https://codeberg.org/forgejo/forgejo/commit/4ddd9af50fbfcfb2ebf629697a803b3bce56c4af) to the merge template.
|
||||||
- feat(perf): [add the `[ui.csv].MAX_ROWS` setting](https://codeberg.org/forgejo/forgejo/commit/433b6c6910f8699dc41787ef8f5148b122b4677e) to avoid displaying a large number of lines (defaults to 2500).
|
- feat(perf): [add the `[ui.csv].MAX_ROWS` setting](https://codeberg.org/forgejo/forgejo/commit/433b6c6910f8699dc41787ef8f5148b122b4677e) to avoid displaying a large number of lines (defaults to 2500).
|
||||||
- feat: [add a setting to override or add headers of all outgoing emails](https://codeberg.org/forgejo/forgejo/commit/1d4bff4f65d5e4a3969871ef91d3612daf272b45), for instance `Reply-To` or `In-Reply-To`.<!--description-->
|
- feat: [add a setting to override or add headers of all outgoing emails](https://codeberg.org/forgejo/forgejo/commit/1d4bff4f65d5e4a3969871ef91d3612daf272b45), for instance `Reply-To` or `In-Reply-To`.<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4027)</a>: <!--number 4027 --><!--number--><!--description - Gitea/Forgejo webhook payload include additional fields (`html_url`, `additions`, `deletions`, `review_comments`...) for better compatbility with [OpenProject](https://www.openproject.org/), ported from [gitea#28435](https://github.com/go-gitea/gitea/pull/28435).-->the Gitea/Forgejo webhook payload includes additional fields (`html_url`, `additions`, `deletions`, `review_comments`...) for better compatbility with [OpenProject](https://www.openproject.org/).<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4027): <!--number 4027 --><!--number--><!--description - Gitea/Forgejo webhook payload include additional fields (`html_url`, `additions`, `deletions`, `review_comments`...) for better compatibility with [OpenProject](https://www.openproject.org/), ported from [gitea#28435](https://github.com/go-gitea/gitea/pull/28435).-->the Gitea/Forgejo webhook payload includes additional fields (`html_url`, `additions`, `deletions`, `review_comments`...) for better compatibility with [OpenProject](https://www.openproject.org/).<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4026)</a>: <!--number 4026 --><!--number--><!--description - when an OAuth grant request submitted to a Forgejo user is denied, the server from which the request originates is not notified that it has been denied-->when an OAuth grant request submitted to a Forgejo user is denied, the server from which the request originates is notified that it has been denied.<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4026): <!--number 4026 --><!--number--><!--description - when an OAuth grant request submitted to a Forgejo user is denied, the server from which the request originates is not notified that it has been denied-->when an OAuth grant request submitted to a Forgejo user is denied, the server from which the request originates is notified that it has been denied.<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3989)</a>: <!--number 3989 --><!--number--><!--description multine placeholder-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3989): <!--number 3989 --><!--number--><!--description multine placeholder-->
|
||||||
- feat: API endpoints that return a repository now [also include the topics](https://codeberg.org/forgejo/forgejo/commit/ee2247d77c0b13b0b45df704d7589b541db03899).
|
- feat: API endpoints that return a repository now [also include the topics](https://codeberg.org/forgejo/forgejo/commit/ee2247d77c0b13b0b45df704d7589b541db03899).
|
||||||
- feat: display an error when an issue comment is [edited simultaneously by two users](https://codeberg.org/forgejo/forgejo/commit/ca0921a95aa9a37d8820538458c15fd0a3b0c97c) instead of silently overriding one of them.
|
- feat: display an error when an issue comment is [edited simultaneously by two users](https://codeberg.org/forgejo/forgejo/commit/ca0921a95aa9a37d8820538458c15fd0a3b0c97c) instead of silently overriding one of them.
|
||||||
- feat: add [support for a credentials chain for minio](https://codeberg.org/forgejo/forgejo/commit/73706ae26d138684ef9da9e1164846a040fd4a7d).
|
- feat: add [support for a credentials chain for minio](https://codeberg.org/forgejo/forgejo/commit/73706ae26d138684ef9da9e1164846a040fd4a7d).
|
||||||
- feat(perf): improve performances when [retrieving pull requests via the API](https://codeberg.org/forgejo/forgejo/commit/47a2102694c47bc30a2a7c673c328471839ef206).<!--description-->
|
- feat(perf): improve performances when [retrieving pull requests via the API](https://codeberg.org/forgejo/forgejo/commit/47a2102694c47bc30a2a7c673c328471839ef206).<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3934)</a>: <!--number 3934 --><!--number--><!--description When installing Forgejo through the built-in installer, open (self-) registration is now disabled by default.-->when installing Forgejo through the built-in installer, open (self-) registration is now disabled by default.<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3934): <!--number 3934 --><!--number--><!--description When installing Forgejo through the built-in installer, open (self-) registration is now disabled by default.-->when installing Forgejo through the built-in installer, open (self-) registration is now disabled by default.<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3917)</a>: <!--number 3917 --><!--number--><!--description support [setting the default attribute of the issue template dropdown field](https://codeberg.org/forgejo/forgejo/commit/df15abd07264138fd07e003d0cf056f7da514b8f)-->support [setting the default attribute of the issue template dropdown field](https://codeberg.org/forgejo/forgejo/commit/df15abd07264138fd07e003d0cf056f7da514b8f)<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3917): <!--number 3917 --><!--number--><!--description support [setting the default attribute of the issue template dropdown field](https://codeberg.org/forgejo/forgejo/commit/df15abd07264138fd07e003d0cf056f7da514b8f)-->support [setting the default attribute of the issue template dropdown field](https://codeberg.org/forgejo/forgejo/commit/df15abd07264138fd07e003d0cf056f7da514b8f)<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3886)</a>: <!--number 3886 --><!--number--><!--description For federated-star we introduce a new repository setting to define following repositories. That is a workaround till we find a better way to express repository federation.-->For federated-star we introduce a new repository setting to define following repositories. That is a workaround till we find a better way to express repository federation.<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3886): <!--number 3886 --><!--number--><!--description For federated-star we introduce a new repository setting to define following repositories. That is a workaround till we find a better way to express repository federation.-->For federated-star we introduce a new repository setting to define following repositories. That is a workaround till we find a better way to express repository federation.<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3847)</a>: <!--number 3847 --><!--number--><!--description Basic wiki content search using git-grep. The search results include the first ten matched files. Only the first three matches per file are displayed.-->Basic wiki content search using git-grep. The search results include the first ten matched files. Only the first three matches per file are displayed.<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3847): <!--number 3847 --><!--number--><!--description Basic wiki content search using git-grep. The search results include the first ten matched files. Only the first three matches per file are displayed.-->Basic wiki content search using git-grep. The search results include the first ten matched files. Only the first three matches per file are displayed.<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3838)</a>: <!--number 3838 --><!--number--><!--description - [Support using label names when changing issue labels](https://codeberg.org/forgejo/forgejo/commit/8e1de85980f1e4ae05b240cafbf9eaf33c94a203)-->support using label names when changing issue labels.<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3838): <!--number 3838 --><!--number--><!--description - [Support using label names when changing issue labels](https://codeberg.org/forgejo/forgejo/commit/8e1de85980f1e4ae05b240cafbf9eaf33c94a203)-->support using label names when changing issue labels.<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3836)</a>: <!--number 3836 --><!--number--><!--description Parse prefix parameter from redis URI for queues and use that as prefix to keys-->parse prefix parameter from redis URI for queues and use that as prefix to keys.<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3836): <!--number 3836 --><!--number--><!--description Parse prefix parameter from redis URI for queues and use that as prefix to keys-->parse prefix parameter from redis URI for queues and use that as prefix to keys.<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3830)</a>: <!--number 3830 --><!--number--><!--description Neutralize delete runners' UUID to prevent collisions with new records-->neutralize delete runners' UUID to prevent collisions with new records.<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3830): <!--number 3830 --><!--number--><!--description Neutralize delete runners' UUID to prevent collisions with new records-->neutralize delete runners' UUID to prevent collisions with new records.<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3811)</a>: <!--number 3811 --><!--number--><!--description Implement a non-caching version of the [RubyGems compact API](https://guides.rubygems.org/rubygems-org-compact-index-api/) for bundler dependency resolution.-->implement a non-caching version of the [RubyGems compact API](https://guides.rubygems.org/rubygems-org-compact-index-api/) for bundler dependency resolution.<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3811): <!--number 3811 --><!--number--><!--description Implement a non-caching version of the [RubyGems compact API](https://guides.rubygems.org/rubygems-org-compact-index-api/) for bundler dependency resolution.-->implement a non-caching version of the [RubyGems compact API](https://guides.rubygems.org/rubygems-org-compact-index-api/) for bundler dependency resolution.<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3808)</a>: <!--number 3808 --><!--number--><!--description - Add support for the [reddit](https://github.com/markbates/goth/pull/523) and [Hubspot](https://github.com/markbates/goth/pull/531) OAuth providers.-->add support for the [reddit](https://github.com/markbates/goth/pull/523) and [Hubspot](https://github.com/markbates/goth/pull/531) OAuth providers.<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3808): <!--number 3808 --><!--number--><!--description - Add support for the [reddit](https://github.com/markbates/goth/pull/523) and [Hubspot](https://github.com/markbates/goth/pull/531) OAuth providers.-->add support for the [reddit](https://github.com/markbates/goth/pull/523) and [Hubspot](https://github.com/markbates/goth/pull/531) OAuth providers.<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3791)</a>: <!--number 3791 --><!--number--><!--description - when parsing [incoming emails](https://forgejo.org/docs/v8.0/user/incoming/), [remove tspecials from type/subtype](https://github.com/jhillyerd/enmime/pull/317). According to the RFC, content type and subtype cannot contain special characters and any such character will fail parsing. Removing the characters from the type/subtype can help successfully parsing the content type that contains some extra garbage.-->when parsing [incoming emails](https://forgejo.org/docs/v8.0/user/incoming/), [remove tspecials from type/subtype](https://github.com/jhillyerd/enmime/pull/317). According to the RFC, content type and subtype cannot contain special characters and any such character will fail parsing. Removing the characters from the type/subtype can help successfully parsing the content type that contains some extra garbage.<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3791): <!--number 3791 --><!--number--><!--description - when parsing [incoming emails](https://forgejo.org/docs/v8.0/user/incoming/), [remove tspecials from type/subtype](https://github.com/jhillyerd/enmime/pull/317). According to the RFC, content type and subtype cannot contain special characters and any such character will fail parsing. Removing the characters from the type/subtype can help successfully parsing the content type that contains some extra garbage.-->when parsing [incoming emails](https://forgejo.org/docs/v8.0/user/incoming/), [remove tspecials from type/subtype](https://github.com/jhillyerd/enmime/pull/317). According to the RFC, content type and subtype cannot contain special characters and any such character will fail parsing. Removing the characters from the type/subtype can help successfully parsing the content type that contains some extra garbage.<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3752)</a>: <!--number 3752 --><!--number--><!--description There are a couple of new configs to define the name of the instance. The more important is `APP_SLOGAN`. It permits to configure a slogan for the site and it is optional. The other is `APP_DISPLAY_NAME_FORMAT` and permits to customize the aspect of the full display name for the instance used in some parts of the UI as: (i) Title page, (ii) Homepage head title (ii) Open Graph site and title meta tags. Its default value is `APP_NAME: APP_SLOGAN`. The config `APP_DISPLAY_NAME_FORMAT` is used only if `APP_SLOGAN` is set otherwise the full display name shows only `APP_NAME` value.-->there are a couple of new configs to define the name of the instance. The more important is `APP_SLOGAN`. It permits to configure a slogan for the site and it is optional. The other is `APP_DISPLAY_NAME_FORMAT` and permits to customize the aspect of the full display name for the instance used in some parts of the UI as: (i) Title page, (ii) Homepage head title (ii) Open Graph site and title meta tags. Its default value is `APP_NAME: APP_SLOGAN`. The config `APP_DISPLAY_NAME_FORMAT` is used only if `APP_SLOGAN` is set otherwise the full display name shows only `APP_NAME` value.<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3752): <!--number 3752 --><!--number--><!--description There are a couple of new configs to define the name of the instance. The more important is `APP_SLOGAN`. It permits to configure a slogan for the site and it is optional. The other is `APP_DISPLAY_NAME_FORMAT` and permits to customize the aspect of the full display name for the instance used in some parts of the UI as: (i) Title page, (ii) Homepage head title (ii) Open Graph site and title meta tags. Its default value is `APP_NAME: APP_SLOGAN`. The config `APP_DISPLAY_NAME_FORMAT` is used only if `APP_SLOGAN` is set otherwise the full display name shows only `APP_NAME` value.-->there are a couple of new configs to define the name of the instance. The more important is `APP_SLOGAN`. It permits to configure a slogan for the site and it is optional. The other is `APP_DISPLAY_NAME_FORMAT` and permits to customize the aspect of the full display name for the instance used in some parts of the UI as: (i) Title page, (ii) Homepage head title (ii) Open Graph site and title meta tags. Its default value is `APP_NAME: APP_SLOGAN`. The config `APP_DISPLAY_NAME_FORMAT` is used only if `APP_SLOGAN` is set otherwise the full display name shows only `APP_NAME` value.<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3729)</a>: <!--number 3729 --><!--number--><!--description multine placeholder-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3729): <!--number 3729 --><!--number--><!--description multine placeholder-->
|
||||||
- feat: [commit](https://codeberg.org/forgejo/forgejo/commit/7028fe0b4d89c045b64ae891d2716e89965bc012): add actions-artifacts to the [storage migrate CLI](https://forgejo.org/docs/v8.0/admin/command-line/#migrate).
|
- feat: [commit](https://codeberg.org/forgejo/forgejo/commit/7028fe0b4d89c045b64ae891d2716e89965bc012): add actions-artifacts to the [storage migrate CLI](https://forgejo.org/docs/v8.0/admin/command-line/#migrate).
|
||||||
- fix: [commit](https://codeberg.org/forgejo/forgejo/commit/8f0f6bf89cdcd12cd4daa761aa259fdba7e32b50): pull request search shows closed pull requests in the open tab.<!--description-->
|
- fix: [commit](https://codeberg.org/forgejo/forgejo/commit/8f0f6bf89cdcd12cd4daa761aa259fdba7e32b50): pull request search shows closed pull requests in the open tab.<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3724)</a>: <!--number 3724 --><!--number--><!--description multine placeholder-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3724): <!--number 3724 --><!--number--><!--description multine placeholder-->
|
||||||
- [CERT management was improved](https://codeberg.org/forgejo/forgejo/pulls/3724) when [`ENABLE_ACME=true`](https://forgejo.org/docs/v7.0/admin/config-cheat-sheet/#server-server)
|
- [CERT management was improved](https://codeberg.org/forgejo/forgejo/pulls/3724) when [`ENABLE_ACME=true`](https://forgejo.org/docs/v7.0/admin/config-cheat-sheet/#server-server)
|
||||||
- Draft support for draft-03 of [ACME Renewal Information (ARI)](https://datatracker.ietf.org/doc/draft-ietf-acme-ari/) which assists with deciding when to renew certificates. This augments CertMagic's already-advanced logic using cert lifetime and OCSP/revocation status.
|
- Draft support for draft-03 of [ACME Renewal Information (ARI)](https://datatracker.ietf.org/doc/draft-ietf-acme-ari/) which assists with deciding when to renew certificates. This augments CertMagic's already-advanced logic using cert lifetime and OCSP/revocation status.
|
||||||
- New [`ZeroSSLIssuer`](https://pkg.go.dev/github.com/caddyserver/certmagic@v0.21.0#ZeroSSLIssuer) uses the [ZeroSSL API](https://zerossl.com/documentation/api/) to get certificates. ZeroSSL also has an ACME endpoint, which can still be accesed using the existing ACMEIssuer, as always. Their proprietary API is paid, but has extra features like IP certificates, better reliability, and support.
|
- New [`ZeroSSLIssuer`](https://pkg.go.dev/github.com/caddyserver/certmagic@v0.21.0#ZeroSSLIssuer) uses the [ZeroSSL API](https://zerossl.com/documentation/api/) to get certificates. ZeroSSL also has an ACME endpoint, which can still be accessed using the existing ACMEIssuer, as always. Their proprietary API is paid, but has extra features like IP certificates, better reliability, and support.
|
||||||
- DNS challenges should be smoother in some cases as we've improved propagation checking.
|
- DNS challenges should be smoother in some cases as we've improved propagation checking.
|
||||||
- In the odd case your ACME account disappears from the ACME server, CertMagic will automatically retry with a new account. (This happens in some test/dev environments.)
|
- In the odd case your ACME account disappears from the ACME server, CertMagic will automatically retry with a new account. (This happens in some test/dev environments.)
|
||||||
- ACME accounts are identified only by their public keys, but CertMagic maps accounts by CA+email for practical/storage reasons. So now you can "pin" an account key to use by specifying your email and the account public key in your config, which is useful if you need to absolutely be sure to use a specific account (like if you get rate limit exemptions from a CA).<!--description-->
|
- ACME accounts are identified only by their public keys, but CertMagic maps accounts by CA+email for practical/storage reasons. So now you can "pin" an account key to use by specifying your email and the account public key in your config, which is useful if you need to absolutely be sure to use a specific account (like if you get rate limit exemptions from a CA).<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3723)</a>: <!--number 3723 --><!--number--><!--description multine placeholder-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3723): <!--number 3723 --><!--number--><!--description multine placeholder-->
|
||||||
- With the go-enry upgrade to [v2.8.8](https://github.com/go-enry/go-enry/releases/tag/v2.8.8), language detection in the repository [now includes](https://github.com/github-linguist/linguist/releases/tag/v7.29.0):
|
- With the go-enry upgrade to [v2.8.8](https://github.com/go-enry/go-enry/releases/tag/v2.8.8), language detection in the repository [now includes](https://github.com/github-linguist/linguist/releases/tag/v7.29.0):
|
||||||
- New languages
|
- New languages
|
||||||
- [Roc](https://github.com/github-linguist/linguist/pull/6633)
|
- [Roc](https://github.com/github-linguist/linguist/pull/6633)
|
||||||
|
@ -95,43 +121,96 @@ A [companion blog post](https://forgejo.org/2024-07-release-v8-0/) provides addi
|
||||||
- [Add cs.pp extension to C#](https://github.com/github-linguist/linguist/pull/6679)
|
- [Add cs.pp extension to C#](https://github.com/github-linguist/linguist/pull/6679)
|
||||||
- [Add tmux.conf and .tmux.conf as shell filenames](https://github.com/github-linguist/linguist/pull/6726)
|
- [Add tmux.conf and .tmux.conf as shell filenames](https://github.com/github-linguist/linguist/pull/6726)
|
||||||
- [Add .env.sample as Dotenv filename](https://github.com/github-linguist/linguist/pull/6732)<!--description-->
|
- [Add .env.sample as Dotenv filename](https://github.com/github-linguist/linguist/pull/6732)<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3654)</a>: <!--number 3654 --><!--number--><!--description Code Search for non-default branches and tags when repository indexer is disabled-->support Code Search for non-default branches and tags when the repository indexer is disabled.<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3654): <!--number 3654 --><!--number--><!--description Code Search for non-default branches and tags when repository indexer is disabled-->support Code Search for non-default branches and tags when the repository indexer is disabled.<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3615)</a>: <!--number 3615 --><!--number--><!--description -->add an immutable tarball link to archive download headers for Nix.<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3615): <!--number 3615 --><!--number--><!--description -->add an immutable tarball link to archive download headers for Nix.<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3414)</a>: <!--number 3414 --><!--number--><!--description Allow to customize the domain name used as a fallback when synchronizing sources from ldap [`ldap: default domain name`](https://codeberg.org/forgejo/forgejo/pulls/3414)-->allow to customize the domain name used as a fallback when synchronizing sources from ldap default domain name.<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3414): <!--number 3414 --><!--number--><!--description Allow to customize the domain name used as a fallback when synchronizing sources from ldap [`ldap: default domain name`](https://codeberg.org/forgejo/forgejo/pulls/3414)-->allow to customize the domain name used as a fallback when synchronizing sources from ldap default domain name.<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3383)</a>: <!--number 3383 --><!--number--><!--description The default config for `database.MAX_OPEN_CONNS` changed from 0 (unlimited) to 100 to avoid problems if it exceeds the limit by the database server. If you require high concurrency, try to increase this value for both Forgejo **and your database server**. [`Limit database max connections by default`](https://codeberg.org/forgejo/forgejo/pulls/3383)-->the default config for `database.MAX_OPEN_CONNS` changed from 0 (unlimited) to 100 to avoid problems if it exceeds the limit by the database server. If you require high concurrency, try to increase this value for both Forgejo **and your database server**.<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3383): <!--number 3383 --><!--number--><!--description The default config for `database.MAX_OPEN_CONNS` changed from 0 (unlimited) to 100 to avoid problems if it exceeds the limit by the database server. If you require high concurrency, try to increase this value for both Forgejo **and your database server**. [`Limit database max connections by default`](https://codeberg.org/forgejo/forgejo/pulls/3383)-->the default config for `database.MAX_OPEN_CONNS` changed from 0 (unlimited) to 100 to avoid problems if it exceeds the limit by the database server. If you require high concurrency, try to increase this value for both Forgejo **and your database server**.<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3366)</a>: <!--number 3366 --><!--number--><!--description -->infer the `[email.incoming].PORT` setting from `.USE_TLS`.<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3366): <!--number 3366 --><!--number--><!--description -->infer the `[email.incoming].PORT` setting from `.USE_TLS`.<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3363)</a>: <!--number 3363 --><!--number--><!--description Reverted the rootless container image path in `GITEA_APP_INI` from `/etc/gitea/app.ini` to its default value of `/var/lib/gitea/custom/conf/app.ini`. This allows container users to not have to mount two separate volumes (one for the configuration data and one for the configuration `.ini` file). A warning is issued for users with the legacy configuration on how to update to the new path.-->reverted the rootless container image path in `GITEA_APP_INI` from `/etc/gitea/app.ini` to its default value of `/var/lib/gitea/custom/conf/app.ini`. This allows container users to not have to mount two separate volumes (one for the configuration data and one for the configuration `.ini` file). A warning is issued for users with the legacy configuration on how to update to the new path.<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3363): <!--number 3363 --><!--number--><!--description Reverted the rootless container image path in `GITEA_APP_INI` from `/etc/gitea/app.ini` to its default value of `/var/lib/gitea/custom/conf/app.ini`. This allows container users to not have to mount two separate volumes (one for the configuration data and one for the configuration `.ini` file). A warning is issued for users with the legacy configuration on how to update to the new path.-->reverted the rootless container image path in `GITEA_APP_INI` from `/etc/gitea/app.ini` to its default value of `/var/lib/gitea/custom/conf/app.ini`. This allows container users to not have to mount two separate volumes (one for the configuration data and one for the configuration `.ini` file). A warning is issued for users with the legacy configuration on how to update to the new path.<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3334)</a>: <!--number 3334 --><!--number--><!--description Added support for the `workflow_dispatch` workflow trigger-->added support for the [`workflow_dispatch` trigger](https://forgejo.org/docs/v8.0/user/actions/#onworkflow_dispatch) in Forgejo Actions.<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3334): <!--number 3334 --><!--number--><!--description Added support for the `workflow_dispatch` workflow trigger-->added support for the [`workflow_dispatch` trigger](https://forgejo.org/docs/v8.0/user/actions/#onworkflow_dispatch) in Forgejo Actions.<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3307)</a>: <!--number 3307 --><!--number--><!--description Support [Proof Key for Code Exchange (PKCE - RFC7636)](https://www.rfc-editor.org/rfc/rfc7636) for external login using the OpenID Connect authentication source.-->support [Proof Key for Code Exchange (PKCE - RFC7636)](https://www.rfc-editor.org/rfc/rfc7636) for external login using the OpenID Connect authentication source.<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3307): <!--number 3307 --><!--number--><!--description Support [Proof Key for Code Exchange (PKCE - RFC7636)](https://www.rfc-editor.org/rfc/rfc7636) for external login using the OpenID Connect authentication source.-->support [Proof Key for Code Exchange (PKCE - RFC7636)](https://www.rfc-editor.org/rfc/rfc7636) for external login using the OpenID Connect authentication source.<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3139)</a>: <!--number 3139 --><!--number--><!--description Allow hiding auto generated release archives-->allow hiding auto generated release archives.<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3139): <!--number 3139 --><!--number--><!--description Allow hiding auto generated release archives-->allow hiding auto generated release archives.<!--description-->
|
||||||
- **Bug fixes**
|
- **Bug fixes**
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4423)</a> ([backport](https://codeberg.org/forgejo/forgejo/pulls/4375)): <!--number 4423 --><!--number--><!--description the "View command line instructions" link in pull requests and the "Copy content" button in file editor are not accessible-->Fixed: the "View command line instructions" link in pull requests and the "Copy content" button in file editor are not accessible.<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4732) ([backported from](https://codeberg.org/forgejo/forgejo/pulls/4715)): <!--number 4732 --><!--number--><!--description -->Show the AGit label on merged pull requests.<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4288)</a> ([backport](https://codeberg.org/forgejo/forgejo/pulls/4253)): <!--number 4288 --><!--number--><!--description - unknown git push options are rejected instead of being ignored-->Fixed: unknown git push options are rejected instead of being ignored.<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4689) ([backported from](https://codeberg.org/forgejo/forgejo/pulls/4687)): <!--number 4689 --><!--number--><!--description -->Fixed: issue state change via the API is not idempotent.<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4240)</a>: <!--number 4240 --><!--number--><!--description - markdown `[*[a]*](b)` [is incorrectly rendered as `<p><a href="b"><em>[a]</em></a></p>`](https://github.com/yuin/goldmark/issues/457)-->Fixed: markdown `[*[a]*](b)` [is incorrectly rendered as `<p><a href="b"><em>[a]</em></a></p>`](https://github.com/yuin/goldmark/issues/457).<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4547) ([backported from](https://codeberg.org/forgejo/forgejo/pulls/4546)): <!--number 4547 --><!--number--><!--description The milestone section in the sidebar on the issue and pull request page now uses HTMX. If you update the milestone of a issue or pull request it will no longer reload the whole page and instead update the current page with the new information about the milestone update. This should provide a smoother user experience.-->The milestone section in the sidebar on the issue and pull request page now uses HTMX. If you update the milestone of a issue or pull request it will no longer reload the whole page and instead update the current page with the new information about the milestone update. This should provide a smoother user experience.<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4222)</a>: <!--number 4222 --><!--number--><!--description - markdown files displayed in the UI that have an unescaped backtick in the image alt [could (accidentally) trigger an inline code](https://github.com/yuin/goldmark/issues/456)-->Fixed: markdown files displayed in the UI that have an unescaped backtick in the image alt [could (accidentally) trigger an inline code](https://github.com/yuin/goldmark/issues/456).<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4402) ([backported from](https://codeberg.org/forgejo/forgejo/pulls/4382)): <!--number 4402 --><!--number--><!--description -->Fix mobile UI for organisation creation.<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3562)</a>: <!--number 3562 --><!--number--><!--description -->Fixed: when the git repository is empty, it is not possible to unsubscribe from an issue.<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4621) ([backported from](https://codeberg.org/forgejo/forgejo/pulls/4618)): <!--number 4621 --><!--number--><!--description -->Fixes: Forgejo Actions does not trigger an edited event when the title of an issue or pull request is changed.<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3442)</a>: <!--number 3442 --><!--number--><!--description Save updated empty comments instead of skipping the update silently, [which prevented the removal of attachments of such comments](https://codeberg.org/forgejo/forgejo/issues/3424).-->Fixed: it is not possible to remove attachments from an empty comment.<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4529) ([backported from](https://codeberg.org/forgejo/forgejo/pulls/4523)): <!--number 4529 --><!--number--><!--description -->Load attachments for `/issues/comments/{id}`.<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3430)</a>: <!--number 3430 --><!--number--><!--description Fixed a bug where the `/api/v1/repos/{owner}/{repo}/wiki` API endpoints were using a hardcoded "master" branch for the wiki, rather than the branch they really use.-->Fixed: the `/api/v1/repos/{owner}/{repo}/wiki` API endpoints is using a hardcoded "master" branch for the wiki, rather than the branch they really use.<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4423) ([backported from](https://codeberg.org/forgejo/forgejo/pulls/4375)): <!--number 4423 --><!--number--><!--description the "View command line instructions" link in pull requests and the "Copy content" button in file editor are not accessible-->Fixed: the "View command line instructions" link in pull requests and the "Copy content" button in file editor are not accessible.<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3379)</a>: <!--number 3379 --><!--number--><!--description -->Fixed: using the API to search for users, the results are not paged by default an the default paging limits are not respected.<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4380) ([backported from](https://codeberg.org/forgejo/forgejo/pulls/4377)): <!--number 4380 --><!--number--><!--description -->Use correct SHA in `GetCommitPullRequest`<!--description-->
|
||||||
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4288) ([backported from](https://codeberg.org/forgejo/forgejo/pulls/4253)): <!--number 4288 --><!--number--><!--description - unknown git push options are rejected instead of being ignored-->Fixed: unknown git push options are rejected instead of being ignored.<!--description-->
|
||||||
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4240): <!--number 4240 --><!--number--><!--description - markdown `[*[a]*](b)` [is incorrectly rendered as `<p><a href="b"><em>[a]</em></a></p>`](https://github.com/yuin/goldmark/issues/457)-->Fixed: markdown `[*[a]*](b)` [is incorrectly rendered as `<p><a href="b"><em>[a]</em></a></p>`](https://github.com/yuin/goldmark/issues/457).<!--description-->
|
||||||
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4222): <!--number 4222 --><!--number--><!--description - markdown files displayed in the UI that have an unescaped backtick in the image alt [could (accidentally) trigger an inline code](https://github.com/yuin/goldmark/issues/456)-->Fixed: markdown files displayed in the UI that have an unescaped backtick in the image alt [could (accidentally) trigger an inline code](https://github.com/yuin/goldmark/issues/456).<!--description-->
|
||||||
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3562): <!--number 3562 --><!--number--><!--description -->Fixed: when the git repository is empty, it is not possible to unsubscribe from an issue.<!--description-->
|
||||||
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3442): <!--number 3442 --><!--number--><!--description Save updated empty comments instead of skipping the update silently, [which prevented the removal of attachments of such comments](https://codeberg.org/forgejo/forgejo/issues/3424).-->Fixed: it is not possible to remove attachments from an empty comment.<!--description-->
|
||||||
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3430): <!--number 3430 --><!--number--><!--description Fixed a bug where the `/api/v1/repos/{owner}/{repo}/wiki` API endpoints were using a hardcoded "master" branch for the wiki, rather than the branch they really use.-->Fixed: the `/api/v1/repos/{owner}/{repo}/wiki` API endpoints is using a hardcoded "master" branch for the wiki, rather than the branch they really use.<!--description-->
|
||||||
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3379): <!--number 3379 --><!--number--><!--description -->Fixed: using the API to search for users, the results are not paged by default an the default paging limits are not respected.<!--description-->
|
||||||
- **Localization**
|
- **Localization**
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4445)</a> ([backport](https://codeberg.org/forgejo/forgejo/pulls/4330)): <!--number 4445 --><!--number--><!--description -->11 July updates<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4661) ([backported from](https://codeberg.org/forgejo/forgejo/pulls/4568)): <!--number 4661 --><!--number--><!--description -->24 July updates<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4316)</a> ([backport](https://codeberg.org/forgejo/forgejo/pulls/4251)): <!--number 4316 --><!--number--><!--description -->4 July updates<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4565) ([backported from](https://codeberg.org/forgejo/forgejo/pulls/4451)): <!--number 4565 --><!--number--><!--description -->19 July updates<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4168)</a>: <!--number 4168 --><!--number--><!--description -->18 June updates<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4445) ([backported from](https://codeberg.org/forgejo/forgejo/pulls/4330)): <!--number 4445 --><!--number--><!--description -->11 July updates<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4098)</a>: <!--number 4098 --><!--number--><!--description -->10 June updates<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4316) ([backported from](https://codeberg.org/forgejo/forgejo/pulls/4251)): <!--number 4316 --><!--number--><!--description -->4 July updates<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3992)</a>: <!--number 3992 --><!--number--><!--description -->2 June updates<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4168): <!--number 4168 --><!--number--><!--description -->18 June updates<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3908)</a>: <!--number 3908 --><!--number--><!--description -->25 May updates<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4098): <!--number 4098 --><!--number--><!--description -->10 June updates<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3851)</a>: <!--number 3851 --><!--number--><!--description -->20 May updates<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3992): <!--number 3992 --><!--number--><!--description -->2 June updates<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3759)</a>: <!--number 3759 --><!--number--><!--description -->14 May updates<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3908): <!--number 3908 --><!--number--><!--description -->25 May updates<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3637)</a>: <!--number 3637 --><!--number--><!--description -->5 May updates<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3851): <!--number 3851 --><!--number--><!--description -->20 May updates<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3508)</a>: <!--number 3508 --><!--number--><!--description -->28 April updates<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3759): <!--number 3759 --><!--number--><!--description -->14 May updates<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3359)</a>: <!--number 3359 --><!--number--><!--description -->22 April updates<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3637): <!--number 3637 --><!--number--><!--description -->5 May updates<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3244)</a>: <!--number 3244 --><!--number--><!--description -->15 April updates<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3508): <!--number 3508 --><!--number--><!--description -->28 April updates<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3138)</a>: <!--number 3138 --><!--number--><!--description -->10 April updates<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3359): <!--number 3359 --><!--number--><!--description -->22 April updates<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3064)</a>: <!--number 3064 --><!--number--><!--description -->5 April updates<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3244): <!--number 3244 --><!--number--><!--description -->15 April updates<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/2982)</a>: <!--number 2982 --><!--number--><!--description -->3 April updates<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3138): <!--number 3138 --><!--number--><!--description -->10 April updates<!--description-->
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/2937)</a>: <!--number 2937 --><!--number--><!--description -->31 March updates<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/3064): <!--number 3064 --><!--number--><!--description -->5 April updates<!--description-->
|
||||||
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/2982): <!--number 2982 --><!--number--><!--description -->3 April updates<!--description-->
|
||||||
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/2937): <!--number 2937 --><!--number--><!--description -->31 March updates<!--description-->
|
||||||
<!--end release-notes-assistant-->
|
<!--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).
|
||||||
|
|
||||||
|
## 7.0.8
|
||||||
|
|
||||||
|
The Forgejo v7.0.8 release notes are [available in the v7.0.8 milestone](https://codeberg.org/forgejo/forgejo/milestone/7729).
|
||||||
|
|
||||||
|
## 7.0.7
|
||||||
|
|
||||||
|
The Forgejo v7.0.7 release notes are [available in the v7.0.7 milestone](https://codeberg.org/forgejo/forgejo/milestone/7683).
|
||||||
|
|
||||||
|
## 7.0.6
|
||||||
|
|
||||||
|
This is a bug fix release. See the documentation for more information on the [upgrade procedure](https://forgejo.org/docs/v7.0/admin/upgrade/). In addition to the pull requests listed below, you will find a complete list in the [v7.0.6 milestone](https://codeberg.org/forgejo/forgejo/milestone/7252).
|
||||||
|
|
||||||
|
- Two frontend features were removed because a license incompatibility was discovered. [Read more in the companion blog post](https://forgejo.org/2024-07-non-free-dependency-found/).
|
||||||
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4679) ([backported from](https://codeberg.org/forgejo/forgejo/pulls/4670)): <!--number 4679 --><!--line 0 --><!--description W0NIT1JFXSBEb24ndCBidW5kbGUgYGVsa2pzYA==-->[Mermaid](https://mermaid.js.org/) rendering: `%%{init: {"flowchart": {"defaultRenderer": "elk"}} }%%` will now fail because [ELK](https://github.com/kieler/elkjs) is no longer included.<!--description-->
|
||||||
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4600) ([backported from](https://codeberg.org/forgejo/forgejo/pulls/4595)): <!--number 4600 --><!--line 0 --><!--description UmVwb3NpdG9yeSBjaXRhdGlvbjogUmVtb3ZlZCB0aGUgYWJpbGl0eSB0byBleHBvcnQgY2l0YXRpb25zIGluIEFQQSBmb3JtYXQuIFtSZWFkIG1vcmUgaW4gdGhlIGNvbXBhbmlvbiBibG9nIHBvc3RdKGh0dHBzOi8vZm9yZ2Vqby5vcmcvMjAyNC0wNy1ub24tZnJlZS1kZXBlbmRlbmN5LWZvdW5kLyk=-->Repository citation: Removed the ability to export citations in APA format.<!--description-->
|
||||||
|
- **User Interface bug fixes**
|
||||||
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4593) ([backported from](https://codeberg.org/forgejo/forgejo/pulls/4571)): <!--number 4593 --><!--line 0 --><!--description UmVwbGFjZSBgdnVlLWJhci1ncmFwaGAgd2l0aCBgY2hhcnQuanNg-->Replace `vue-bar-graph` with `chart.js`<!--description-->
|
||||||
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4731) ([backported from](https://codeberg.org/forgejo/forgejo/pulls/4715)): <!--number 4731 --><!--line 0 --><!--description U2hvdyBBR2l0IGxhYmVsIG9uIG1lcmdlZCBQUg==-->Show AGit label on merged PR<!--description-->
|
||||||
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4424) ([backported from](https://codeberg.org/forgejo/forgejo/pulls/4382)): <!--number 4424 --><!--line 0 --><!--description Rml4IG1vYmlsZSBVSSBmb3Igb3JnYW5pc2F0aW9uIGNyZWF0aW9u-->Fix mobile UI for organisation creation<!--description-->
|
||||||
|
- **Bug fixes**
|
||||||
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4688) ([backported from](https://codeberg.org/forgejo/forgejo/pulls/4687)): <!--number 4688 --><!--line 0 --><!--description Zml4KGFwaSk6IGlzc3VlIHN0YXRlIGNoYW5nZSBpcyBub3QgaWRlbXBvdGVudA==-->fix(api): issue state change is not idempotent<!--description-->
|
||||||
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4647) ([backported from](https://codeberg.org/forgejo/forgejo/pulls/4638)): <!--number 4647 --><!--line 0 --><!--description UmVzZXJ2ZSB0aGUgYGRldnRlc3RgIHVzZXJuYW1l-->Reserve the `devtest` username<!--description-->
|
||||||
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4620) ([backported from](https://codeberg.org/forgejo/forgejo/pulls/4618)): <!--number 4620 --><!--line 0 --><!--description Zml4KGFjdGlvbnMpOiBubyBlZGl0ZWQgZXZlbnQgdHJpZ2dlcmVkIHdoZW4gYSB0aXRsZSBpcyBjaGFuZ2Vk-->fix(actions): no edited event triggered when a title is changed<!--description-->
|
||||||
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4528) ([backported from](https://codeberg.org/forgejo/forgejo/pulls/4523)): <!--number 4528 --><!--line 0 --><!--description TG9hZCBhdHRhY2htZW50cyBmb3IgYC9pc3N1ZXMvY29tbWVudHMve2lkfWA=-->Load attachments for `/issues/comments/{id}`<!--description-->
|
||||||
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4526) ([backported from](https://codeberg.org/forgejo/forgejo/pulls/3379)): <!--number 4526 --><!--line 0 --><!--description V2hlbiBzZWFyY2hpbmcgZm9yIHVzZXJzLCBwYWdlIHRoZSByZXN1bHRzIGJ5IGRlZmF1bHQsIGFuZCByZXNwZWN0IHRoZSBkZWZhdWx0IHBhZ2luZyBsaW1pdHM=-->When searching for users, page the results by default, and respect the default paging limits<!--description-->
|
||||||
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4422) ([backported from](https://codeberg.org/forgejo/forgejo/pulls/4375)): <!--number 4422 --><!--line 0 --><!--description dGhlICJWaWV3IGNvbW1hbmQgbGluZSBpbnN0cnVjdGlvbnMiIGxpbmsgaW4gcHVsbCByZXF1ZXN0cyBhbmQgdGhlICJDb3B5IGNvbnRlbnQiIGJ1dHRvbiBpbiBmaWxlIGVkaXRvciBhcmUgbm90IGFjY2Vzc2libGU=-->the "View command line instructions" link in pull requests and the "Copy content" button in file editor are not accessible<!--description-->
|
||||||
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4379) ([backported from](https://codeberg.org/forgejo/forgejo/pulls/4377)): <!--number 4379 --><!--line 0 --><!--description VXNlIGNvcnJlY3QgU0hBIGluIGBHZXRDb21taXRQdWxsUmVxdWVzdGA=-->Use correct SHA in `GetCommitPullRequest`<!--description-->
|
||||||
|
- Localization
|
||||||
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4594) ([backported from](https://codeberg.org/forgejo/forgejo/pulls/4451)): <!--number 4594 --><!--line 0 --><!--description VXBkYXRlIG9mIHRyYW5zbGF0aW9ucyBmcm9tIFdlYmxhdGU=-->Update of translations from Weblate<!--description-->
|
||||||
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4447): <!--number 4447 --><!--line 0 --><!--description VXBkYXRlIG9mIHRyYW5zbGF0aW9ucyBmcm9tIFdlYmxhdGU=-->Update of translations from Weblate<!--description-->
|
||||||
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/4420) ([backported from](https://codeberg.org/forgejo/forgejo/pulls/4098)): <!--number 4420 --><!--line 0 --><!--description MyB0cmFuc2xhdGlvbiB1cGRhdGVzIGZyb20gV2VibGF0ZQ==-->3 translation updates from Weblate - [PR 1](https://codeberg.org/forgejo/forgejo/pulls/4098), [PR 2](https://codeberg.org/forgejo/forgejo/pulls/4168), [PR 3](https://codeberg.org/forgejo/forgejo/pulls/4251)<!--description-->
|
||||||
|
|
||||||
## 7.0.5
|
## 7.0.5
|
||||||
|
|
||||||
This is a security release. See the documentation for more information on the [upgrade procedure](https://forgejo.org/docs/v7.0/admin/upgrade/).
|
This is a security release. See the documentation for more information on the [upgrade procedure](https://forgejo.org/docs/v7.0/admin/upgrade/).
|
||||||
|
@ -2182,7 +2261,7 @@ This stable release includes a security fix for `git` and bug fixes.
|
||||||
|
|
||||||
### Git
|
### Git
|
||||||
|
|
||||||
Git [recently announced](https://github.blog/2023-02-14-git-security-vulnerabilities-announced-3/) new versions to address two CVEs ([CVE-2023-22490](https://cve.circl.lu/cve/CVE-2023-22490), [CVE-2023-23946](https://cve.circl.lu/cve/CVE-2023-23946)). On 14 Februrary 2023, Git published the maintenance release v2.39.2, together with releases for older maintenance tracks v2.38.4, v2.37.6, v2.36.5, v2.35.7, v2.34.7, v2.33.7, v2.32.6, v2.31.7, and v2.30.8. All major GNU/Linux distributions also provide updated packages via their security update channels.
|
Git [recently announced](https://github.blog/2023-02-14-git-security-vulnerabilities-announced-3/) new versions to address two CVEs ([CVE-2023-22490](https://cve.circl.lu/cve/CVE-2023-22490), [CVE-2023-23946](https://cve.circl.lu/cve/CVE-2023-23946)). On 14 February 2023, Git published the maintenance release v2.39.2, together with releases for older maintenance tracks v2.38.4, v2.37.6, v2.36.5, v2.35.7, v2.34.7, v2.33.7, v2.32.6, v2.31.7, and v2.30.8. All major GNU/Linux distributions also provide updated packages via their security update channels.
|
||||||
|
|
||||||
We recommend that all installations running a version affected by the issues described below are upgraded to the latest version as soon as possible.
|
We recommend that all installations running a version affected by the issues described below are upgraded to the latest version as soon as possible.
|
||||||
|
|
||||||
|
|
141
assets/go-licenses.json
generated
141
assets/go-licenses.json
generated
File diff suppressed because one or more lines are too long
|
@ -7,6 +7,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestFormatImportsSimple(t *testing.T) {
|
func TestFormatImportsSimple(t *testing.T) {
|
||||||
|
@ -29,7 +30,7 @@ import (
|
||||||
)
|
)
|
||||||
`
|
`
|
||||||
|
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, expected, string(formatted))
|
assert.Equal(t, expected, string(formatted))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +93,7 @@ import (
|
||||||
)
|
)
|
||||||
`
|
`
|
||||||
|
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, expected, string(formatted))
|
assert.Equal(t, expected, string(formatted))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,5 +121,5 @@ import (
|
||||||
"image/gif"
|
"image/gif"
|
||||||
)
|
)
|
||||||
`))
|
`))
|
||||||
assert.ErrorIs(t, err, errInvalidCommentBetweenImports)
|
require.ErrorIs(t, err, errInvalidCommentBetweenImports)
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,8 +53,6 @@ func (e Emoji) MarshalJSON() ([]byte, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
var err error
|
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
// generate data
|
// generate data
|
||||||
|
@ -83,8 +81,6 @@ var replacer = strings.NewReplacer(
|
||||||
var emojiRE = regexp.MustCompile(`\{Emoji:"([^"]*)"`)
|
var emojiRE = regexp.MustCompile(`\{Emoji:"([^"]*)"`)
|
||||||
|
|
||||||
func generate() ([]byte, error) {
|
func generate() ([]byte, error) {
|
||||||
var err error
|
|
||||||
|
|
||||||
// load gemoji data
|
// load gemoji data
|
||||||
res, err := http.Get(gemojiURL)
|
res, err := http.Get(gemojiURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -77,6 +77,20 @@ func main() {
|
||||||
sort.Strings(paths)
|
sort.Strings(paths)
|
||||||
|
|
||||||
var entries []LicenseEntry
|
var entries []LicenseEntry
|
||||||
|
|
||||||
|
{
|
||||||
|
licenseText, err := os.ReadFile("LICENSE")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
entries = append(entries, LicenseEntry{
|
||||||
|
Name: "codeberg.org/forgejo/forgejo",
|
||||||
|
Path: "codeberg.org/forgejo/forgejo/GPL-3.0-or-later",
|
||||||
|
LicenseText: string(licenseText),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
for _, filePath := range paths {
|
for _, filePath := range paths {
|
||||||
licenseText, err := os.ReadFile(filePath)
|
licenseText, err := os.ReadFile(filePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
156
build/lint-locale.go
Normal file
156
build/lint-locale.go
Normal 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
65
build/lint-locale_test.go
Normal 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 \x1b[0m\x1b[32m\u00a0\x1b[0m"}, checkLocaleContent([]byte(`key = و `)))
|
||||||
|
})
|
||||||
|
}
|
|
@ -386,7 +386,7 @@ func (a *authService) addLdapSimpleAuth(c *cli.Context) error {
|
||||||
return a.createAuthSource(ctx, authSource)
|
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 {
|
func (a *authService) updateLdapSimpleAuth(c *cli.Context) error {
|
||||||
ctx, cancel := installSignals()
|
ctx, cancel := installSignals()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"code.gitea.io/gitea/services/auth/source/ldap"
|
"code.gitea.io/gitea/services/auth/source/ldap"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -234,7 +235,7 @@ func TestAddLdapBindDn(t *testing.T) {
|
||||||
if c.errMsg != "" {
|
if c.errMsg != "" {
|
||||||
assert.EqualError(t, err, c.errMsg, "case %d: error should match", n)
|
assert.EqualError(t, err, c.errMsg, "case %d: error should match", n)
|
||||||
} else {
|
} else {
|
||||||
assert.NoError(t, err, "case %d: should have no errors", n)
|
require.NoError(t, err, "case %d: should have no errors", n)
|
||||||
assert.Equal(t, c.source, createdAuthSource, "case %d: wrong authSource", n)
|
assert.Equal(t, c.source, createdAuthSource, "case %d: wrong authSource", n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -465,7 +466,7 @@ func TestAddLdapSimpleAuth(t *testing.T) {
|
||||||
if c.errMsg != "" {
|
if c.errMsg != "" {
|
||||||
assert.EqualError(t, err, c.errMsg, "case %d: error should match", n)
|
assert.EqualError(t, err, c.errMsg, "case %d: error should match", n)
|
||||||
} else {
|
} else {
|
||||||
assert.NoError(t, err, "case %d: should have no errors", n)
|
require.NoError(t, err, "case %d: should have no errors", n)
|
||||||
assert.Equal(t, c.authSource, createdAuthSource, "case %d: wrong authSource", n)
|
assert.Equal(t, c.authSource, createdAuthSource, "case %d: wrong authSource", n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -928,7 +929,7 @@ func TestUpdateLdapBindDn(t *testing.T) {
|
||||||
if c.errMsg != "" {
|
if c.errMsg != "" {
|
||||||
assert.EqualError(t, err, c.errMsg, "case %d: error should match", n)
|
assert.EqualError(t, err, c.errMsg, "case %d: error should match", n)
|
||||||
} else {
|
} else {
|
||||||
assert.NoError(t, err, "case %d: should have no errors", n)
|
require.NoError(t, err, "case %d: should have no errors", n)
|
||||||
assert.Equal(t, c.authSource, updatedAuthSource, "case %d: wrong authSource", n)
|
assert.Equal(t, c.authSource, updatedAuthSource, "case %d: wrong authSource", n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1318,7 +1319,7 @@ func TestUpdateLdapSimpleAuth(t *testing.T) {
|
||||||
if c.errMsg != "" {
|
if c.errMsg != "" {
|
||||||
assert.EqualError(t, err, c.errMsg, "case %d: error should match", n)
|
assert.EqualError(t, err, c.errMsg, "case %d: error should match", n)
|
||||||
} else {
|
} else {
|
||||||
assert.NoError(t, err, "case %d: should have no errors", n)
|
require.NoError(t, err, "case %d: should have no errors", n)
|
||||||
assert.Equal(t, c.authSource, updatedAuthSource, "case %d: wrong authSource", n)
|
assert.Equal(t, c.authSource, updatedAuthSource, "case %d: wrong authSource", n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/services/doctor"
|
"code.gitea.io/gitea/services/doctor"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -25,9 +25,9 @@ func TestDoctorRun(t *testing.T) {
|
||||||
app := cli.NewApp()
|
app := cli.NewApp()
|
||||||
app.Commands = []*cli.Command{cmdDoctorCheck}
|
app.Commands = []*cli.Command{cmdDoctorCheck}
|
||||||
err := app.Run([]string{"./gitea", "check", "--run", "test-check"})
|
err := app.Run([]string{"./gitea", "check", "--run", "test-check"})
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = app.Run([]string{"./gitea", "check", "--run", "no-such"})
|
err = app.Run([]string{"./gitea", "check", "--run", "no-such"})
|
||||||
assert.ErrorContains(t, err, `unknown checks: "no-such"`)
|
require.ErrorContains(t, err, `unknown checks: "no-such"`)
|
||||||
err = app.Run([]string{"./gitea", "check", "--run", "test-check,no-such"})
|
err = app.Run([]string{"./gitea", "check", "--run", "test-check,no-such"})
|
||||||
assert.ErrorContains(t, err, `unknown checks: "no-such"`)
|
require.ErrorContains(t, err, `unknown checks: "no-such"`)
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/storage"
|
"code.gitea.io/gitea/modules/storage"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
|
||||||
"gitea.com/go-chi/session"
|
"code.forgejo.org/go-chi/session"
|
||||||
"github.com/mholt/archiver/v3"
|
"github.com/mholt/archiver/v3"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
|
|
||||||
"github.com/mholt/archiver/v3"
|
"github.com/mholt/archiver/v3"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
type mockArchiver struct {
|
type mockArchiver struct {
|
||||||
|
@ -35,20 +36,20 @@ func TestAddRecursiveExclude(t *testing.T) {
|
||||||
archiver := &mockArchiver{}
|
archiver := &mockArchiver{}
|
||||||
|
|
||||||
err := addRecursiveExclude(archiver, "", dir, []string{}, false)
|
err := addRecursiveExclude(archiver, "", dir, []string{}, false)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Empty(t, archiver.addedFiles)
|
assert.Empty(t, archiver.addedFiles)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Single file", func(t *testing.T) {
|
t.Run("Single file", func(t *testing.T) {
|
||||||
dir := t.TempDir()
|
dir := t.TempDir()
|
||||||
err := os.WriteFile(dir+"/example", nil, 0o666)
|
err := os.WriteFile(dir+"/example", nil, 0o666)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
t.Run("No exclude", func(t *testing.T) {
|
t.Run("No exclude", func(t *testing.T) {
|
||||||
archiver := &mockArchiver{}
|
archiver := &mockArchiver{}
|
||||||
|
|
||||||
err = addRecursiveExclude(archiver, "", dir, nil, false)
|
err = addRecursiveExclude(archiver, "", dir, nil, false)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Len(t, archiver.addedFiles, 1)
|
assert.Len(t, archiver.addedFiles, 1)
|
||||||
assert.Contains(t, archiver.addedFiles, "example")
|
assert.Contains(t, archiver.addedFiles, "example")
|
||||||
})
|
})
|
||||||
|
@ -57,7 +58,7 @@ func TestAddRecursiveExclude(t *testing.T) {
|
||||||
archiver := &mockArchiver{}
|
archiver := &mockArchiver{}
|
||||||
|
|
||||||
err = addRecursiveExclude(archiver, "", dir, []string{dir + "/example"}, false)
|
err = addRecursiveExclude(archiver, "", dir, []string{dir + "/example"}, false)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Empty(t, archiver.addedFiles)
|
assert.Empty(t, archiver.addedFiles)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -65,17 +66,17 @@ func TestAddRecursiveExclude(t *testing.T) {
|
||||||
t.Run("File inside directory", func(t *testing.T) {
|
t.Run("File inside directory", func(t *testing.T) {
|
||||||
dir := t.TempDir()
|
dir := t.TempDir()
|
||||||
err := os.MkdirAll(dir+"/deep/nested/folder", 0o750)
|
err := os.MkdirAll(dir+"/deep/nested/folder", 0o750)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = os.WriteFile(dir+"/deep/nested/folder/example", nil, 0o666)
|
err = os.WriteFile(dir+"/deep/nested/folder/example", nil, 0o666)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = os.WriteFile(dir+"/deep/nested/folder/another-file", nil, 0o666)
|
err = os.WriteFile(dir+"/deep/nested/folder/another-file", nil, 0o666)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
t.Run("No exclude", func(t *testing.T) {
|
t.Run("No exclude", func(t *testing.T) {
|
||||||
archiver := &mockArchiver{}
|
archiver := &mockArchiver{}
|
||||||
|
|
||||||
err = addRecursiveExclude(archiver, "", dir, nil, false)
|
err = addRecursiveExclude(archiver, "", dir, nil, false)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Len(t, archiver.addedFiles, 5)
|
assert.Len(t, archiver.addedFiles, 5)
|
||||||
assert.Contains(t, archiver.addedFiles, "deep")
|
assert.Contains(t, archiver.addedFiles, "deep")
|
||||||
assert.Contains(t, archiver.addedFiles, "deep/nested")
|
assert.Contains(t, archiver.addedFiles, "deep/nested")
|
||||||
|
@ -88,7 +89,7 @@ func TestAddRecursiveExclude(t *testing.T) {
|
||||||
archiver := &mockArchiver{}
|
archiver := &mockArchiver{}
|
||||||
|
|
||||||
err = addRecursiveExclude(archiver, "", dir, []string{dir + "/deep"}, false)
|
err = addRecursiveExclude(archiver, "", dir, []string{dir + "/deep"}, false)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Empty(t, archiver.addedFiles)
|
assert.Empty(t, archiver.addedFiles)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -96,7 +97,7 @@ func TestAddRecursiveExclude(t *testing.T) {
|
||||||
archiver := &mockArchiver{}
|
archiver := &mockArchiver{}
|
||||||
|
|
||||||
err = addRecursiveExclude(archiver, "", dir, []string{dir + "/deep/nested/folder"}, false)
|
err = addRecursiveExclude(archiver, "", dir, []string{dir + "/deep/nested/folder"}, false)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Len(t, archiver.addedFiles, 2)
|
assert.Len(t, archiver.addedFiles, 2)
|
||||||
assert.Contains(t, archiver.addedFiles, "deep")
|
assert.Contains(t, archiver.addedFiles, "deep")
|
||||||
assert.Contains(t, archiver.addedFiles, "deep/nested")
|
assert.Contains(t, archiver.addedFiles, "deep/nested")
|
||||||
|
@ -106,7 +107,7 @@ func TestAddRecursiveExclude(t *testing.T) {
|
||||||
archiver := &mockArchiver{}
|
archiver := &mockArchiver{}
|
||||||
|
|
||||||
err = addRecursiveExclude(archiver, "", dir, []string{dir + "/deep/nested/folder/example"}, false)
|
err = addRecursiveExclude(archiver, "", dir, []string{dir + "/deep/nested/folder/example"}, false)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Len(t, archiver.addedFiles, 4)
|
assert.Len(t, archiver.addedFiles, 4)
|
||||||
assert.Contains(t, archiver.addedFiles, "deep")
|
assert.Contains(t, archiver.addedFiles, "deep")
|
||||||
assert.Contains(t, archiver.addedFiles, "deep/nested")
|
assert.Contains(t, archiver.addedFiles, "deep/nested")
|
||||||
|
|
|
@ -86,6 +86,11 @@ func SubcmdActionsRegister(ctx context.Context) *cli.Command {
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "comma separated list of labels supported by the runner (e.g. docker,ubuntu-latest,self-hosted) (not required since v1.21)",
|
Usage: "comma separated list of labels supported by the runner (e.g. docker,ubuntu-latest,self-hosted) (not required since v1.21)",
|
||||||
},
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "keep-labels",
|
||||||
|
Value: false,
|
||||||
|
Usage: "do not affect the labels when updating an existing runner",
|
||||||
|
},
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "name",
|
Name: "name",
|
||||||
Value: "runner",
|
Value: "runner",
|
||||||
|
@ -133,6 +138,17 @@ func validateSecret(secret string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getLabels(cliCtx *cli.Context) (*[]string, error) {
|
||||||
|
if !cliCtx.Bool("keep-labels") {
|
||||||
|
lblValue := strings.Split(cliCtx.String("labels"), ",")
|
||||||
|
return &lblValue, nil
|
||||||
|
}
|
||||||
|
if cliCtx.String("labels") != "" {
|
||||||
|
return nil, fmt.Errorf("--labels and --keep-labels should not be used together")
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
func RunRegister(ctx context.Context, cliCtx *cli.Context) error {
|
func RunRegister(ctx context.Context, cliCtx *cli.Context) error {
|
||||||
var cancel context.CancelFunc
|
var cancel context.CancelFunc
|
||||||
if !ContextGetNoInit(ctx) {
|
if !ContextGetNoInit(ctx) {
|
||||||
|
@ -153,9 +169,12 @@ func RunRegister(ctx context.Context, cliCtx *cli.Context) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
scope := cliCtx.String("scope")
|
scope := cliCtx.String("scope")
|
||||||
labels := cliCtx.String("labels")
|
|
||||||
name := cliCtx.String("name")
|
name := cliCtx.String("name")
|
||||||
version := cliCtx.String("version")
|
version := cliCtx.String("version")
|
||||||
|
labels, err := getLabels(cliCtx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// There are two kinds of tokens
|
// There are two kinds of tokens
|
||||||
|
@ -179,7 +198,7 @@ func RunRegister(ctx context.Context, cliCtx *cli.Context) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
runner, err := actions_model.RegisterRunner(ctx, owner, repo, secret, strings.Split(labels, ","), name, version)
|
runner, err := actions_model.RegisterRunner(ctx, owner, repo, secret, labels, name, version)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error while registering runner: %v", err)
|
return fmt.Errorf("error while registering runner: %v", err)
|
||||||
}
|
}
|
||||||
|
|
88
cmd/forgejo/actions_test.go
Normal file
88
cmd/forgejo/actions_test.go
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
// Copyright The Forgejo Authors.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package forgejo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/services/context"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestActions_getLabels(t *testing.T) {
|
||||||
|
type testCase struct {
|
||||||
|
args []string
|
||||||
|
hasLabels bool
|
||||||
|
hasError bool
|
||||||
|
labels []string
|
||||||
|
}
|
||||||
|
type resultType struct {
|
||||||
|
labels *[]string
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
cases := []testCase{
|
||||||
|
{
|
||||||
|
args: []string{"x"},
|
||||||
|
hasLabels: true,
|
||||||
|
hasError: false,
|
||||||
|
labels: []string{""},
|
||||||
|
}, {
|
||||||
|
args: []string{"x", "--labels", "a,b"},
|
||||||
|
hasLabels: true,
|
||||||
|
hasError: false,
|
||||||
|
labels: []string{"a", "b"},
|
||||||
|
}, {
|
||||||
|
args: []string{"x", "--keep-labels"},
|
||||||
|
hasLabels: false,
|
||||||
|
hasError: false,
|
||||||
|
}, {
|
||||||
|
args: []string{"x", "--keep-labels", "--labels", "a,b"},
|
||||||
|
hasLabels: false,
|
||||||
|
hasError: true,
|
||||||
|
}, {
|
||||||
|
// this edge-case exists because that's what actually happens
|
||||||
|
// when no '--labels ...' options are present
|
||||||
|
args: []string{"x", "--keep-labels", "--labels", ""},
|
||||||
|
hasLabels: false,
|
||||||
|
hasError: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
flags := SubcmdActionsRegister(context.Context{}).Flags
|
||||||
|
for _, c := range cases {
|
||||||
|
t.Run(fmt.Sprintf("args: %v", c.args), func(t *testing.T) {
|
||||||
|
// Create a copy of command to test
|
||||||
|
var result *resultType
|
||||||
|
app := cli.NewApp()
|
||||||
|
app.Flags = flags
|
||||||
|
app.Action = func(ctx *cli.Context) error {
|
||||||
|
labels, err := getLabels(ctx)
|
||||||
|
result = &resultType{labels, err}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run it
|
||||||
|
_ = app.Run(c.args)
|
||||||
|
|
||||||
|
// Test the results
|
||||||
|
require.NotNil(t, result)
|
||||||
|
if c.hasLabels {
|
||||||
|
assert.NotNil(t, result.labels)
|
||||||
|
assert.Equal(t, c.labels, *result.labels)
|
||||||
|
} else {
|
||||||
|
assert.Nil(t, result.labels)
|
||||||
|
}
|
||||||
|
if c.hasError {
|
||||||
|
require.Error(t, result.err)
|
||||||
|
} else {
|
||||||
|
assert.NoError(t, result.err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 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 {
|
func runHookPostReceive(c *cli.Context) error {
|
||||||
|
@ -535,14 +536,14 @@ Forgejo or set your environment appropriately.`, "")
|
||||||
|
|
||||||
index := bytes.IndexByte(rs.Data, byte(0))
|
index := bytes.IndexByte(rs.Data, byte(0))
|
||||||
if index >= len(rs.Data) {
|
if index >= len(rs.Data) {
|
||||||
return fail(ctx, "Protocol: format error", "pkt-line: format error "+fmt.Sprint(rs.Data))
|
return fail(ctx, "Protocol: format error", "pkt-line: format error %s", rs.Data)
|
||||||
}
|
}
|
||||||
|
|
||||||
if index < 0 {
|
if index < 0 {
|
||||||
if len(rs.Data) == 10 && rs.Data[9] == '\n' {
|
if len(rs.Data) == 10 && rs.Data[9] == '\n' {
|
||||||
index = 9
|
index = 9
|
||||||
} else {
|
} else {
|
||||||
return fail(ctx, "Protocol: format error", "pkt-line: format error "+fmt.Sprint(rs.Data))
|
return fail(ctx, "Protocol: format error", "pkt-line: format error %s", rs.Data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,66 +48,66 @@ func TestPktLine(t *testing.T) {
|
||||||
s := strings.NewReader("0000")
|
s := strings.NewReader("0000")
|
||||||
r := bufio.NewReader(s)
|
r := bufio.NewReader(s)
|
||||||
result, err := readPktLine(ctx, r, pktLineTypeFlush)
|
result, err := readPktLine(ctx, r, pktLineTypeFlush)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, pktLineTypeFlush, result.Type)
|
assert.Equal(t, pktLineTypeFlush, result.Type)
|
||||||
|
|
||||||
s = strings.NewReader("0006a\n")
|
s = strings.NewReader("0006a\n")
|
||||||
r = bufio.NewReader(s)
|
r = bufio.NewReader(s)
|
||||||
result, err = readPktLine(ctx, r, pktLineTypeData)
|
result, err = readPktLine(ctx, r, pktLineTypeData)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, pktLineTypeData, result.Type)
|
assert.Equal(t, pktLineTypeData, result.Type)
|
||||||
assert.Equal(t, []byte("a\n"), result.Data)
|
assert.Equal(t, []byte("a\n"), result.Data)
|
||||||
|
|
||||||
s = strings.NewReader("0004")
|
s = strings.NewReader("0004")
|
||||||
r = bufio.NewReader(s)
|
r = bufio.NewReader(s)
|
||||||
result, err = readPktLine(ctx, r, pktLineTypeData)
|
result, err = readPktLine(ctx, r, pktLineTypeData)
|
||||||
assert.Error(t, err)
|
require.Error(t, err)
|
||||||
assert.Nil(t, result)
|
assert.Nil(t, result)
|
||||||
|
|
||||||
data := strings.Repeat("x", 65516)
|
data := strings.Repeat("x", 65516)
|
||||||
r = bufio.NewReader(strings.NewReader("fff0" + data))
|
r = bufio.NewReader(strings.NewReader("fff0" + data))
|
||||||
result, err = readPktLine(ctx, r, pktLineTypeData)
|
result, err = readPktLine(ctx, r, pktLineTypeData)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, pktLineTypeData, result.Type)
|
assert.Equal(t, pktLineTypeData, result.Type)
|
||||||
assert.Equal(t, []byte(data), result.Data)
|
assert.Equal(t, []byte(data), result.Data)
|
||||||
|
|
||||||
r = bufio.NewReader(strings.NewReader("fff1a"))
|
r = bufio.NewReader(strings.NewReader("fff1a"))
|
||||||
result, err = readPktLine(ctx, r, pktLineTypeData)
|
result, err = readPktLine(ctx, r, pktLineTypeData)
|
||||||
assert.Error(t, err)
|
require.Error(t, err)
|
||||||
assert.Nil(t, result)
|
assert.Nil(t, result)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Write", func(t *testing.T) {
|
t.Run("Write", func(t *testing.T) {
|
||||||
w := bytes.NewBuffer([]byte{})
|
w := bytes.NewBuffer([]byte{})
|
||||||
err := writeFlushPktLine(ctx, w)
|
err := writeFlushPktLine(ctx, w)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, []byte("0000"), w.Bytes())
|
assert.Equal(t, []byte("0000"), w.Bytes())
|
||||||
|
|
||||||
w.Reset()
|
w.Reset()
|
||||||
err = writeDataPktLine(ctx, w, []byte("a\nb"))
|
err = writeDataPktLine(ctx, w, []byte("a\nb"))
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, []byte("0007a\nb"), w.Bytes())
|
assert.Equal(t, []byte("0007a\nb"), w.Bytes())
|
||||||
|
|
||||||
w.Reset()
|
w.Reset()
|
||||||
data := bytes.Repeat([]byte{0x05}, 288)
|
data := bytes.Repeat([]byte{0x05}, 288)
|
||||||
err = writeDataPktLine(ctx, w, data)
|
err = writeDataPktLine(ctx, w, data)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, append([]byte("0124"), data...), w.Bytes())
|
assert.Equal(t, append([]byte("0124"), data...), w.Bytes())
|
||||||
|
|
||||||
w.Reset()
|
w.Reset()
|
||||||
err = writeDataPktLine(ctx, w, nil)
|
err = writeDataPktLine(ctx, w, nil)
|
||||||
assert.Error(t, err)
|
require.Error(t, err)
|
||||||
assert.Empty(t, w.Bytes())
|
assert.Empty(t, w.Bytes())
|
||||||
|
|
||||||
w.Reset()
|
w.Reset()
|
||||||
data = bytes.Repeat([]byte{0x64}, 65516)
|
data = bytes.Repeat([]byte{0x64}, 65516)
|
||||||
err = writeDataPktLine(ctx, w, data)
|
err = writeDataPktLine(ctx, w, data)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, append([]byte("fff0"), data...), w.Bytes())
|
assert.Equal(t, append([]byte("fff0"), data...), w.Bytes())
|
||||||
|
|
||||||
w.Reset()
|
w.Reset()
|
||||||
err = writeDataPktLine(ctx, w, bytes.Repeat([]byte{0x64}, 65516+1))
|
err = writeDataPktLine(ctx, w, bytes.Repeat([]byte{0x64}, 65516+1))
|
||||||
assert.Error(t, err)
|
require.Error(t, err)
|
||||||
assert.Empty(t, w.Bytes())
|
assert.Empty(t, w.Bytes())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -117,7 +117,7 @@ func TestDelayWriter(t *testing.T) {
|
||||||
defer test.MockVariableValue(&setting.InternalToken, "Random")()
|
defer test.MockVariableValue(&setting.InternalToken, "Random")()
|
||||||
defer test.MockVariableValue(&setting.InstallLock, true)()
|
defer test.MockVariableValue(&setting.InstallLock, true)()
|
||||||
defer test.MockVariableValue(&setting.Git.VerbosePush, true)()
|
defer test.MockVariableValue(&setting.Git.VerbosePush, true)()
|
||||||
require.NoError(t, os.Setenv("SSH_ORIGINAL_COMMAND", "true"))
|
t.Setenv("SSH_ORIGINAL_COMMAND", "true")
|
||||||
|
|
||||||
// Setup the Stdin.
|
// Setup the Stdin.
|
||||||
f, err := os.OpenFile(t.TempDir()+"/stdin", os.O_RDWR|os.O_CREATE|os.O_EXCL, 0o666)
|
f, err := os.OpenFile(t.TempDir()+"/stdin", os.O_RDWR|os.O_CREATE|os.O_EXCL, 0o666)
|
||||||
|
@ -174,23 +174,30 @@ func TestRunHookUpdate(t *testing.T) {
|
||||||
|
|
||||||
err := app.Run([]string{"./forgejo", "update", "refs/pull/1/head", "0a51ae26bc73c47e2f754560c40904cf14ed51a9", "0000000000000000000000000000000000000000"})
|
err := app.Run([]string{"./forgejo", "update", "refs/pull/1/head", "0a51ae26bc73c47e2f754560c40904cf14ed51a9", "0000000000000000000000000000000000000000"})
|
||||||
out := finish()
|
out := finish()
|
||||||
assert.Error(t, err)
|
require.Error(t, err)
|
||||||
|
|
||||||
assert.Contains(t, out, "The deletion of refs/pull/1/head is skipped as it's an internal reference.")
|
assert.Contains(t, out, "The deletion of refs/pull/1/head is skipped as it's an internal reference.")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Update of internal reference", func(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"})
|
err := app.Run([]string{"./forgejo", "update", "refs/pull/1/head", "0a51ae26bc73c47e2f754560c40904cf14ed51a9", "0000000000000000000000000000000000000001"})
|
||||||
assert.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) {
|
t.Run("Removal of branch", func(t *testing.T) {
|
||||||
err := app.Run([]string{"./forgejo", "update", "refs/head/main", "0a51ae26bc73c47e2f754560c40904cf14ed51a9", "0000000000000000000000000000000000000000"})
|
err := app.Run([]string{"./forgejo", "update", "refs/head/main", "0a51ae26bc73c47e2f754560c40904cf14ed51a9", "0000000000000000000000000000000000000000"})
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Not enough arguments", func(t *testing.T) {
|
t.Run("Not enough arguments", func(t *testing.T) {
|
||||||
err := app.Run([]string{"./forgejo", "update"})
|
err := app.Run([]string{"./forgejo", "update"})
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/test"
|
"code.gitea.io/gitea/modules/test"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -141,7 +142,7 @@ func TestCliCmd(t *testing.T) {
|
||||||
}
|
}
|
||||||
args := strings.Split(c.cmd, " ") // for test only, "split" is good enough
|
args := strings.Split(c.cmd, " ") // for test only, "split" is good enough
|
||||||
r, err := runTestApp(app, args...)
|
r, err := runTestApp(app, args...)
|
||||||
assert.NoError(t, err, c.cmd)
|
require.NoError(t, err, c.cmd)
|
||||||
assert.NotEmpty(t, c.exp, c.cmd)
|
assert.NotEmpty(t, c.exp, c.cmd)
|
||||||
assert.Contains(t, r.Stdout, c.exp, c.cmd)
|
assert.Contains(t, r.Stdout, c.exp, c.cmd)
|
||||||
}
|
}
|
||||||
|
@ -150,28 +151,28 @@ func TestCliCmd(t *testing.T) {
|
||||||
func TestCliCmdError(t *testing.T) {
|
func TestCliCmdError(t *testing.T) {
|
||||||
app := newTestApp(func(ctx *cli.Context) error { return fmt.Errorf("normal error") })
|
app := newTestApp(func(ctx *cli.Context) error { return fmt.Errorf("normal error") })
|
||||||
r, err := runTestApp(app, "./gitea", "test-cmd")
|
r, err := runTestApp(app, "./gitea", "test-cmd")
|
||||||
assert.Error(t, err)
|
require.Error(t, err)
|
||||||
assert.Equal(t, 1, r.ExitCode)
|
assert.Equal(t, 1, r.ExitCode)
|
||||||
assert.Equal(t, "", r.Stdout)
|
assert.Equal(t, "", r.Stdout)
|
||||||
assert.Equal(t, "Command error: normal error\n", r.Stderr)
|
assert.Equal(t, "Command error: normal error\n", r.Stderr)
|
||||||
|
|
||||||
app = newTestApp(func(ctx *cli.Context) error { return cli.Exit("exit error", 2) })
|
app = newTestApp(func(ctx *cli.Context) error { return cli.Exit("exit error", 2) })
|
||||||
r, err = runTestApp(app, "./gitea", "test-cmd")
|
r, err = runTestApp(app, "./gitea", "test-cmd")
|
||||||
assert.Error(t, err)
|
require.Error(t, err)
|
||||||
assert.Equal(t, 2, r.ExitCode)
|
assert.Equal(t, 2, r.ExitCode)
|
||||||
assert.Equal(t, "", r.Stdout)
|
assert.Equal(t, "", r.Stdout)
|
||||||
assert.Equal(t, "exit error\n", r.Stderr)
|
assert.Equal(t, "exit error\n", r.Stderr)
|
||||||
|
|
||||||
app = newTestApp(func(ctx *cli.Context) error { return nil })
|
app = newTestApp(func(ctx *cli.Context) error { return nil })
|
||||||
r, err = runTestApp(app, "./gitea", "test-cmd", "--no-such")
|
r, err = runTestApp(app, "./gitea", "test-cmd", "--no-such")
|
||||||
assert.Error(t, err)
|
require.Error(t, err)
|
||||||
assert.Equal(t, 1, r.ExitCode)
|
assert.Equal(t, 1, r.ExitCode)
|
||||||
assert.Equal(t, "Incorrect Usage: flag provided but not defined: -no-such\n\n", r.Stdout)
|
assert.Equal(t, "Incorrect Usage: flag provided but not defined: -no-such\n\n", r.Stdout)
|
||||||
assert.Equal(t, "", r.Stderr) // the cli package's strange behavior, the error message is not in stderr ....
|
assert.Equal(t, "", r.Stderr) // the cli package's strange behavior, the error message is not in stderr ....
|
||||||
|
|
||||||
app = newTestApp(func(ctx *cli.Context) error { return nil })
|
app = newTestApp(func(ctx *cli.Context) error { return nil })
|
||||||
r, err = runTestApp(app, "./gitea", "test-cmd")
|
r, err = runTestApp(app, "./gitea", "test-cmd")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, -1, r.ExitCode) // the cli.OsExiter is not called
|
assert.Equal(t, -1, r.ExitCode) // the cli.OsExiter is not called
|
||||||
assert.Equal(t, "", r.Stdout)
|
assert.Equal(t, "", r.Stdout)
|
||||||
assert.Equal(t, "", r.Stderr)
|
assert.Equal(t, "", r.Stderr)
|
||||||
|
|
|
@ -18,7 +18,7 @@ import (
|
||||||
var CmdMigrate = &cli.Command{
|
var CmdMigrate = &cli.Command{
|
||||||
Name: "migrate",
|
Name: "migrate",
|
||||||
Usage: "Migrate the database",
|
Usage: "Migrate the database",
|
||||||
Description: "This is a command for migrating the database, so that you can run gitea admin create-user before starting the server.",
|
Description: "This is a command for migrating the database, so that you can run gitea admin user create before starting the server.",
|
||||||
Action: runMigrate,
|
Action: runMigrate,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,13 +41,13 @@ func createLocalStorage(t *testing.T) (storage.ObjectStorage, string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMigratePackages(t *testing.T) {
|
func TestMigratePackages(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
creator := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
creator := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||||
|
|
||||||
content := "package main\n\nfunc main() {\nfmt.Println(\"hi\")\n}\n"
|
content := "package main\n\nfunc main() {\nfmt.Println(\"hi\")\n}\n"
|
||||||
buf, err := packages_module.CreateHashedBufferFromReaderWithSize(strings.NewReader(content), 1024)
|
buf, err := packages_module.CreateHashedBufferFromReaderWithSize(strings.NewReader(content), 1024)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
defer buf.Close()
|
defer buf.Close()
|
||||||
|
|
||||||
v, f, err := packages_service.CreatePackageAndAddFile(db.DefaultContext, &packages_service.PackageCreationInfo{
|
v, f, err := packages_service.CreatePackageAndAddFile(db.DefaultContext, &packages_service.PackageCreationInfo{
|
||||||
|
@ -68,7 +68,7 @@ func TestMigratePackages(t *testing.T) {
|
||||||
Data: buf,
|
Data: buf,
|
||||||
IsLead: true,
|
IsLead: true,
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.NotNil(t, v)
|
assert.NotNil(t, v)
|
||||||
assert.NotNil(t, f)
|
assert.NotNil(t, f)
|
||||||
|
|
||||||
|
@ -77,21 +77,21 @@ func TestMigratePackages(t *testing.T) {
|
||||||
dstStorage, p := createLocalStorage(t)
|
dstStorage, p := createLocalStorage(t)
|
||||||
|
|
||||||
err = migratePackages(ctx, dstStorage)
|
err = migratePackages(ctx, dstStorage)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
entries, err := os.ReadDir(p)
|
entries, err := os.ReadDir(p)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Len(t, entries, 2)
|
assert.Len(t, entries, 2)
|
||||||
assert.EqualValues(t, "01", entries[0].Name())
|
assert.EqualValues(t, "01", entries[0].Name())
|
||||||
assert.EqualValues(t, "tmp", entries[1].Name())
|
assert.EqualValues(t, "tmp", entries[1].Name())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMigrateActionsArtifacts(t *testing.T) {
|
func TestMigrateActionsArtifacts(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
srcStorage, _ := createLocalStorage(t)
|
srcStorage, _ := createLocalStorage(t)
|
||||||
defer test.MockVariableValue(&storage.ActionsArtifacts, srcStorage)()
|
defer test.MockVariableValue(&storage.ActionsArtifacts, srcStorage)()
|
||||||
id := int64(0)
|
id := int64(42)
|
||||||
|
|
||||||
addArtifact := func(storagePath string, status actions.ArtifactStatus) {
|
addArtifact := func(storagePath string, status actions.ArtifactStatus) {
|
||||||
id++
|
id++
|
||||||
|
@ -118,17 +118,17 @@ func TestMigrateActionsArtifacts(t *testing.T) {
|
||||||
|
|
||||||
dstStorage, _ := createLocalStorage(t)
|
dstStorage, _ := createLocalStorage(t)
|
||||||
|
|
||||||
assert.NoError(t, migrateActionsArtifacts(db.DefaultContext, dstStorage))
|
require.NoError(t, migrateActionsArtifacts(db.DefaultContext, dstStorage))
|
||||||
|
|
||||||
object, err := dstStorage.Open(exists)
|
object, err := dstStorage.Open(exists)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
buf, err := io.ReadAll(object)
|
buf, err := io.ReadAll(object)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, exists, string(buf))
|
assert.Equal(t, exists, string(buf))
|
||||||
|
|
||||||
_, err = dstStorage.Stat(expired)
|
_, err = dstStorage.Stat(expired)
|
||||||
assert.Error(t, err)
|
require.Error(t, err)
|
||||||
|
|
||||||
_, err = dstStorage.Stat(notFound)
|
_, err = dstStorage.Stat(notFound)
|
||||||
assert.Error(t, err)
|
require.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
11
cmd/serv.go
11
cmd/serv.go
|
@ -147,6 +147,12 @@ func runServ(c *cli.Context) error {
|
||||||
return nil
|
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(), "-")
|
keys := strings.Split(c.Args().First(), "-")
|
||||||
if len(keys) != 2 || keys[0] != "key" {
|
if len(keys) != 2 || keys[0] != "key" {
|
||||||
return fail(ctx, "Key ID format error", "Invalid key argument: %s", c.Args().First())
|
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]
|
verb := words[0]
|
||||||
repoPath := words[1]
|
repoPath := strings.TrimPrefix(words[1], "/")
|
||||||
if repoPath[0] == '/' {
|
|
||||||
repoPath = repoPath[1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
var lfsVerb string
|
var lfsVerb string
|
||||||
if verb == lfsAuthenticateVerb {
|
if verb == lfsAuthenticateVerb {
|
||||||
|
|
|
@ -17,7 +17,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/google/go-github/v57/github"
|
"github.com/google/go-github/v64/github"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
"go.buildTags": "sqlite,sqlite_unlock_notify",
|
"go.buildTags": "sqlite,sqlite_unlock_notify",
|
||||||
"go.testFlags": ["-v"]
|
"go.testFlags": ["-v"],
|
||||||
|
"go.lintTool": "golangci-lint",
|
||||||
|
"go.lintFlags": ["--fast"]
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,7 +61,7 @@ WorkingDirectory=/var/lib/forgejo/
|
||||||
#RuntimeDirectory=forgejo
|
#RuntimeDirectory=forgejo
|
||||||
ExecStart=/usr/local/bin/forgejo web --config /etc/forgejo/app.ini
|
ExecStart=/usr/local/bin/forgejo web --config /etc/forgejo/app.ini
|
||||||
Restart=always
|
Restart=always
|
||||||
Environment=USER=git HOME=/home/git GITEA_WORK_DIR=/var/lib/forgejo
|
Environment=USER=git HOME=/home/git FORGEJO_WORK_DIR=/var/lib/forgejo
|
||||||
# If you install Git to directory prefix other than default PATH (which happens
|
# If you install Git to directory prefix other than default PATH (which happens
|
||||||
# for example if you install other versions of Git side-to-side with
|
# for example if you install other versions of Git side-to-side with
|
||||||
# distribution version), uncomment below line and add that prefix to PATH
|
# distribution version), uncomment below line and add that prefix to PATH
|
||||||
|
|
|
@ -328,6 +328,10 @@ RUN_USER = ; git
|
||||||
;; Maximum number of locks returned per page
|
;; Maximum number of locks returned per page
|
||||||
;LFS_LOCKS_PAGING_NUM = 50
|
;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 using SIGHUP to fork
|
||||||
;ALLOW_GRACEFUL_RESTARTS = true
|
;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
|
;; MySQL Configuration
|
||||||
;;
|
;;
|
||||||
DB_TYPE = mysql
|
;DB_TYPE = mysql
|
||||||
HOST = 127.0.0.1:3306 ; can use socket e.g. /var/run/mysqld/mysqld.sock
|
;HOST = 127.0.0.1:3306 ; can use socket e.g. /var/run/mysqld/mysqld.sock
|
||||||
NAME = gitea
|
;NAME = gitea
|
||||||
USER = root
|
;USER = root
|
||||||
;PASSWD = ;Use PASSWD = `your password` for quoting if you use special characters in the password.
|
;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"
|
;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.
|
;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
|
;; Other settings
|
||||||
;;
|
;;
|
||||||
;; For iterate buffer, default is 50
|
;; 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 to encode urls with, it **is required** if camo is enabled.
|
||||||
;HMAC_KEY =
|
;HMAC_KEY =
|
||||||
;; Set to true to use camo for https too lese only non https urls are proxyed
|
;; 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
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -635,7 +629,7 @@ LEVEL = Info
|
||||||
;[log.%(WriterMode)]
|
;[log.%(WriterMode)]
|
||||||
;MODE=console/file/conn/...
|
;MODE=console/file/conn/...
|
||||||
;LEVEL=
|
;LEVEL=
|
||||||
;FLAGS = stdflags
|
;FLAGS = stdflags or journald
|
||||||
;EXPRESSION =
|
;EXPRESSION =
|
||||||
;PREFIX =
|
;PREFIX =
|
||||||
;COLORIZE = false
|
;COLORIZE = false
|
||||||
|
@ -732,6 +726,7 @@ LEVEL = Info
|
||||||
;CLONE = 300
|
;CLONE = 300
|
||||||
;PULL = 300
|
;PULL = 300
|
||||||
;GC = 60
|
;GC = 60
|
||||||
|
;GREP = 2
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; Git config options
|
;; Git config options
|
||||||
|
@ -923,6 +918,24 @@ LEVEL = Info
|
||||||
;; Valid site url schemes for user profiles
|
;; Valid site url schemes for user profiles
|
||||||
;VALID_SITE_URL_SCHEMES=http,https
|
;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
|
||||||
|
;;
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -1727,6 +1740,10 @@ LEVEL = Info
|
||||||
;; Sometimes it is helpful to use a different address on the envelope. Set this to use ENVELOPE_FROM as the from on the envelope. Set to `<>` to send an empty address.
|
;; Sometimes it is helpful to use a different address on the envelope. Set this to use ENVELOPE_FROM as the from on the envelope. Set to `<>` to send an empty address.
|
||||||
;ENVELOPE_FROM =
|
;ENVELOPE_FROM =
|
||||||
;;
|
;;
|
||||||
|
;; If gitea sends mails on behave of users, it will just use the name also displayed in the WebUI. If you want e.g. `Mister X (by CodeIt) <gitea@codeit.net>`,
|
||||||
|
;; set it to `{{ .DisplayName }} (by {{ .AppName }})`. Available Variables: `.DisplayName`, `.AppName` and `.Domain`.
|
||||||
|
;FROM_DISPLAY_NAME_FORMAT = {{ .DisplayName }}
|
||||||
|
;;
|
||||||
;; Mailer user name and password, if required by provider.
|
;; Mailer user name and password, if required by provider.
|
||||||
;USER =
|
;USER =
|
||||||
;;
|
;;
|
||||||
|
@ -1921,7 +1938,7 @@ LEVEL = Info
|
||||||
;ENABLED = true
|
;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.
|
;; 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 of each file. Defaults to 2048MB
|
||||||
;MAX_SIZE = 2048
|
;MAX_SIZE = 2048
|
||||||
|
@ -2290,7 +2307,7 @@ LEVEL = Info
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; Delete all old actions from database
|
;; Delete all old activities from database
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;[cron.delete_old_actions]
|
;[cron.delete_old_actions]
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -2599,6 +2616,8 @@ LEVEL = Info
|
||||||
;LIMIT_SIZE_SWIFT = -1
|
;LIMIT_SIZE_SWIFT = -1
|
||||||
;; Maximum size of a Vagrant upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
;; Maximum size of a Vagrant upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`)
|
||||||
;LIMIT_SIZE_VAGRANT = -1
|
;LIMIT_SIZE_VAGRANT = -1
|
||||||
|
;; Enable RPM re-signing by default. (It will overwrite the old signature ,using v4 format, not compatible with CentOS 6 or older)
|
||||||
|
;DEFAULT_RPM_SIGN_ENABLED = false
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -2646,6 +2665,10 @@ LEVEL = Info
|
||||||
;; override the minio base path if storage type is minio
|
;; override the minio base path if storage type is minio
|
||||||
;MINIO_BASE_PATH = lfs/
|
;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
|
;; settings for packages, will override storage setting
|
||||||
|
@ -2704,7 +2727,15 @@ LEVEL = Info
|
||||||
;ENABLED = true
|
;ENABLED = true
|
||||||
;; Default address to get action plugins, e.g. the default value means downloading from "https://code.forgejo.org/actions/checkout" for "uses: actions/checkout@v3"
|
;; Default address to get action plugins, e.g. the default value means downloading from "https://code.forgejo.org/actions/checkout" for "uses: actions/checkout@v3"
|
||||||
;DEFAULT_ACTIONS_URL = https://code.forgejo.org
|
;DEFAULT_ACTIONS_URL = https://code.forgejo.org
|
||||||
;; Default artifact retention time in days, default is 90 days
|
;; Logs retention time in days. Old logs will be deleted after this period.
|
||||||
|
;LOG_RETENTION_DAYS = 365
|
||||||
|
;; Log compression type, `none` for no compression, `zstd` for zstd compression.
|
||||||
|
;; Other compression types like `gzip` are NOT supported, since seekable stream is required for log view.
|
||||||
|
;; It's always recommended to use compression when using local disk as log storage if CPU or memory is not a bottleneck.
|
||||||
|
;; And for object storage services like S3, which is billed for requests, it would cause extra 2 times of get requests for each log view.
|
||||||
|
;; But it will save storage space and network bandwidth, so it's still recommended to use compression.
|
||||||
|
;LOG_COMPRESSION = zstd
|
||||||
|
;; Default artifact retention time in days. Artifacts could have their own retention periods by setting the `retention-days` option in `actions/upload-artifact` step.
|
||||||
;ARTIFACT_RETENTION_DAYS = 90
|
;ARTIFACT_RETENTION_DAYS = 90
|
||||||
;; Timeout to stop the task which have running status, but haven't been updated for a long time
|
;; Timeout to stop the task which have running status, but haven't been updated for a long time
|
||||||
;ZOMBIE_TASK_TIMEOUT = 10m
|
;ZOMBIE_TASK_TIMEOUT = 10m
|
||||||
|
|
1170
eslint.config.mjs
Normal file
1170
eslint.config.mjs
Normal file
File diff suppressed because it is too large
Load diff
165
go.mod
165
go.mod
|
@ -1,83 +1,81 @@
|
||||||
module code.gitea.io/gitea
|
module code.gitea.io/gitea
|
||||||
|
|
||||||
go 1.22.0
|
go 1.23.3
|
||||||
|
|
||||||
toolchain go1.22.5
|
|
||||||
|
|
||||||
require (
|
require (
|
||||||
code.forgejo.org/f3/gof3/v3 v3.4.0
|
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/forgejo/reply v1.0.2
|
||||||
|
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/actions-proto-go v0.4.0
|
||||||
code.gitea.io/gitea-vet v0.2.3
|
code.gitea.io/gitea-vet v0.2.3
|
||||||
code.gitea.io/sdk/gitea v0.17.1
|
code.gitea.io/sdk/gitea v0.17.1
|
||||||
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570
|
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570
|
||||||
connectrpc.com/connect v1.16.2
|
connectrpc.com/connect v1.17.0
|
||||||
gitea.com/go-chi/binding v0.0.0-20240430071103-39a851e106ed
|
|
||||||
gitea.com/go-chi/cache v0.2.0
|
|
||||||
gitea.com/go-chi/captcha v0.0.0-20240315150714-fb487f629098
|
|
||||||
gitea.com/go-chi/session v0.0.0-20240316035857-16768d98ec96
|
|
||||||
gitea.com/lunny/levelqueue v0.4.2-0.20230414023320-3c0159fe0fe4
|
gitea.com/lunny/levelqueue v0.4.2-0.20230414023320-3c0159fe0fe4
|
||||||
github.com/42wim/sshsig v0.0.0-20211121163825-841cf5bbc121
|
github.com/42wim/sshsig v0.0.0-20211121163825-841cf5bbc121
|
||||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358
|
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358
|
||||||
github.com/ProtonMail/go-crypto v1.0.0
|
github.com/ProtonMail/go-crypto v1.0.0
|
||||||
github.com/PuerkitoBio/goquery v1.9.2
|
github.com/PuerkitoBio/goquery v1.10.0
|
||||||
|
github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.7.2
|
||||||
github.com/alecthomas/chroma/v2 v2.14.0
|
github.com/alecthomas/chroma/v2 v2.14.0
|
||||||
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb
|
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb
|
||||||
github.com/blevesearch/bleve/v2 v2.4.1
|
github.com/blevesearch/bleve/v2 v2.4.3
|
||||||
github.com/buildkite/terminal-to-html/v3 v3.14.0
|
github.com/buildkite/terminal-to-html/v3 v3.16.4
|
||||||
github.com/caddyserver/certmagic v0.21.0
|
github.com/caddyserver/certmagic v0.21.4
|
||||||
github.com/chi-middleware/proxy v1.1.1
|
github.com/chi-middleware/proxy v1.1.1
|
||||||
github.com/djherbis/buffer v1.2.0
|
github.com/djherbis/buffer v1.2.0
|
||||||
github.com/djherbis/nio/v3 v3.0.1
|
github.com/djherbis/nio/v3 v3.0.1
|
||||||
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5
|
github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707
|
||||||
github.com/dustin/go-humanize v1.0.1
|
github.com/dustin/go-humanize v1.0.1
|
||||||
github.com/editorconfig/editorconfig-core-go/v2 v2.6.2
|
github.com/editorconfig/editorconfig-core-go/v2 v2.6.2
|
||||||
github.com/emersion/go-imap v1.2.1
|
github.com/emersion/go-imap v1.2.1
|
||||||
github.com/emirpasic/gods v1.18.1
|
github.com/felixge/fgprof v0.9.5
|
||||||
github.com/felixge/fgprof v0.9.4
|
github.com/fsnotify/fsnotify v1.8.0
|
||||||
github.com/fsnotify/fsnotify v1.7.0
|
|
||||||
github.com/gliderlabs/ssh v0.3.7
|
github.com/gliderlabs/ssh v0.3.7
|
||||||
github.com/go-ap/activitypub v0.0.0-20231114162308-e219254dc5c9
|
github.com/go-ap/activitypub v0.0.0-20231114162308-e219254dc5c9
|
||||||
github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73
|
github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73
|
||||||
github.com/go-chi/chi/v5 v5.0.14
|
github.com/go-chi/chi/v5 v5.1.0
|
||||||
github.com/go-chi/cors v1.2.1
|
github.com/go-chi/cors v1.2.1
|
||||||
github.com/go-co-op/gocron v1.37.0
|
github.com/go-co-op/gocron v1.37.0
|
||||||
github.com/go-enry/go-enry/v2 v2.8.8
|
github.com/go-enry/go-enry/v2 v2.9.1
|
||||||
github.com/go-fed/httpsig v1.1.1-0.20201223112313-55836744818e
|
github.com/go-fed/httpsig v1.1.1-0.20201223112313-55836744818e
|
||||||
github.com/go-git/go-billy/v5 v5.5.0
|
|
||||||
github.com/go-git/go-git/v5 v5.11.0
|
github.com/go-git/go-git/v5 v5.11.0
|
||||||
github.com/go-ldap/ldap/v3 v3.4.6
|
github.com/go-ldap/ldap/v3 v3.4.6
|
||||||
github.com/go-sql-driver/mysql v1.8.1
|
github.com/go-sql-driver/mysql v1.8.1
|
||||||
github.com/go-swagger/go-swagger v0.30.5
|
github.com/go-swagger/go-swagger v0.30.5
|
||||||
github.com/go-testfixtures/testfixtures/v3 v3.12.0
|
github.com/go-testfixtures/testfixtures/v3 v3.12.0
|
||||||
github.com/go-webauthn/webauthn v0.10.0
|
github.com/go-webauthn/webauthn v0.11.2
|
||||||
github.com/gobwas/glob v0.2.3
|
github.com/gobwas/glob v0.2.3
|
||||||
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f
|
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f
|
||||||
github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85
|
github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85
|
||||||
github.com/golang-jwt/jwt/v5 v5.2.0
|
github.com/golang-jwt/jwt/v5 v5.2.1
|
||||||
github.com/google/go-github/v57 v57.0.0
|
github.com/google/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/google/uuid v1.6.0
|
||||||
github.com/gorilla/feeds v1.2.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/h2non/gock v1.2.0
|
||||||
github.com/hashicorp/go-version v1.6.0
|
github.com/hashicorp/go-version v1.6.0
|
||||||
github.com/hashicorp/golang-lru/v2 v2.0.7
|
github.com/hashicorp/golang-lru/v2 v2.0.7
|
||||||
github.com/huandu/xstrings v1.5.0
|
github.com/huandu/xstrings v1.5.0
|
||||||
github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056
|
github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056
|
||||||
github.com/jhillyerd/enmime v1.2.0
|
github.com/jhillyerd/enmime/v2 v2.0.0
|
||||||
github.com/json-iterator/go v1.1.12
|
github.com/json-iterator/go v1.1.12
|
||||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
|
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/klauspost/cpuid/v2 v2.2.8
|
||||||
github.com/lib/pq v1.10.9
|
github.com/lib/pq v1.10.9
|
||||||
github.com/markbates/goth v1.80.0
|
github.com/markbates/goth v1.80.0
|
||||||
github.com/mattn/go-isatty v0.0.20
|
github.com/mattn/go-isatty v0.0.20
|
||||||
github.com/mattn/go-sqlite3 v1.14.22
|
github.com/mattn/go-sqlite3 v1.14.24
|
||||||
github.com/meilisearch/meilisearch-go v0.26.1
|
github.com/meilisearch/meilisearch-go v0.29.0
|
||||||
github.com/mholt/archiver/v3 v3.5.1
|
github.com/mholt/archiver/v3 v3.5.1
|
||||||
github.com/microcosm-cc/bluemonday v1.0.27
|
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/msteinert/pam v1.2.0
|
||||||
github.com/nektos/act v0.2.52
|
github.com/nektos/act v0.2.52
|
||||||
github.com/niklasfasching/go-org v1.7.0
|
github.com/niklasfasching/go-org v1.7.0
|
||||||
|
@ -85,44 +83,42 @@ require (
|
||||||
github.com/opencontainers/go-digest v1.0.0
|
github.com/opencontainers/go-digest v1.0.0
|
||||||
github.com/opencontainers/image-spec v1.1.0
|
github.com/opencontainers/image-spec v1.1.0
|
||||||
github.com/pquerna/otp v1.4.0
|
github.com/pquerna/otp v1.4.0
|
||||||
github.com/prometheus/client_golang v1.18.0
|
github.com/prometheus/client_golang v1.20.5
|
||||||
github.com/quasoft/websspi v1.1.2
|
github.com/redis/go-redis/v9 v9.7.0
|
||||||
github.com/redis/go-redis/v9 v9.5.2
|
|
||||||
github.com/robfig/cron/v3 v3.0.1
|
github.com/robfig/cron/v3 v3.0.1
|
||||||
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1
|
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1
|
||||||
github.com/sassoftware/go-rpmutils v0.2.1-0.20240124161140-277b154961dd
|
github.com/sassoftware/go-rpmutils v0.4.0
|
||||||
github.com/sergi/go-diff v1.3.1
|
github.com/sergi/go-diff v1.3.1
|
||||||
github.com/shurcooL/vfsgen v0.0.0-20230704071429-0000e147ea92
|
github.com/shurcooL/vfsgen v0.0.0-20230704071429-0000e147ea92
|
||||||
github.com/stretchr/testify v1.9.0
|
github.com/stretchr/testify v1.9.0
|
||||||
github.com/syndtr/goleveldb v1.0.0
|
github.com/syndtr/goleveldb v1.0.0
|
||||||
github.com/ulikunitz/xz v0.5.11
|
github.com/ulikunitz/xz v0.5.12
|
||||||
github.com/urfave/cli/v2 v2.27.2
|
github.com/urfave/cli/v2 v2.27.5
|
||||||
github.com/valyala/fastjson v1.6.4
|
github.com/valyala/fastjson v1.6.4
|
||||||
github.com/xanzy/go-gitlab v0.96.0
|
github.com/xanzy/go-gitlab v0.109.0
|
||||||
github.com/yohcop/openid-go v1.0.1
|
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
|
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
|
||||||
go.uber.org/mock v0.4.0
|
go.uber.org/mock v0.4.0
|
||||||
golang.org/x/crypto v0.25.0
|
golang.org/x/crypto v0.29.0
|
||||||
golang.org/x/image v0.18.0
|
golang.org/x/image v0.21.0
|
||||||
golang.org/x/net v0.27.0
|
golang.org/x/net v0.31.0
|
||||||
golang.org/x/oauth2 v0.21.0
|
golang.org/x/oauth2 v0.23.0
|
||||||
golang.org/x/sys v0.22.0
|
golang.org/x/sys v0.27.0
|
||||||
golang.org/x/text v0.16.0
|
golang.org/x/text v0.20.0
|
||||||
golang.org/x/tools v0.23.0
|
golang.org/x/tools v0.26.0
|
||||||
google.golang.org/grpc v1.65.0
|
google.golang.org/grpc v1.68.0
|
||||||
google.golang.org/protobuf v1.34.1
|
google.golang.org/protobuf v1.35.1
|
||||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
||||||
gopkg.in/ini.v1 v1.67.0
|
gopkg.in/ini.v1 v1.67.0
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
mvdan.cc/xurls/v2 v2.5.0
|
mvdan.cc/xurls/v2 v2.5.0
|
||||||
strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251
|
|
||||||
xorm.io/builder v0.3.13
|
xorm.io/builder v0.3.13
|
||||||
xorm.io/xorm v1.3.7
|
xorm.io/xorm v1.3.9
|
||||||
)
|
)
|
||||||
|
|
||||||
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
|
dario.cat/mergo v1.0.0 // indirect
|
||||||
filippo.io/edwards25519 v1.1.0 // indirect
|
filippo.io/edwards25519 v1.1.0 // indirect
|
||||||
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078 // indirect
|
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078 // indirect
|
||||||
|
@ -141,13 +137,13 @@ require (
|
||||||
github.com/aymerick/douceur v0.2.0 // indirect
|
github.com/aymerick/douceur v0.2.0 // indirect
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/bits-and-blooms/bitset v1.13.0 // indirect
|
github.com/bits-and-blooms/bitset v1.13.0 // indirect
|
||||||
github.com/blevesearch/bleve_index_api v1.1.9 // indirect
|
github.com/blevesearch/bleve_index_api v1.1.12 // indirect
|
||||||
github.com/blevesearch/geo v0.1.20 // indirect
|
github.com/blevesearch/geo v0.1.20 // indirect
|
||||||
github.com/blevesearch/go-faiss v1.0.19 // indirect
|
github.com/blevesearch/go-faiss v1.0.23 // indirect
|
||||||
github.com/blevesearch/go-porterstemmer v1.0.3 // indirect
|
github.com/blevesearch/go-porterstemmer v1.0.3 // indirect
|
||||||
github.com/blevesearch/gtreap v0.1.1 // indirect
|
github.com/blevesearch/gtreap v0.1.1 // indirect
|
||||||
github.com/blevesearch/mmap-go v1.0.4 // indirect
|
github.com/blevesearch/mmap-go v1.0.4 // indirect
|
||||||
github.com/blevesearch/scorch_segment_api/v2 v2.2.14 // indirect
|
github.com/blevesearch/scorch_segment_api/v2 v2.2.16 // indirect
|
||||||
github.com/blevesearch/segment v0.9.1 // indirect
|
github.com/blevesearch/segment v0.9.1 // indirect
|
||||||
github.com/blevesearch/snowballstem v0.9.0 // indirect
|
github.com/blevesearch/snowballstem v0.9.0 // indirect
|
||||||
github.com/blevesearch/upsidedown_store_api v1.0.2 // indirect
|
github.com/blevesearch/upsidedown_store_api v1.0.2 // indirect
|
||||||
|
@ -156,33 +152,32 @@ require (
|
||||||
github.com/blevesearch/zapx/v12 v12.3.10 // indirect
|
github.com/blevesearch/zapx/v12 v12.3.10 // indirect
|
||||||
github.com/blevesearch/zapx/v13 v13.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/v14 v14.3.10 // indirect
|
||||||
github.com/blevesearch/zapx/v15 v15.3.13 // indirect
|
github.com/blevesearch/zapx/v15 v15.3.16 // indirect
|
||||||
github.com/blevesearch/zapx/v16 v16.1.4 // indirect
|
github.com/blevesearch/zapx/v16 v16.1.8 // indirect
|
||||||
github.com/boombuler/barcode v1.0.1 // indirect
|
github.com/boombuler/barcode v1.0.1 // indirect
|
||||||
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 // 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/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
github.com/cloudflare/circl v1.3.7 // indirect
|
github.com/cloudflare/circl v1.3.8 // indirect
|
||||||
github.com/couchbase/go-couchbase v0.1.1 // indirect
|
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
|
||||||
github.com/couchbase/gomemcached v0.3.0 // indirect
|
|
||||||
github.com/couchbase/goutils v0.1.2 // indirect
|
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
|
|
||||||
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
|
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||||
github.com/davidmz/go-pageant v1.0.2 // indirect
|
github.com/davidmz/go-pageant v1.0.2 // indirect
|
||||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||||
github.com/dlclark/regexp2 v1.11.0 // indirect
|
github.com/dlclark/regexp2 v1.11.0 // indirect
|
||||||
github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43 // indirect
|
github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43 // indirect
|
||||||
|
github.com/emirpasic/gods v1.18.1 // indirect
|
||||||
github.com/fatih/color v1.16.0 // indirect
|
github.com/fatih/color v1.16.0 // indirect
|
||||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||||
github.com/fxamacker/cbor/v2 v2.5.0 // indirect
|
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
|
||||||
github.com/go-ap/errors v0.0.0-20231003111023-183eef4b31b7 // indirect
|
github.com/go-ap/errors v0.0.0-20231003111023-183eef4b31b7 // indirect
|
||||||
github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect
|
github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect
|
||||||
github.com/go-enry/go-oniguruma v1.2.1 // indirect
|
github.com/go-enry/go-oniguruma v1.2.1 // indirect
|
||||||
github.com/go-faster/city v1.0.1 // indirect
|
github.com/go-faster/city v1.0.1 // indirect
|
||||||
github.com/go-faster/errors v0.7.1 // indirect
|
github.com/go-faster/errors v0.7.1 // indirect
|
||||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||||
|
github.com/go-git/go-billy/v5 v5.5.0 // indirect
|
||||||
github.com/go-ini/ini v1.67.0 // indirect
|
github.com/go-ini/ini v1.67.0 // indirect
|
||||||
github.com/go-openapi/analysis v0.22.2 // indirect
|
github.com/go-openapi/analysis v0.22.2 // indirect
|
||||||
github.com/go-openapi/errors v0.21.0 // indirect
|
github.com/go-openapi/errors v0.21.0 // indirect
|
||||||
|
@ -195,17 +190,17 @@ require (
|
||||||
github.com/go-openapi/strfmt v0.22.0 // indirect
|
github.com/go-openapi/strfmt v0.22.0 // indirect
|
||||||
github.com/go-openapi/swag v0.22.7 // indirect
|
github.com/go-openapi/swag v0.22.7 // indirect
|
||||||
github.com/go-openapi/validate v0.22.6 // indirect
|
github.com/go-openapi/validate v0.22.6 // indirect
|
||||||
github.com/go-webauthn/x v0.1.6 // indirect
|
github.com/go-webauthn/x v0.1.14 // indirect
|
||||||
github.com/goccy/go-json v0.10.3 // indirect
|
github.com/goccy/go-json v0.10.3 // indirect
|
||||||
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
|
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
|
||||||
github.com/golang/geo v0.0.0-20230421003525-6adc56603217 // indirect
|
github.com/golang/geo v0.0.0-20230421003525-6adc56603217 // indirect
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||||
github.com/golang/protobuf v1.5.4 // indirect
|
github.com/golang/protobuf v1.5.4 // indirect
|
||||||
github.com/golang/snappy v0.0.4 // indirect
|
github.com/golang/snappy v0.0.4 // indirect
|
||||||
|
github.com/google/btree v1.1.2 // indirect
|
||||||
github.com/google/go-cmp v0.6.0 // indirect
|
github.com/google/go-cmp v0.6.0 // indirect
|
||||||
github.com/google/go-querystring v1.1.0 // indirect
|
github.com/google/go-querystring v1.1.0 // indirect
|
||||||
github.com/google/go-tpm v0.9.0 // indirect
|
github.com/google/go-tpm v0.9.1 // indirect
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99 // indirect
|
|
||||||
github.com/gorilla/css v1.0.1 // indirect
|
github.com/gorilla/css v1.0.1 // indirect
|
||||||
github.com/gorilla/handlers v1.5.2 // indirect
|
github.com/gorilla/handlers v1.5.2 // indirect
|
||||||
github.com/gorilla/mux v1.8.1 // indirect
|
github.com/gorilla/mux v1.8.1 // indirect
|
||||||
|
@ -227,9 +222,9 @@ require (
|
||||||
github.com/mailru/easyjson v0.7.7 // indirect
|
github.com/mailru/easyjson v0.7.7 // indirect
|
||||||
github.com/markbates/going v1.0.3 // indirect
|
github.com/markbates/going v1.0.3 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||||
github.com/mholt/acmez/v2 v2.0.1 // indirect
|
github.com/mholt/acmez/v2 v2.0.3 // indirect
|
||||||
github.com/miekg/dns v1.1.59 // indirect
|
github.com/miekg/dns v1.1.62 // indirect
|
||||||
github.com/minio/md5-simd v1.1.2 // indirect
|
github.com/minio/md5-simd v1.1.2 // indirect
|
||||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
|
@ -238,6 +233,7 @@ require (
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/mrjones/oauth v0.0.0-20190623134757-126b35219450 // indirect
|
github.com/mrjones/oauth v0.0.0-20190623134757-126b35219450 // indirect
|
||||||
github.com/mschoch/smat v0.2.0 // 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/nwaples/rardecode v1.1.3 // indirect
|
||||||
github.com/oklog/ulid v1.3.1 // indirect
|
github.com/oklog/ulid v1.3.1 // indirect
|
||||||
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
github.com/olekukonko/tablewriter v0.0.5 // indirect
|
||||||
|
@ -248,13 +244,13 @@ require (
|
||||||
github.com/pjbgf/sha1cd v0.3.0 // indirect
|
github.com/pjbgf/sha1cd v0.3.0 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // 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/client_model v0.6.1 // indirect
|
||||||
github.com/prometheus/common v0.46.0 // indirect
|
github.com/prometheus/common v0.55.0 // indirect
|
||||||
github.com/prometheus/procfs v0.12.0 // indirect
|
github.com/prometheus/procfs v0.15.1 // indirect
|
||||||
github.com/rhysd/actionlint v1.6.27 // indirect
|
github.com/rhysd/actionlint v1.6.27 // indirect
|
||||||
github.com/rivo/uniseg v0.4.7 // indirect
|
github.com/rivo/uniseg v0.4.7 // indirect
|
||||||
github.com/rogpeppe/go-internal v1.12.0 // 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/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
||||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||||
|
@ -271,14 +267,11 @@ require (
|
||||||
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
|
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
|
||||||
github.com/subosito/gotenv v1.6.0 // indirect
|
github.com/subosito/gotenv v1.6.0 // indirect
|
||||||
github.com/toqueteos/webbrowser v1.2.0 // indirect
|
github.com/toqueteos/webbrowser v1.2.0 // indirect
|
||||||
github.com/unknwon/com v1.0.1 // indirect
|
|
||||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
|
||||||
github.com/valyala/fasthttp v1.51.0 // indirect
|
|
||||||
github.com/x448/float16 v0.8.4 // indirect
|
github.com/x448/float16 v0.8.4 // indirect
|
||||||
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
||||||
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
|
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
|
||||||
github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 // 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.etcd.io/bbolt v1.3.9 // indirect
|
||||||
go.mongodb.org/mongo-driver v1.13.1 // indirect
|
go.mongodb.org/mongo-driver v1.13.1 // indirect
|
||||||
go.opentelemetry.io/otel v1.26.0 // indirect
|
go.opentelemetry.io/otel v1.26.0 // indirect
|
||||||
|
@ -287,10 +280,10 @@ require (
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
go.uber.org/zap v1.27.0 // indirect
|
go.uber.org/zap v1.27.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect
|
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect
|
||||||
golang.org/x/mod v0.19.0 // indirect
|
golang.org/x/mod v0.21.0 // indirect
|
||||||
golang.org/x/sync v0.7.0 // indirect
|
golang.org/x/sync v0.9.0 // indirect
|
||||||
golang.org/x/time v0.5.0 // indirect
|
golang.org/x/time v0.5.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 // 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/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
|
@ -300,14 +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/shurcooL/vfsgen => github.com/lunny/vfsgen v0.0.0-20220105142115-2c99e1ffdfa0
|
||||||
|
|
||||||
replace github.com/nektos/act => gitea.com/gitea/act v0.261.1
|
replace github.com/nektos/act => code.forgejo.org/forgejo/act v1.22.0
|
||||||
|
|
||||||
exclude github.com/gofrs/uuid v3.2.0+incompatible
|
|
||||||
|
|
||||||
exclude github.com/gofrs/uuid v4.0.0+incompatible
|
|
||||||
|
|
||||||
exclude github.com/goccy/go-json v0.4.11
|
|
||||||
|
|
||||||
exclude github.com/satori/go.uuid v1.2.0
|
|
||||||
|
|
||||||
replace github.com/mholt/archiver/v3 => code.forgejo.org/forgejo/archiver/v3 v3.5.1
|
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
|
||||||
|
|
370
go.sum
370
go.sum
|
@ -1,11 +1,23 @@
|
||||||
cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc=
|
cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY=
|
||||||
cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
|
cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY=
|
||||||
code.forgejo.org/f3/gof3/v3 v3.4.0 h1:60LOo47tAKvr9nVu2qqNjbgRnCKeKx68mRMRBo/hIuA=
|
code.forgejo.org/f3/gof3/v3 v3.7.0 h1:ZfuCP8CGm8ZJbWmL+V0pUu3E0X4FCAA7GfRDy/y5/K4=
|
||||||
code.forgejo.org/f3/gof3/v3 v3.4.0/go.mod h1:9v7foN46KlEr5gywOSQPn1k5BVpPeuBozsLKlgOQ3YM=
|
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.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 h1:UmmbA7D5550uf71SQjarmrn6yKwOGxtEjb3jaYYtmSE=
|
||||||
code.forgejo.org/forgejo/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4=
|
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 h1:dMhQCHV6/O3L5CLWNTol+dNzDAuyCK88z4J/lCdgFuQ=
|
||||||
code.forgejo.org/forgejo/reply v1.0.2/go.mod h1:RyZUfzQLc+fuLIGjTSQWDAJWPiL4WtKXB/FifT5fM7U=
|
code.forgejo.org/forgejo/reply v1.0.2/go.mod h1:RyZUfzQLc+fuLIGjTSQWDAJWPiL4WtKXB/FifT5fM7U=
|
||||||
|
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 h1:OsPBPhodXuQnsspG1sQ4eRE1PeoZyofd7+i73zCwnsU=
|
||||||
code.gitea.io/actions-proto-go v0.4.0/go.mod h1:mn7Wkqz6JbnTOHQpot3yDeHx+O5C9EGhMEE+htvHBas=
|
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=
|
code.gitea.io/gitea-vet v0.2.3 h1:gdFmm6WOTM65rE8FUBTRzeQZYzXePKSSB1+r574hWwI=
|
||||||
|
@ -14,24 +26,14 @@ code.gitea.io/sdk/gitea v0.17.1 h1:3jCPOG2ojbl8AcfaUCRYLT5MUcBMFwS0OSK2mA5Zok8=
|
||||||
code.gitea.io/sdk/gitea v0.17.1/go.mod h1:aCnBqhHpoEWA180gMbaCtdX9Pl6BWBAuuP2miadoTNM=
|
code.gitea.io/sdk/gitea v0.17.1/go.mod h1:aCnBqhHpoEWA180gMbaCtdX9Pl6BWBAuuP2miadoTNM=
|
||||||
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570 h1:TXbikPqa7YRtfU9vS6QJBg77pUvbEb6StRdZO8t1bEY=
|
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570 h1:TXbikPqa7YRtfU9vS6QJBg77pUvbEb6StRdZO8t1bEY=
|
||||||
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570/go.mod h1:IIAjsijsd8q1isWX8MACefDEgTQslQ4stk2AeeTt3kM=
|
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570/go.mod h1:IIAjsijsd8q1isWX8MACefDEgTQslQ4stk2AeeTt3kM=
|
||||||
connectrpc.com/connect v1.16.2 h1:ybd6y+ls7GOlb7Bh5C8+ghA6SvCBajHwxssO2CGFjqE=
|
connectrpc.com/connect v1.17.0 h1:W0ZqMhtVzn9Zhn2yATuUokDLO5N+gIuBWMOnsQrfmZk=
|
||||||
connectrpc.com/connect v1.16.2/go.mod h1:n2kgwskMHXC+lVqb18wngEpF95ldBHXjZYJussz5FRc=
|
connectrpc.com/connect v1.17.0/go.mod h1:0292hj1rnx8oFrStN7cB4jjVBeqs+Yx5yDIC2prWDO8=
|
||||||
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
|
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
|
||||||
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
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 h1:cliQ4HHsCo6xi2oWZYKWW4bly/Ory9FuTpFPRxj/mAg=
|
||||||
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078/go.mod h1:g/V2Hjas6Z1UHUp4yIx6bATpNzJ7DYtD0FG3+xARWxs=
|
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078/go.mod h1:g/V2Hjas6Z1UHUp4yIx6bATpNzJ7DYtD0FG3+xARWxs=
|
||||||
gitea.com/gitea/act v0.261.1 h1:iACWLc/k8wct9fCF2WdYKqn2Hxx6NjW9zbOP79HF4H4=
|
|
||||||
gitea.com/gitea/act v0.261.1/go.mod h1:Pg5C9kQY1CEA3QjthjhlrqOC/QOT5NyWNjOjRHw23Ok=
|
|
||||||
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/go-chi/cache v0.2.0 h1:E0npuTfDW6CT1yD8NMDVc1SK6IeRjfmRL2zlEsCEd7w=
|
|
||||||
gitea.com/go-chi/cache v0.2.0/go.mod h1:iQlVK2aKTZ/rE9UcHyz9pQWGvdP9i1eI2spOpzgCrtE=
|
|
||||||
gitea.com/go-chi/captcha v0.0.0-20240315150714-fb487f629098 h1:p2ki+WK0cIeNQuqjR98IP2KZQKRzJJiV7aTeMAFwaWo=
|
|
||||||
gitea.com/go-chi/captcha v0.0.0-20240315150714-fb487f629098/go.mod h1:LjzIOHlRemuUyO7WR12fmm18VZIlCAaOt9L3yKw40pk=
|
|
||||||
gitea.com/go-chi/session v0.0.0-20240316035857-16768d98ec96 h1:IFDiMBObsP6CZIRaDLd54SR6zPYAffPXiXck5Xslu0Q=
|
|
||||||
gitea.com/go-chi/session v0.0.0-20240316035857-16768d98ec96/go.mod h1:0iEpFKnwO5dG0aF98O4eq6FMsAiXkNBaDIlUOlq4BtM=
|
|
||||||
gitea.com/lunny/levelqueue v0.4.2-0.20230414023320-3c0159fe0fe4 h1:IFT+hup2xejHqdhS7keYWioqfmxdnfblFDTGoOwcZ+o=
|
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/lunny/levelqueue v0.4.2-0.20230414023320-3c0159fe0fe4/go.mod h1:HBqmLbz56JWpfEGG0prskAV97ATNRoj5LDmPicD22hU=
|
||||||
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGqTOXqu2aRi/XEQxDCBwM8yJtE6s=
|
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGqTOXqu2aRi/XEQxDCBwM8yJtE6s=
|
||||||
|
@ -42,12 +44,10 @@ github.com/6543/go-version v1.3.1 h1:HvOp+Telns7HWJ2Xo/05YXQSB2bE0WmVgbHqwMPZT4U
|
||||||
github.com/6543/go-version v1.3.1/go.mod h1:oqFAHCwtLVUTLdhQmVZWYvaHXTdsbB4SY85at64SQEo=
|
github.com/6543/go-version v1.3.1/go.mod h1:oqFAHCwtLVUTLdhQmVZWYvaHXTdsbB4SY85at64SQEo=
|
||||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8=
|
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8=
|
||||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
|
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
|
||||||
github.com/ClickHouse/ch-go v0.61.5 h1:zwR8QbYI0tsMiEcze/uIMK+Tz1D3XZXLdNrlaOpeEI4=
|
github.com/ClickHouse/ch-go v0.61.5 h1:zwR8QbYI0tsMiEcze/uIMK+Tz1D3XZXLdNrlaOpeEI4=
|
||||||
github.com/ClickHouse/ch-go v0.61.5/go.mod h1:s1LJW/F/LcFs5HJnuogFMta50kKDO0lf9zzfrbl0RQg=
|
github.com/ClickHouse/ch-go v0.61.5/go.mod h1:s1LJW/F/LcFs5HJnuogFMta50kKDO0lf9zzfrbl0RQg=
|
||||||
github.com/ClickHouse/clickhouse-go/v2 v2.26.0 h1:j4/y6NYaCcFkJwN/TU700ebW+nmsIy34RmUAAcZKy9w=
|
github.com/ClickHouse/clickhouse-go/v2 v2.26.0 h1:j4/y6NYaCcFkJwN/TU700ebW+nmsIy34RmUAAcZKy9w=
|
||||||
github.com/ClickHouse/clickhouse-go/v2 v2.26.0/go.mod h1:iDTViXk2Fgvf1jn2dbJd1ys+fBkdD1UMRnXlwmhijhQ=
|
github.com/ClickHouse/clickhouse-go/v2 v2.26.0/go.mod h1:iDTViXk2Fgvf1jn2dbJd1ys+fBkdD1UMRnXlwmhijhQ=
|
||||||
github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
|
|
||||||
github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ=
|
github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ=
|
||||||
github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
|
github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
|
||||||
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
|
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
|
||||||
|
@ -62,10 +62,12 @@ github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migc
|
||||||
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
|
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
|
||||||
github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78=
|
github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78=
|
||||||
github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
|
github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
|
||||||
github.com/PuerkitoBio/goquery v1.9.2 h1:4/wZksC3KgkQw7SQgkKotmKljk0M6V8TUvA8Wb4yPeE=
|
github.com/PuerkitoBio/goquery v1.10.0 h1:6fiXdLuUvYs2OJSvNRqlNPoBm6YABE226xrbavY5Wv4=
|
||||||
github.com/PuerkitoBio/goquery v1.9.2/go.mod h1:GHPCaP0ODyyxqcNoFGYlAprUFH81NuRPd0GX3Zu2Mvk=
|
github.com/PuerkitoBio/goquery v1.10.0/go.mod h1:TjZZl68Q3eGHNBA8CWaxAN7rOU1EbDz3CWuolcO5Yu4=
|
||||||
github.com/RoaringBitmap/roaring v1.9.3 h1:t4EbC5qQwnisr5PrP9nt0IRhRTb9gMUgQF4t4S2OByM=
|
github.com/RoaringBitmap/roaring v1.9.3 h1:t4EbC5qQwnisr5PrP9nt0IRhRTb9gMUgQF4t4S2OByM=
|
||||||
github.com/RoaringBitmap/roaring v1.9.3/go.mod h1:6AXUsoIEzDTFFQCe1RbGA6uFONMhvejWj5rqITANK90=
|
github.com/RoaringBitmap/roaring v1.9.3/go.mod h1:6AXUsoIEzDTFFQCe1RbGA6uFONMhvejWj5rqITANK90=
|
||||||
|
github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.7.2 h1:cSXom2MoKJ9KPPw29RoZtHvUETY4F4n/kXl8m9btnQ0=
|
||||||
|
github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.7.2/go.mod h1:JitQWJ8JuV4Y87l8VsHiiwhb3cgdyn68mX40s7NT6PA=
|
||||||
github.com/alecthomas/assert/v2 v2.7.0 h1:QtqSACNS3tF7oasA8CU6A6sXZSBDqnm7RfpLl9bZqbE=
|
github.com/alecthomas/assert/v2 v2.7.0 h1:QtqSACNS3tF7oasA8CU6A6sXZSBDqnm7RfpLl9bZqbE=
|
||||||
github.com/alecthomas/assert/v2 v2.7.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
|
github.com/alecthomas/assert/v2 v2.7.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
|
||||||
github.com/alecthomas/chroma/v2 v2.2.0/go.mod h1:vf4zrexSH54oEjJ7EdB65tGNHmH3pGZmVkgTP5RHvAs=
|
github.com/alecthomas/chroma/v2 v2.2.0/go.mod h1:vf4zrexSH54oEjJ7EdB65tGNHmH3pGZmVkgTP5RHvAs=
|
||||||
|
@ -77,7 +79,6 @@ github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW5
|
||||||
github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74 h1:Kk6a4nehpJ3UuJRqlA3JxYxBZEqCeOmATOvrbT4p9RA=
|
github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74 h1:Kk6a4nehpJ3UuJRqlA3JxYxBZEqCeOmATOvrbT4p9RA=
|
||||||
github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4=
|
github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4=
|
||||||
github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
||||||
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
|
||||||
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
|
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
|
||||||
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
|
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
|
||||||
github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss=
|
github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss=
|
||||||
|
@ -97,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/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 h1:m935MPodAbYS46DG4pJSv7WO+VECIWUQ7OJYSoTrMh4=
|
||||||
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI=
|
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI=
|
||||||
github.com/blevesearch/bleve/v2 v2.4.1 h1:8QWqsifq693mN3h6cSigKqkKUsUfv5hu0FDgz/4bFuA=
|
github.com/blevesearch/bleve/v2 v2.4.3 h1:XDYj+1prgX84L2Cf+V3ojrOPqXxy0qxyd2uLMmeuD+4=
|
||||||
github.com/blevesearch/bleve/v2 v2.4.1/go.mod h1:Ezmvsouspi+uVwnDzjIsCeUIT0WuBKlicP5JZnExWzo=
|
github.com/blevesearch/bleve/v2 v2.4.3/go.mod h1:hEPDPrbYw3vyrm5VOa36GyS4bHWuIf4Fflp7460QQXY=
|
||||||
github.com/blevesearch/bleve_index_api v1.1.9 h1:Cpq0Lp3As0Gfk3+PmcoNDRKeI50C5yuFNpj0YlN/bOE=
|
github.com/blevesearch/bleve_index_api v1.1.12 h1:P4bw9/G/5rulOF7SJ9l4FsDoo7UFJ+5kexNy1RXfegY=
|
||||||
github.com/blevesearch/bleve_index_api v1.1.9/go.mod h1:PbcwjIcRmjhGbkS/lJCpfgVSMROV6TRubGGAODaK1W8=
|
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 h1:paaSpu2Ewh/tn5DKn/FB5SzvH0EWupxHEIwbCk/QPqM=
|
||||||
github.com/blevesearch/geo v0.1.20/go.mod h1:DVG2QjwHNMFmjo+ZgzrIq2sfCh6rIHzy9d9d0B59I6w=
|
github.com/blevesearch/geo v0.1.20/go.mod h1:DVG2QjwHNMFmjo+ZgzrIq2sfCh6rIHzy9d9d0B59I6w=
|
||||||
github.com/blevesearch/go-faiss v1.0.19 h1:UKoP8hS7DVsVSRRloNJb4qPfe2UQ99pP4D3oXd23g2A=
|
github.com/blevesearch/go-faiss v1.0.23 h1:Wmc5AFwDLKGl2L6mjLX1Da3vCL0EKa2uHHSorcIS1Uc=
|
||||||
github.com/blevesearch/go-faiss v1.0.19/go.mod h1:jrxHrbl42X/RnDPI+wBoZU8joxxuRwedrxqswQ3xfU8=
|
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 h1:GtmsqID0aZdCSNiY8SkuPJ12pD4jI+DdXTAn4YRcHCo=
|
||||||
github.com/blevesearch/go-porterstemmer v1.0.3/go.mod h1:angGc5Ht+k2xhJdZi511LtmxuEf0OVpvUUNrwmM1P7M=
|
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 h1:2JWigFrzDMR+42WGIN/V2p0cUvn4UP3C4Q5nmaZGW8Y=
|
||||||
github.com/blevesearch/gtreap v0.1.1/go.mod h1:QaQyDRAT51sotthUWAH4Sj08awFSSWzgYICSZ3w0tYk=
|
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 h1:OVhDhT5B/M1HNPpYPBKIEJaD0F3Si+CrEKULGCDPWmc=
|
||||||
github.com/blevesearch/mmap-go v1.0.4/go.mod h1:EWmEAOmdAS9z/pi/+Toxu99DnsbhG1TIxUoRmJw/pSs=
|
github.com/blevesearch/mmap-go v1.0.4/go.mod h1:EWmEAOmdAS9z/pi/+Toxu99DnsbhG1TIxUoRmJw/pSs=
|
||||||
github.com/blevesearch/scorch_segment_api/v2 v2.2.14 h1:fgMLMpGWR7u2TdRm7XSZVWhPvMAcdYHh25Lq1fQ6Fjo=
|
github.com/blevesearch/scorch_segment_api/v2 v2.2.16 h1:uGvKVvG7zvSxCwcm4/ehBa9cCEuZVE+/zvrSl57QUVY=
|
||||||
github.com/blevesearch/scorch_segment_api/v2 v2.2.14/go.mod h1:B7+a7vfpY4NsjuTkpv/eY7RZ91Xr90VaJzT2t7upZN8=
|
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 h1:+dThDy+Lvgj5JMxhmOVlgFfkUtZV2kw49xax4+jTfSU=
|
||||||
github.com/blevesearch/segment v0.9.1/go.mod h1:zN21iLm7+GnBHWTao9I+Au/7MBiL8pPFtJBJTsk6kQw=
|
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=
|
github.com/blevesearch/snowballstem v0.9.0 h1:lMQ189YspGP6sXvZQ4WZ+MLawfV8wOmPoD/iWeNXm8s=
|
||||||
|
@ -129,27 +130,26 @@ 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/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 h1:SG6xlsL+W6YjhX5N3aEiL/2tcWh3DO75Bnz77pSwwKU=
|
||||||
github.com/blevesearch/zapx/v14 v14.3.10/go.mod h1:qqyuR0u230jN1yMmE4FIAuCxmahRQEOehF78m6oTgns=
|
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.16 h1:Ct3rv7FUJPfPk99TI/OofdC+Kpb4IdyfdMH48sb+FmE=
|
||||||
github.com/blevesearch/zapx/v15 v15.3.13/go.mod h1:Turk/TNRKj9es7ZpKK95PS7f6D44Y7fAFy8F4LXQtGg=
|
github.com/blevesearch/zapx/v15 v15.3.16/go.mod h1:Turk/TNRKj9es7ZpKK95PS7f6D44Y7fAFy8F4LXQtGg=
|
||||||
github.com/blevesearch/zapx/v16 v16.1.4 h1:TBQfG77g2UUXwfjOVcEtB9pXkg6JBmGXkeZKI67+TiA=
|
github.com/blevesearch/zapx/v16 v16.1.8 h1:Bxzpw6YQpFs7UjoCV1+RvDw6fmAT2GZxldwX8b3wVBM=
|
||||||
github.com/blevesearch/zapx/v16 v16.1.4/go.mod h1:+Q+Z89Iv7ewhdX2jyE6Qs/RUnN4tZuokaQ0xvTaFmx8=
|
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-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 h1:NDBbPmhS+EqABEs5Kg3n/5ZNjy73Pz7SIV+KCeqyXcs=
|
||||||
github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||||
github.com/bradfitz/gomemcache v0.0.0-20190329173943-551aad21a668/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
|
|
||||||
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 h1:N7oVaKyGp8bttX0bfZGmcGkjz7DLQXhAn3DNd3T0ous=
|
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 h1:N7oVaKyGp8bttX0bfZGmcGkjz7DLQXhAn3DNd3T0ous=
|
||||||
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874/go.mod h1:r5xuitiExdLAJ09PR7vBVENGvp4ZuTBeWTGtxuX3K+c=
|
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874/go.mod h1:r5xuitiExdLAJ09PR7vBVENGvp4ZuTBeWTGtxuX3K+c=
|
||||||
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
|
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/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 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
|
||||||
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
|
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
|
||||||
github.com/buildkite/terminal-to-html/v3 v3.14.0 h1:mW+Lvhn1uEfbH4jsg4m0wfgquq2o3S14xtJD4M7tk8k=
|
github.com/buildkite/terminal-to-html/v3 v3.16.4 h1:QFYO8IGvRnp7tGgiQb8g9uFU8kY9wOzxsFFx17+yy6Q=
|
||||||
github.com/buildkite/terminal-to-html/v3 v3.14.0/go.mod h1:33sojHDaRBSMwwkKXPEkb5Uc7LKF79rWGurL3ei/GX0=
|
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/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.4 h1:e7VobB8rffHv8ZZpSiZtEwnLDHUwLVYLWzWSa1FfKI0=
|
||||||
github.com/caddyserver/certmagic v0.21.0/go.mod h1:OgUZNXYV/ylYoFJNmoYVR5nntydLNMQISePPgqZTyhc=
|
github.com/caddyserver/certmagic v0.21.4/go.mod h1:swUXjQ1T9ZtMv95qj7/InJvWLXURU85r+CfG0T+ZbDE=
|
||||||
github.com/caddyserver/zerossl v0.1.2 h1:tlEu1VzWGoqcCpivs9liKAKhfpJWYJkHEMmlxRbVAxE=
|
github.com/caddyserver/zerossl v0.1.3 h1:onS+pxp3M8HnHpN5MMbOMyNjmTheJyWRaZYwn+YTAyA=
|
||||||
github.com/caddyserver/zerossl v0.1.2/go.mod h1:wtiJEHbdvunr40ZzhXlnIkOB8Xj4eKtBKizCcZitJiQ=
|
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 h1:MISbI8sU/PSK/ztvmWKFcI7UGb5/HQT7B+i3a2myKgI=
|
||||||
github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a/go.mod h1:2GxOXOlEPAMFPfp014mK1SWq8G8BN8o7/dfYqJrVGn8=
|
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=
|
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||||
|
@ -163,18 +163,11 @@ github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwys
|
||||||
github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk=
|
github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk=
|
||||||
github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8=
|
github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8=
|
||||||
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
|
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
|
||||||
github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
|
github.com/cloudflare/circl v1.3.8 h1:j+V8jJt09PoeMFIu2uh5JUyEaIHTXVOHslFoLNAKqwI=
|
||||||
github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
|
github.com/cloudflare/circl v1.3.8/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZFnBQS5QU=
|
||||||
github.com/couchbase/go-couchbase v0.1.1 h1:ClFXELcKj/ojyoTYbsY34QUrrYCBi/1G749sXSCkdhk=
|
github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
|
||||||
github.com/couchbase/go-couchbase v0.1.1/go.mod h1:+/bddYDxXsf9qt0xpDUtRR47A2GjaXmGGAqQ/k3GJ8A=
|
github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
github.com/couchbase/gomemcached v0.3.0 h1:XkMDdP6w7rtvLijDE0/RhcccX+XvAk5cboyBv1YcI0U=
|
|
||||||
github.com/couchbase/gomemcached v0.3.0/go.mod h1:mxliKQxOv84gQ0bJWbI+w9Wxdpt9HjDvgW9MjCym5Vo=
|
|
||||||
github.com/couchbase/goutils v0.1.2 h1:gWr8B6XNWPIhfalHNog3qQKfGiYyh4K4VhO3P2o9BCs=
|
|
||||||
github.com/couchbase/goutils v0.1.2/go.mod h1:h89Ek/tiOxxqjz30nPPlwZdQbdB8BwgnuBxeoUe/ViE=
|
|
||||||
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/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76/go.mod h1:vYwsqCOLxGiisLwp9rITslkFNpZD5rz43tf41QFkTWY=
|
|
||||||
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
|
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
|
||||||
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
|
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
@ -197,14 +190,14 @@ github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55k
|
||||||
github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||||
github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
|
github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
|
||||||
github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||||
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 h1:iFaUwBSo5Svw6L7HYpRu/0lE3e0BaElwnNO1qkNQxBY=
|
|
||||||
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s=
|
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s=
|
||||||
|
github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 h1:2tV76y6Q9BB+NEBasnqvs7e49aEBFI8ejC89PSnWH+4=
|
||||||
|
github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s=
|
||||||
github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
|
github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
|
||||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||||
github.com/editorconfig/editorconfig-core-go/v2 v2.6.2 h1:dKG8sc7n321deIVRcQtwlMNoBEra7j0qQ8RwxO8RN0w=
|
github.com/editorconfig/editorconfig-core-go/v2 v2.6.2 h1:dKG8sc7n321deIVRcQtwlMNoBEra7j0qQ8RwxO8RN0w=
|
||||||
github.com/editorconfig/editorconfig-core-go/v2 v2.6.2/go.mod h1:7dvD3GCm7eBw53xZ/lsiq72LqobdMg3ITbMBxnmJmqY=
|
github.com/editorconfig/editorconfig-core-go/v2 v2.6.2/go.mod h1:7dvD3GCm7eBw53xZ/lsiq72LqobdMg3ITbMBxnmJmqY=
|
||||||
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
|
||||||
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU=
|
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU=
|
||||||
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
|
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
|
||||||
github.com/emersion/go-imap v1.2.1 h1:+s9ZjMEjOB8NzZMVTM3cCenz2JrQIGGo5j1df19WjTA=
|
github.com/emersion/go-imap v1.2.1 h1:+s9ZjMEjOB8NzZMVTM3cCenz2JrQIGGo5j1df19WjTA=
|
||||||
|
@ -218,8 +211,8 @@ github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc
|
||||||
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
|
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
|
||||||
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||||
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
|
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
|
||||||
github.com/felixge/fgprof v0.9.4 h1:ocDNwMFlnA0NU0zSB3I52xkO4sFXk80VK9lXjLClu88=
|
github.com/felixge/fgprof v0.9.5 h1:8+vR6yu2vvSKn08urWyEuxx75NWPEvybbkBirEpsbVY=
|
||||||
github.com/felixge/fgprof v0.9.4/go.mod h1:yKl+ERSa++RYOs32d8K6WEXCB4uXdLls4ZaZPpayhMM=
|
github.com/felixge/fgprof v0.9.5/go.mod h1:yKl+ERSa++RYOs32d8K6WEXCB4uXdLls4ZaZPpayhMM=
|
||||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||||
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
|
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
|
||||||
|
@ -228,10 +221,10 @@ 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/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.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.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
|
||||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||||
github.com/fxamacker/cbor/v2 v2.5.0 h1:oHsG0V/Q6E/wqTS2O1Cozzsy69nqCiguo5Q1a1ADivE=
|
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
|
||||||
github.com/fxamacker/cbor/v2 v2.5.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo=
|
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
|
||||||
github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE=
|
github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE=
|
||||||
github.com/gliderlabs/ssh v0.3.7/go.mod h1:zpHEXBstFnQYtGnB8k8kQLol82umzn/2/snG7alWVD8=
|
github.com/gliderlabs/ssh v0.3.7/go.mod h1:zpHEXBstFnQYtGnB8k8kQLol82umzn/2/snG7alWVD8=
|
||||||
github.com/go-ap/activitypub v0.0.0-20231114162308-e219254dc5c9 h1:j2TrkUG/NATGi/EQS+MvEoF79CxiRUmT16ErFroNcKI=
|
github.com/go-ap/activitypub v0.0.0-20231114162308-e219254dc5c9 h1:j2TrkUG/NATGi/EQS+MvEoF79CxiRUmT16ErFroNcKI=
|
||||||
|
@ -243,14 +236,14 @@ github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73/go.mod h1:jyveZeGw5La
|
||||||
github.com/go-asn1-ber/asn1-ber v1.5.5 h1:MNHlNMBDgEKD4TcKr36vQN68BA00aDfjIt3/bD50WnA=
|
github.com/go-asn1-ber/asn1-ber v1.5.5 h1:MNHlNMBDgEKD4TcKr36vQN68BA00aDfjIt3/bD50WnA=
|
||||||
github.com/go-asn1-ber/asn1-ber v1.5.5/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
github.com/go-asn1-ber/asn1-ber v1.5.5/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||||
github.com/go-chi/chi/v5 v5.0.1/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
github.com/go-chi/chi/v5 v5.0.1/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||||
github.com/go-chi/chi/v5 v5.0.14 h1:PyEwo2Vudraa0x/Wl6eDRRW2NXBvekgfxyydcM0WGE0=
|
github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw=
|
||||||
github.com/go-chi/chi/v5 v5.0.14/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||||
github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4=
|
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-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 h1:ZYDJGtQ4OMhTLKOKMIch+/CY70Brbb1dGdooLEhh7b0=
|
||||||
github.com/go-co-op/gocron v1.37.0/go.mod h1:3L/n6BkO7ABj+TrfSVXLRzsP26zmikL4ISkLQ0O8iNY=
|
github.com/go-co-op/gocron v1.37.0/go.mod h1:3L/n6BkO7ABj+TrfSVXLRzsP26zmikL4ISkLQ0O8iNY=
|
||||||
github.com/go-enry/go-enry/v2 v2.8.8 h1:EhfxWpw4DQ3WEFB1Y77X8vKqZL0D0EDUUWYDUAIv9/4=
|
github.com/go-enry/go-enry/v2 v2.9.1 h1:G9iDteJ/Mc0F4Di5NeQknf83R2OkRbwY9cAYmcqVG6U=
|
||||||
github.com/go-enry/go-enry/v2 v2.8.8/go.mod h1:9yrj4ES1YrbNb1Wb7/PWYr2bpaCXUGRt0uafN0ISyG8=
|
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 h1:k8aAMuJfMrqm/56SG2lV9Cfti6tC4x8673aHCcBk+eo=
|
||||||
github.com/go-enry/go-oniguruma v1.2.1/go.mod h1:bWDhYP+S6xZQgiRL7wlTScFYBe023B6ilRZbCAD5Hf4=
|
github.com/go-enry/go-oniguruma v1.2.1/go.mod h1:bWDhYP+S6xZQgiRL7wlTScFYBe023B6ilRZbCAD5Hf4=
|
||||||
github.com/go-faster/city v1.0.1 h1:4WAxSZ3V2Ws4QRDrscLEDcibJY8uf41H6AhXDrNDcGw=
|
github.com/go-faster/city v1.0.1 h1:4WAxSZ3V2Ws4QRDrscLEDcibJY8uf41H6AhXDrNDcGw=
|
||||||
|
@ -294,8 +287,6 @@ github.com/go-openapi/swag v0.22.7 h1:JWrc1uc/P9cSomxfnsFSVWoE1FW6bNbrVPmpQYpCcR
|
||||||
github.com/go-openapi/swag v0.22.7/go.mod h1:Gl91UqO+btAM0plGGxHqJcQZ1ZTy6jbmridBTsDy8A0=
|
github.com/go-openapi/swag v0.22.7/go.mod h1:Gl91UqO+btAM0plGGxHqJcQZ1ZTy6jbmridBTsDy8A0=
|
||||||
github.com/go-openapi/validate v0.22.6 h1:+NhuwcEYpWdO5Nm4bmvhGLW0rt1Fcc532Mu3wpypXfo=
|
github.com/go-openapi/validate v0.22.6 h1:+NhuwcEYpWdO5Nm4bmvhGLW0rt1Fcc532Mu3wpypXfo=
|
||||||
github.com/go-openapi/validate v0.22.6/go.mod h1:eaddXSqKeTg5XpSmj1dYyFTK/95n/XHwcOY+BMxKMyM=
|
github.com/go-openapi/validate v0.22.6/go.mod h1:eaddXSqKeTg5XpSmj1dYyFTK/95n/XHwcOY+BMxKMyM=
|
||||||
github.com/go-redis/redis v6.15.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
|
|
||||||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
|
||||||
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
||||||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||||
github.com/go-swagger/go-swagger v0.30.5 h1:SQ2+xSonWjjoEMOV5tcOnZJVlfyUfCBhGQGArS1b9+U=
|
github.com/go-swagger/go-swagger v0.30.5 h1:SQ2+xSonWjjoEMOV5tcOnZJVlfyUfCBhGQGArS1b9+U=
|
||||||
|
@ -303,21 +294,19 @@ 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 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-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-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.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U=
|
||||||
github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
|
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 h1:Ew0+c2o1mXSUqMwjuNup3MK/vw1HkLS3ILljX5C6lVE=
|
||||||
github.com/go-testfixtures/testfixtures/v3 v3.12.0/go.mod h1:13F0m6/DtqqSDso9IAVuhbZ4I7AiRAHrolmDMu9v5vY=
|
github.com/go-testfixtures/testfixtures/v3 v3.12.0/go.mod h1:13F0m6/DtqqSDso9IAVuhbZ4I7AiRAHrolmDMu9v5vY=
|
||||||
github.com/go-webauthn/webauthn v0.10.0 h1:yuW2e1tXnRAwAvKrR4q4LQmc6XtCMH639/ypZGhZCwk=
|
github.com/go-webauthn/webauthn v0.11.2 h1:Fgx0/wlmkClTKlnOsdOQ+K5HcHDsDcYIvtYmfhEOSUc=
|
||||||
github.com/go-webauthn/webauthn v0.10.0/go.mod h1:l0NiauXhL6usIKqNLCUM3Qir43GK7ORg8ggold0Uv/Y=
|
github.com/go-webauthn/webauthn v0.11.2/go.mod h1:aOtudaF94pM71g3jRwTYYwQTG1KyTILTcZqN1srkmD0=
|
||||||
github.com/go-webauthn/x v0.1.6 h1:QNAX+AWeqRt9loE8mULeWJCqhVG5D/jvdmJ47fIWCkQ=
|
github.com/go-webauthn/x v0.1.14 h1:1wrB8jzXAofojJPAaRxnZhRgagvLGnLjhCAwg3kTpT0=
|
||||||
github.com/go-webauthn/x v0.1.6/go.mod h1:W8dFVZ79o4f+nY1eOUICy/uq5dhrRl7mxQkYhXTo0FA=
|
github.com/go-webauthn/x v0.1.14/go.mod h1:UuVvFZ8/NbOnkDz3y1NaxtUN87pmtpC1PQ+/5BBQRdc=
|
||||||
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
|
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
|
||||||
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
|
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
|
||||||
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
|
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/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
|
||||||
github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY=
|
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/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 h1:3BSP1Tbs2djlpprl7wCLuiqMaUh5SJkkzI2gDs+FgLs=
|
||||||
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f/go.mod h1:Pcatq5tYkCW2Q6yrR2VRHlbHpZ/R4/7qyL1TCF7vl14=
|
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f/go.mod h1:Pcatq5tYkCW2Q6yrR2VRHlbHpZ/R4/7qyL1TCF7vl14=
|
||||||
|
@ -325,8 +314,8 @@ github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85 h1:UjoPNDAQ5JP
|
||||||
github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85/go.mod h1:fR6z1Ie6rtF7kl/vBYMfgD5/G5B1blui7z426/sj2DU=
|
github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85/go.mod h1:fR6z1Ie6rtF7kl/vBYMfgD5/G5B1blui7z426/sj2DU=
|
||||||
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
|
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
|
||||||
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||||
github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw=
|
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
|
||||||
github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
|
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
|
||||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||||
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
|
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
|
||||||
|
@ -336,7 +325,6 @@ github.com/golang/geo v0.0.0-20230421003525-6adc56603217/go.mod h1:8wI0hitZ3a1Ix
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
|
||||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||||
|
@ -351,6 +339,8 @@ github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW
|
||||||
github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
|
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
|
||||||
|
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
@ -358,27 +348,23 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/go-github/v57 v57.0.0 h1:L+Y3UPTY8ALM8x+TV0lg+IEBI+upibemtBD8Q9u7zHs=
|
github.com/google/go-github/v64 v64.0.0 h1:4G61sozmY3eiPAjjoOHponXDBONm+utovTKbyUb2Qdg=
|
||||||
github.com/google/go-github/v57 v57.0.0/go.mod h1:s0omdnye0hvK/ecLvpsGfJMiRt85PimQh4oygmLIxHw=
|
github.com/google/go-github/v64 v64.0.0/go.mod h1:xB3vqMQNdHzilXBiO2I+M7iEFtHf+DP/omBOv6tQzVo=
|
||||||
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
||||||
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
||||||
github.com/google/go-tpm v0.9.0 h1:sQF6YqWMi+SCXpsmS3fd21oPy/vSddwZry4JnmltHVk=
|
github.com/google/go-tpm v0.9.1 h1:0pGc4X//bAlmZzMKf8iz6IsDo1nYTbYJ6FZN/rg4zdM=
|
||||||
github.com/google/go-tpm v0.9.0/go.mod h1:FkNVkc6C+IsvDI9Jw1OveJmxGZUUaKxtrpOS47QWKfU=
|
github.com/google/go-tpm v0.9.1/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
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/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-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-20241017200806-017d972448fc h1:NGyrhhFhwvRAZg02jnYVg3GBQy0qGBKmFQJwaPmpmxs=
|
||||||
github.com/google/pprof v0.0.0-20240528025155-186aa0362fba/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
|
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.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.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99 h1:twflg0XRTjwKpxb/jFExr4HGq6on2dEOmnL6FV+fgPw=
|
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
|
||||||
github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
|
github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
|
||||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||||
github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8=
|
github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8=
|
||||||
|
@ -391,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/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 h1:LqbZZ9sNMWVjeXS4NN5oVvhMjDyLhmA1LG86oSo+IqY=
|
||||||
github.com/gorilla/pat v0.0.0-20180118222023-199c85a7f6d1/go.mod h1:YeAe0gNeiNT5hoiZRI4yiOky6jVdNvfO2N6Kav/HmxY=
|
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 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA=
|
||||||
github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo=
|
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.4.0 h1:kpIYOp/oi6MG/p5PgxApU8srsSw9tuFbt46Lt7auzqQ=
|
||||||
github.com/gorilla/sessions v1.2.2 h1:lqzMYz6bOfvn2WriPUjNByzeXIlVzURcPmgMczkmTjY=
|
github.com/gorilla/sessions v1.4.0/go.mod h1:FLWm50oby91+hl7p/wRxDth9bWSuk0qVL2emc7lT5ik=
|
||||||
github.com/gorilla/sessions v1.2.2/go.mod h1:ePLdVu+jbEgHH+KWw8I1z2wqd0BAdAQh/8LRvBeoNcQ=
|
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 h1:K6ol8rfrRkUOefooBC8elXoaNGYkpp7y2qcxGG6BzUE=
|
||||||
github.com/h2non/gock v1.2.0/go.mod h1:tNhoxHYW2W42cYkYb1WqzdbYIieALC99kpYr7rH/BQk=
|
github.com/h2non/gock v1.2.0/go.mod h1:tNhoxHYW2W42cYkYb1WqzdbYIieALC99kpYr7rH/BQk=
|
||||||
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
|
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
|
||||||
|
@ -443,17 +429,14 @@ 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/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 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc=
|
||||||
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
|
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
|
||||||
github.com/jhillyerd/enmime v1.2.0 h1:dIu1IPEymQgoT2dzuB//ttA/xcV40NMPpQtmd4wslHk=
|
github.com/jhillyerd/enmime/v2 v2.0.0 h1:I39PYf0peLGroKq+uX2yGB1ExH/78HcRJy4VmERQAVk=
|
||||||
github.com/jhillyerd/enmime v1.2.0/go.mod h1:FRFuUPCLh8PByQv+8xRcLO9QHqaqTqreYhopv5eyk4I=
|
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 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||||
github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
|
||||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
|
||||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
|
||||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
|
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
|
||||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||||
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
|
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
|
||||||
|
@ -462,15 +445,11 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
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.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||||
github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
|
||||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||||
github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
||||||
github.com/klauspost/compress v1.15.6/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
|
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
||||||
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
|
|
||||||
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
|
||||||
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
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.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 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM=
|
||||||
github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||||
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
||||||
|
@ -485,14 +464,13 @@ 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.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 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
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/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs=
|
||||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
|
||||||
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||||
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||||
github.com/libdns/libdns v0.2.2 h1:O6ws7bAfRPaBsgAYt8MDe2HcNBGC29hkZ9MX2eUSX3s=
|
github.com/libdns/libdns v0.2.2 h1:O6ws7bAfRPaBsgAYt8MDe2HcNBGC29hkZ9MX2eUSX3s=
|
||||||
github.com/libdns/libdns v0.2.2/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ=
|
github.com/libdns/libdns v0.2.2/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ=
|
||||||
github.com/lunny/log v0.0.0-20160921050905-7887c61bf0de/go.mod h1:3q8WtuPQsoRbatJuy3nvq/hRSvuBJrHHr+ybPPiNvHQ=
|
|
||||||
github.com/lunny/nodb v0.0.0-20160621015157-fc1ef06ad4af/go.mod h1:Cqz6pqow14VObJ7peltM+2n3PWOz7yTrfUuGbVFkzN0=
|
|
||||||
github.com/lunny/vfsgen v0.0.0-20220105142115-2c99e1ffdfa0 h1:F/3FfGmKdiKFa8kL3YrpZ7pe9H4l4AzA1pbaOUnRvPI=
|
github.com/lunny/vfsgen v0.0.0-20220105142115-2c99e1ffdfa0 h1:F/3FfGmKdiKFa8kL3YrpZ7pe9H4l4AzA1pbaOUnRvPI=
|
||||||
github.com/lunny/vfsgen v0.0.0-20220105142115-2c99e1ffdfa0/go.mod h1:JEfTc3+2DF9Z4PXhLLvXL42zexJyh8rIq3OzUj/0rAk=
|
github.com/lunny/vfsgen v0.0.0-20220105142115-2c99e1ffdfa0/go.mod h1:JEfTc3+2DF9Z4PXhLLvXL42zexJyh8rIq3OzUj/0rAk=
|
||||||
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
|
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
|
||||||
|
@ -509,23 +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 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
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.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||||
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||||
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||||
github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM=
|
||||||
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
|
github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||||
github.com/mattn/go-sqlite3 v1.14.22/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.26.1 h1:3bmo2uLijX7kvBmiZ9LupVfC95TFcRJDgrRTzbOoE4A=
|
github.com/meilisearch/meilisearch-go v0.29.0/go.mod h1:2cRCAn4ddySUsFfNDLVPod/plRibQsJkXF/4gLhxbOk=
|
||||||
github.com/meilisearch/meilisearch-go v0.26.1/go.mod h1:SxuSqDcPBIykjWz1PX+KzsYzArNLSCadQodWs8extS0=
|
github.com/mholt/acmez/v2 v2.0.3 h1:CgDBlEwg3QBp6s45tPQmFIBrkRIkBT4rW4orMM6p4sw=
|
||||||
github.com/mholt/acmez/v2 v2.0.1 h1:3/3N0u1pLjMK4sNEAFSI+bcvzbPhRpY383sy1kLHJ6k=
|
github.com/mholt/acmez/v2 v2.0.3/go.mod h1:pQ1ysaDeGrIMvJ9dfJMk5kJNkn7L2sb3UhyrX6Q91cw=
|
||||||
github.com/mholt/acmez/v2 v2.0.1/go.mod h1:fX4c9r5jYwMyMsC+7tkYRxHibkOTgta5DIFGoe67e1U=
|
|
||||||
github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk=
|
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/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.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ=
|
||||||
github.com/miekg/dns v1.1.59/go.mod h1:nZpewl5p6IvctfgrckopVx2OlSEHPRO/U4SYkRklrEk=
|
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 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
|
||||||
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
|
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.78 h1:LqW2zy52fxnI4gg8C2oZviTaKHcBV36scS+RzJnxUFs=
|
||||||
github.com/minio/minio-go/v7 v7.0.74/go.mod h1:qydcVzV8Hqtj1VtEocfxbmVFa2siu6HGa+LDEPogjD8=
|
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.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
|
||||||
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
|
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=
|
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
|
||||||
|
@ -546,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/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 h1:mYfjlvN2KYs2Pb9G6nb/1f/nPfAttT/Jee5Sq9r3bGE=
|
||||||
github.com/msteinert/pam v1.2.0/go.mod h1:d2n0DCUK8rGecChV3JzvmsDjOY4R7AYbsNxAT+ftQl0=
|
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 h1:W6apQkHrMkS0Muv8G/TipAy/FJl/rCYT0+EuS8+Z0z4=
|
||||||
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
|
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=
|
github.com/niklasfasching/go-org v1.7.0 h1:vyMdcMWWTe/XmANk19F4k8XGBYg0GQ/gJGMimOjGMek=
|
||||||
|
@ -564,12 +543,10 @@ github.com/olivere/elastic/v7 v7.0.32 h1:R7CXvbu8Eq+WlsLgxmKVKPox0oOwAE/2T9Si5Bn
|
||||||
github.com/olivere/elastic/v7 v7.0.32/go.mod h1:c7PVmLe3Fxq77PIfY/bZmxY/TAamBhCzZ8xDOE09a9k=
|
github.com/olivere/elastic/v7 v7.0.32/go.mod h1:c7PVmLe3Fxq77PIfY/bZmxY/TAamBhCzZ8xDOE09a9k=
|
||||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
|
||||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||||
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
||||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||||
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
|
||||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||||
github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
|
github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
|
||||||
|
@ -582,7 +559,6 @@ github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzb
|
||||||
github.com/paulmach/orb v0.11.1 h1:3koVegMC4X/WeiXYz9iswopaTwMem53NzTJuTF20JzU=
|
github.com/paulmach/orb v0.11.1 h1:3koVegMC4X/WeiXYz9iswopaTwMem53NzTJuTF20JzU=
|
||||||
github.com/paulmach/orb v0.11.1/go.mod h1:5mULz1xQfs3bmQm63QEJA6lNGujuRafwA5S/EnuLaLU=
|
github.com/paulmach/orb v0.11.1/go.mod h1:5mULz1xQfs3bmQm63QEJA6lNGujuRafwA5S/EnuLaLU=
|
||||||
github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKfDlhJCDw2gY=
|
github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKfDlhJCDw2gY=
|
||||||
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
|
|
||||||
github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI=
|
github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI=
|
||||||
github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
|
github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
|
||||||
github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||||
|
@ -598,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/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 h1:wZvl1TIVxKRThZIBiwOOHOGP/1+nZyWBil9Y2XNEDzg=
|
||||||
github.com/pquerna/otp v1.4.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
|
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.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
|
||||||
github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA=
|
github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
||||||
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
|
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
||||||
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
|
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
||||||
github.com/prometheus/common v0.46.0 h1:doXzt5ybi1HBKpsZOL0sSkaNHJJqkyfEWZGGqqScV0Y=
|
github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc=
|
||||||
github.com/prometheus/common v0.46.0/go.mod h1:Tp0qkxpb9Jsg54QMe+EAmqXkSV7Evdy1BTn+g2pa/hQ=
|
github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8=
|
||||||
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
|
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
|
||||||
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
|
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
||||||
github.com/quasoft/websspi v1.1.2 h1:/mA4w0LxWlE3novvsoEL6BBA1WnjJATbjkh1kFrTidw=
|
github.com/redis/go-redis/v9 v9.7.0 h1:HhLSs+B6O021gwzl+locl0zEDnyNkxMtf/Z3NNBMa9E=
|
||||||
github.com/quasoft/websspi v1.1.2/go.mod h1:HmVdl939dQ0WIXZhyik+ARdI03M6bQzaSEKcgpFmewk=
|
github.com/redis/go-redis/v9 v9.7.0/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw=
|
||||||
github.com/redis/go-redis/v9 v9.5.2 h1:L0L3fcSNReTRGyZ6AqAEN0K56wYeYAwapBIhkvh0f3E=
|
|
||||||
github.com/redis/go-redis/v9 v9.5.2/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
|
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
|
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/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
github.com/rhysd/actionlint v1.6.27 h1:xxwe8YmveBcC8lydW6GoHMGmB6H/MTqUU60F2p10wjw=
|
github.com/rhysd/actionlint v1.6.27 h1:xxwe8YmveBcC8lydW6GoHMGmB6H/MTqUU60F2p10wjw=
|
||||||
|
@ -624,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.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 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
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.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU=
|
||||||
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
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 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
|
github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
|
||||||
|
@ -634,8 +608,8 @@ github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6g
|
||||||
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
|
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
|
||||||
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 h1:PKK9DyHxif4LZo+uQSgXNqs0jj5+xZwwfKHgph2lxBw=
|
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 h1:PKK9DyHxif4LZo+uQSgXNqs0jj5+xZwwfKHgph2lxBw=
|
||||||
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU=
|
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU=
|
||||||
github.com/sassoftware/go-rpmutils v0.2.1-0.20240124161140-277b154961dd h1:KpbqRPDwcAQTyaP+L+YudTRb3CnJlQ64Hfn1SF/zHBA=
|
github.com/sassoftware/go-rpmutils v0.4.0 h1:ojND82NYBxgwrV+mX1CWsd5QJvvEZTKddtCdFLPWhpg=
|
||||||
github.com/sassoftware/go-rpmutils v0.2.1-0.20240124161140-277b154961dd/go.mod h1:TJJQYtLe/BeEmEjelI3b7xNZjzAukEkeWKmoakvaOoI=
|
github.com/sassoftware/go-rpmutils v0.4.0/go.mod h1:3goNWi7PGAT3/dlql2lv3+MSN5jNYPjT5mVcQcIsYzI=
|
||||||
github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys=
|
github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys=
|
||||||
github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
|
github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
|
||||||
github.com/serenize/snaker v0.0.0-20171204205717-a683aaf2d516/go.mod h1:Yow6lPLSAXx2ifx470yD/nUe22Dv5vBvxK/UK9UUTVs=
|
github.com/serenize/snaker v0.0.0-20171204205717-a683aaf2d516/go.mod h1:Yow6lPLSAXx2ifx470yD/nUe22Dv5vBvxK/UK9UUTVs=
|
||||||
|
@ -646,22 +620,11 @@ github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp
|
||||||
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
|
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
|
||||||
github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c h1:aqg5Vm5dwtvL+YgDpBcK1ITf3o96N/K7/wsRXQnUTEs=
|
github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c h1:aqg5Vm5dwtvL+YgDpBcK1ITf3o96N/K7/wsRXQnUTEs=
|
||||||
github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c/go.mod h1:owqhoLW1qZoYLZzLnBw+QkPP9WZnjlSWihhxAJC1+/M=
|
github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c/go.mod h1:owqhoLW1qZoYLZzLnBw+QkPP9WZnjlSWihhxAJC1+/M=
|
||||||
github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw=
|
|
||||||
github.com/siddontang/go-snappy v0.0.0-20140704025258-d8f7bb82a96d/go.mod h1:vq0tzqLRu6TS7Id0wMo2N5QzJoKedVeovOpHjnykSzY=
|
|
||||||
github.com/siddontang/ledisdb v0.0.0-20190202134119-8ceb77e66a92/go.mod h1:mF1DpOSOUiJRMR+FDqaqu3EBqrybQtrDDszLUZ6oxPg=
|
|
||||||
github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z92TR1JKMkLLoaOQk++LVnOKL3ScbJ8GNGA=
|
|
||||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
github.com/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ=
|
github.com/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ=
|
||||||
github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo=
|
github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo=
|
||||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
|
||||||
github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
|
||||||
github.com/smartystreets/assertions v1.1.1 h1:T/YLemO5Yp7KPzS+lVtu+WsHn8yoSwTfItdAd1r3cck=
|
|
||||||
github.com/smartystreets/assertions v1.1.1/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
|
|
||||||
github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s=
|
|
||||||
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 h1:WN9BUFbdyOsSH/XohnWpXOlq9NBD5sGAB2FciQMUEe8=
|
|
||||||
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
|
||||||
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
|
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
|
||||||
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
|
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
|
||||||
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
|
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
|
||||||
|
@ -700,25 +663,16 @@ github.com/toqueteos/webbrowser v1.2.0 h1:tVP/gpK69Fx+qMJKsLE7TD8LuGWPnEV71wBN9r
|
||||||
github.com/toqueteos/webbrowser v1.2.0/go.mod h1:XWoZq4cyp9WeUeak7w7LXRUQf1F1ATJMir8RTqb4ayM=
|
github.com/toqueteos/webbrowser v1.2.0/go.mod h1:XWoZq4cyp9WeUeak7w7LXRUQf1F1ATJMir8RTqb4ayM=
|
||||||
github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||||
github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||||
github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8=
|
github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc=
|
||||||
github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||||
github.com/unknwon/com v0.0.0-20190804042917-757f69c95f3e/go.mod h1:tOOxU81rwgoCLoOVVPHb6T/wt8HZygqH5id+GNnlCXM=
|
github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w=
|
||||||
github.com/unknwon/com v1.0.1 h1:3d1LTxD+Lnf3soQiD4Cp/0BRB+Rsa/+RTvz8GMMzIXs=
|
github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ=
|
||||||
github.com/unknwon/com v1.0.1/go.mod h1:tOOxU81rwgoCLoOVVPHb6T/wt8HZygqH5id+GNnlCXM=
|
|
||||||
github.com/urfave/cli/v2 v2.27.2 h1:6e0H+AkS+zDckwPCUrZkKX38mRaau4nL2uipkJpbkcI=
|
|
||||||
github.com/urfave/cli/v2 v2.27.2/go.mod h1:g0+79LmHHATl7DAcHO99smiR/T7uGLw84w8Y42x+4eM=
|
|
||||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
|
||||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
|
||||||
github.com/valyala/fasthttp v1.37.1-0.20220607072126-8a320890c08d/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I=
|
|
||||||
github.com/valyala/fasthttp v1.51.0 h1:8b30A5JlZ6C7AS81RsWjYMQmrZG6feChmgAolCl1SqA=
|
|
||||||
github.com/valyala/fasthttp v1.51.0/go.mod h1:oI2XroL+lI7vdXyYoQk03bXBThfFl2cVdIA3Xl7cH8g=
|
|
||||||
github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
|
github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
|
||||||
github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
|
github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
|
||||||
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
|
|
||||||
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||||
github.com/xanzy/go-gitlab v0.96.0 h1:LGkZ+wSNMRtHIBaYE4Hq3dZVjprwHv3Y1+rhKU3WETs=
|
github.com/xanzy/go-gitlab v0.109.0 h1:RcRme5w8VpLXTSTTMZdVoQWY37qTJWg+gwdQl4aAttE=
|
||||||
github.com/xanzy/go-gitlab v0.96.0/go.mod h1:ETg8tcj4OhrB84UEgeE8dSuV/0h4BBL1uOV/qK0vlyI=
|
github.com/xanzy/go-gitlab v0.109.0/go.mod h1:wKNKh3GkYDMOsGmnfuX+ITCmDuSDWFO0G+C4AygL9RY=
|
||||||
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
|
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
|
||||||
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
|
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
|
||||||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||||
|
@ -728,8 +682,8 @@ github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgk
|
||||||
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
|
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
|
||||||
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo=
|
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo=
|
||||||
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
|
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
|
||||||
github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 h1:+qGGcbkzsfDQNPPe9UDgpxAWQrhbbBXOYJFQDq/dtJw=
|
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4=
|
||||||
github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913/go.mod h1:4aEEwZQutDLsQv2Deui4iYQ6DWTxR14g6m8Wv88+Xqk=
|
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
|
||||||
github.com/yohcop/openid-go v1.0.1 h1:DPRd3iPO5F6O5zX2e62XpVAbPT6wV51cuucH0z9g3js=
|
github.com/yohcop/openid-go v1.0.1 h1:DPRd3iPO5F6O5zX2e62XpVAbPT6wV51cuucH0z9g3js=
|
||||||
github.com/yohcop/openid-go v1.0.1/go.mod h1:b/AvD03P0KHj4yuihb+VtLD6bYYgsy0zqBzPCRjkCNs=
|
github.com/yohcop/openid-go v1.0.1/go.mod h1:b/AvD03P0KHj4yuihb+VtLD6bYYgsy0zqBzPCRjkCNs=
|
||||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
|
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
|
||||||
|
@ -738,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.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.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.4.15/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
github.com/yuin/goldmark v1.7.4 h1:BDXOHExt+A7gwPCJgPIIq7ENvceR7we7rOS9TNoLZeg=
|
github.com/yuin/goldmark v1.7.8 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic=
|
||||||
github.com/yuin/goldmark v1.7.4/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
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 h1:+IAOyRda+RLrxa1WC7umKOZRsGq4QrFFMYApOeHzQwQ=
|
||||||
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc/go.mod h1:ovIvrum6DQJA4QsJSovrkC4saKHQVs7TvcaeO8AIl5I=
|
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 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY=
|
||||||
github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
|
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.4 h1:KYQPkhpRtcqh0ssGYcKLG1JYvddkEA8QwCM/yBqhaZI=
|
||||||
github.com/zeebo/blake3 v0.2.3/go.mod h1:mjJjZpnsyIVtVgTOSpJ9vmRE4wgDeyt2HU3qXvvKCaQ=
|
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 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo=
|
||||||
github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4=
|
github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4=
|
||||||
go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI=
|
go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI=
|
||||||
|
@ -760,7 +714,6 @@ go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZu
|
||||||
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||||
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
|
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
|
||||||
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||||
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
|
|
||||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||||
go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
|
go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
|
||||||
|
@ -770,44 +723,36 @@ go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN8
|
||||||
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||||
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
|
||||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
|
||||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||||
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
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.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||||
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||||
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
|
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
|
||||||
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
|
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 h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA=
|
||||||
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
|
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
|
||||||
golang.org/x/image v0.18.0 h1:jGzIakQa/ZXI1I0Fxvaa9W7yP25TqT6cHIHn+6CqvSQ=
|
golang.org/x/image v0.21.0 h1:c5qV36ajHpdj4Qi0GnE0jUc/yuo33OLFaa0d+crTD5s=
|
||||||
golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E=
|
golang.org/x/image v0.21.0/go.mod h1:vUbsLavqK/W303ZroQQVKQ+Af3Yl6Uz1Ppu5J/cLz78=
|
||||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
|
||||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
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.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8=
|
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
|
||||||
golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
|
@ -815,10 +760,10 @@ 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.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
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.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||||
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
|
golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo=
|
||||||
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
|
golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM=
|
||||||
golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs=
|
golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
|
||||||
golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
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=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
@ -826,16 +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-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.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.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
|
||||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
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-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-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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20190730183949-1393eb018365/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/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-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-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-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
@ -846,8 +788,6 @@ golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
@ -861,9 +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.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.12.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.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
|
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
|
||||||
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
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.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||||
|
@ -873,10 +812,9 @@ 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.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||||
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
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.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
||||||
golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk=
|
golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU=
|
||||||
golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4=
|
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.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
|
@ -887,15 +825,11 @@ 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.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.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.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
|
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
|
||||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
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 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
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=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
|
||||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
|
||||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
|
||||||
golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20200325010219-a49f79bcc224/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
golang.org/x/tools v0.0.0-20200325010219-a49f79bcc224/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
||||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
|
@ -903,17 +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.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.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.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg=
|
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
|
||||||
golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI=
|
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-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-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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 h1:Zy9XzmMEflZ/MAaA7vNcoebnRAld7FsPW1EeBB7V0m8=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0=
|
google.golang.org/grpc v1.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0=
|
||||||
google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc=
|
google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA=
|
||||||
google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ=
|
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
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-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||||
|
@ -922,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.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.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.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
|
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
|
||||||
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
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 h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
|
||||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
|
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=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
@ -935,7 +868,6 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE=
|
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE=
|
||||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw=
|
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw=
|
||||||
gopkg.in/ini.v1 v1.44.2/go.mod h1:M3Cogqpuv0QCi3ExAY5V4uOt4qb/R3xZubo9m8lK5wg=
|
|
||||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||||
|
@ -974,9 +906,7 @@ modernc.org/token v1.0.1 h1:A3qvTqOwexpfZZeyI0FeGPDlSWX5pjZu9hF4lU+EKWg=
|
||||||
modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
||||||
mvdan.cc/xurls/v2 v2.5.0 h1:lyBNOm8Wo71UknhUs4QTFUNNMyxy2JEIaKKo0RWOh+8=
|
mvdan.cc/xurls/v2 v2.5.0 h1:lyBNOm8Wo71UknhUs4QTFUNNMyxy2JEIaKKo0RWOh+8=
|
||||||
mvdan.cc/xurls/v2 v2.5.0/go.mod h1:yQgaGQ1rFtJUzkmKiHYSSfuQxqfYmd//X6PxvholpeE=
|
mvdan.cc/xurls/v2 v2.5.0/go.mod h1:yQgaGQ1rFtJUzkmKiHYSSfuQxqfYmd//X6PxvholpeE=
|
||||||
strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251 h1:mUcz5b3FJbP5Cvdq7Khzn6J9OCUQJaBwgBkCR+MOwSs=
|
|
||||||
strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251/go.mod h1:FJGmPh3vz9jSos1L/F91iAgnC/aejc0wIIrF2ZwJxdY=
|
|
||||||
xorm.io/builder v0.3.13 h1:a3jmiVVL19psGeXx8GIurTp7p0IIgqeDmwhcR6BAOAo=
|
xorm.io/builder v0.3.13 h1:a3jmiVVL19psGeXx8GIurTp7p0IIgqeDmwhcR6BAOAo=
|
||||||
xorm.io/builder v0.3.13/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
|
xorm.io/builder v0.3.13/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
|
||||||
xorm.io/xorm v1.3.7 h1:mLceAGu0b87r9pD4qXyxGHxifOXIIrAdVcA6k95/osw=
|
xorm.io/xorm v1.3.9 h1:TUovzS0ko+IQ1XnNLfs5dqK1cJl1H5uHpWbWqAQ04nU=
|
||||||
xorm.io/xorm v1.3.7/go.mod h1:LsCCffeeYp63ssk0pKumP6l96WZcHix7ChpurcLNuMw=
|
xorm.io/xorm v1.3.9/go.mod h1:LsCCffeeYp63ssk0pKumP6l96WZcHix7ChpurcLNuMw=
|
||||||
|
|
|
@ -69,7 +69,7 @@ func CreateArtifact(ctx context.Context, t *ActionTask, artifactName, artifactPa
|
||||||
OwnerID: t.OwnerID,
|
OwnerID: t.OwnerID,
|
||||||
CommitSHA: t.CommitSHA,
|
CommitSHA: t.CommitSHA,
|
||||||
Status: int64(ArtifactStatusUploadPending),
|
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 {
|
if _, err := db.GetEngine(ctx).Insert(artifact); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -78,6 +78,13 @@ func CreateArtifact(ctx context.Context, t *ActionTask, artifactName, artifactPa
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return nil, err
|
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
|
return artifact, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ package actions
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/hex"
|
"crypto/subtle"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
auth_model "code.gitea.io/gitea/models/auth"
|
auth_model "code.gitea.io/gitea/models/auth"
|
||||||
|
@ -14,7 +14,7 @@ import (
|
||||||
gouuid "github.com/google/uuid"
|
gouuid "github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
func RegisterRunner(ctx context.Context, ownerID, repoID int64, token string, labels []string, name, version string) (*ActionRunner, error) {
|
func RegisterRunner(ctx context.Context, ownerID, repoID int64, token string, labels *[]string, name, version string) (*ActionRunner, error) {
|
||||||
uuid, err := gouuid.FromBytes([]byte(token[:16]))
|
uuid, err := gouuid.FromBytes([]byte(token[:16]))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("gouuid.FromBytes %v", err)
|
return nil, fmt.Errorf("gouuid.FromBytes %v", err)
|
||||||
|
@ -26,22 +26,28 @@ func RegisterRunner(ctx context.Context, ownerID, repoID int64, token string, la
|
||||||
has, err := db.GetEngine(ctx).Where("uuid=?", uuidString).Get(&runner)
|
has, err := db.GetEngine(ctx).Where("uuid=?", uuidString).Get(&runner)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("GetRunner %v", err)
|
return nil, fmt.Errorf("GetRunner %v", err)
|
||||||
} else if !has {
|
}
|
||||||
|
|
||||||
|
var mustUpdateSecret bool
|
||||||
|
if has {
|
||||||
|
//
|
||||||
|
// The runner exists, check if the rest of the token has changed.
|
||||||
|
//
|
||||||
|
mustUpdateSecret = subtle.ConstantTimeCompare(
|
||||||
|
[]byte(runner.TokenHash),
|
||||||
|
[]byte(auth_model.HashToken(token, runner.TokenSalt)),
|
||||||
|
) != 1
|
||||||
|
} else {
|
||||||
//
|
//
|
||||||
// The runner does not exist yet, create it
|
// The runner does not exist yet, create it
|
||||||
//
|
//
|
||||||
saltBytes, err := util.CryptoRandomBytes(16)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("CryptoRandomBytes %v", err)
|
|
||||||
}
|
|
||||||
salt := hex.EncodeToString(saltBytes)
|
|
||||||
|
|
||||||
hash := auth_model.HashToken(token, salt)
|
|
||||||
|
|
||||||
runner = ActionRunner{
|
runner = ActionRunner{
|
||||||
UUID: uuidString,
|
UUID: uuidString,
|
||||||
TokenHash: hash,
|
AgentLabels: []string{},
|
||||||
TokenSalt: salt,
|
}
|
||||||
|
|
||||||
|
if err := runner.UpdateSecret(token); err != nil {
|
||||||
|
return &runner, fmt.Errorf("can't set new runner's secret: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := CreateRunner(ctx, &runner); err != nil {
|
if err := CreateRunner(ctx, &runner); err != nil {
|
||||||
|
@ -54,13 +60,23 @@ func RegisterRunner(ctx context.Context, ownerID, repoID int64, token string, la
|
||||||
//
|
//
|
||||||
name, _ = util.SplitStringAtByteN(name, 255)
|
name, _ = util.SplitStringAtByteN(name, 255)
|
||||||
|
|
||||||
|
cols := []string{"name", "owner_id", "repo_id", "version"}
|
||||||
runner.Name = name
|
runner.Name = name
|
||||||
runner.OwnerID = ownerID
|
runner.OwnerID = ownerID
|
||||||
runner.RepoID = repoID
|
runner.RepoID = repoID
|
||||||
runner.Version = version
|
runner.Version = version
|
||||||
runner.AgentLabels = labels
|
if labels != nil {
|
||||||
|
runner.AgentLabels = *labels
|
||||||
|
cols = append(cols, "agent_labels")
|
||||||
|
}
|
||||||
|
if mustUpdateSecret {
|
||||||
|
if err := runner.UpdateSecret(token); err != nil {
|
||||||
|
return &runner, fmt.Errorf("can't change runner's secret: %w", err)
|
||||||
|
}
|
||||||
|
cols = append(cols, "token_hash", "token_salt")
|
||||||
|
}
|
||||||
|
|
||||||
if err := UpdateRunner(ctx, &runner, "name", "owner_id", "repo_id", "version", "agent_labels"); err != nil {
|
if err := UpdateRunner(ctx, &runner, cols...); err != nil {
|
||||||
return &runner, fmt.Errorf("can't update the runner %+v %w", runner, err)
|
return &runner, fmt.Errorf("can't update the runner %+v %w", runner, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,19 +11,168 @@ import (
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestActions_RegisterRunner(t *testing.T) {
|
func TestActions_RegisterRunner_Token(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
ownerID := int64(0)
|
ownerID := int64(0)
|
||||||
repoID := int64(0)
|
repoID := int64(0)
|
||||||
token := "0123456789012345678901234567890123456789"
|
token := "0123456789012345678901234567890123456789"
|
||||||
labels := []string{}
|
labels := []string{}
|
||||||
name := "runner"
|
name := "runner"
|
||||||
version := "v1.2.3"
|
version := "v1.2.3"
|
||||||
runner, err := RegisterRunner(db.DefaultContext, ownerID, repoID, token, labels, name, version)
|
runner, err := RegisterRunner(db.DefaultContext, ownerID, repoID, token, &labels, name, version)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.EqualValues(t, name, runner.Name)
|
assert.EqualValues(t, name, runner.Name)
|
||||||
|
|
||||||
assert.EqualValues(t, 1, subtle.ConstantTimeCompare([]byte(runner.TokenHash), []byte(auth_model.HashToken(token, runner.TokenSalt))), "the token cannot be verified with the same method as routers/api/actions/runner/interceptor.go as of 8228751c55d6a4263f0fec2932ca16181c09c97d")
|
assert.EqualValues(t, 1, subtle.ConstantTimeCompare([]byte(runner.TokenHash), []byte(auth_model.HashToken(token, runner.TokenSalt))), "the token cannot be verified with the same method as routers/api/actions/runner/interceptor.go as of 8228751c55d6a4263f0fec2932ca16181c09c97d")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestActions_RegisterRunner_TokenUpdate tests that a token's secret is updated
|
||||||
|
// when a runner already exists and RegisterRunner is called with a token
|
||||||
|
// parameter whose first 16 bytes match that record but where the last 24 bytes
|
||||||
|
// do not match.
|
||||||
|
func TestActions_RegisterRunner_TokenUpdate(t *testing.T) {
|
||||||
|
const recordID = 12345678
|
||||||
|
oldToken := "7e577e577e577e57feedfacefeedfacefeedface"
|
||||||
|
newToken := "7e577e577e577e57deadbeefdeadbeefdeadbeef"
|
||||||
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
before := unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: recordID})
|
||||||
|
require.Equal(t,
|
||||||
|
before.TokenHash, auth_model.HashToken(oldToken, before.TokenSalt),
|
||||||
|
"the initial token should match the runner's secret",
|
||||||
|
)
|
||||||
|
|
||||||
|
RegisterRunner(db.DefaultContext, before.OwnerID, before.RepoID, newToken, nil, before.Name, before.Version)
|
||||||
|
|
||||||
|
after := unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: recordID})
|
||||||
|
|
||||||
|
assert.Equal(t, before.UUID, after.UUID)
|
||||||
|
assert.NotEqual(t,
|
||||||
|
after.TokenHash, auth_model.HashToken(oldToken, after.TokenSalt),
|
||||||
|
"the old token can still be verified",
|
||||||
|
)
|
||||||
|
assert.Equal(t,
|
||||||
|
after.TokenHash, auth_model.HashToken(newToken, after.TokenSalt),
|
||||||
|
"the new token cannot be verified",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestActions_RegisterRunner_CreateWithLabels(t *testing.T) {
|
||||||
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
ownerID := int64(0)
|
||||||
|
repoID := int64(0)
|
||||||
|
token := "0123456789012345678901234567890123456789"
|
||||||
|
name := "runner"
|
||||||
|
version := "v1.2.3"
|
||||||
|
labels := []string{"woop", "doop"}
|
||||||
|
labelsCopy := labels // labels may be affected by the tested function so we copy them
|
||||||
|
|
||||||
|
runner, err := RegisterRunner(db.DefaultContext, ownerID, repoID, token, &labels, name, version)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Check that the returned record has been updated, except for the labels
|
||||||
|
assert.EqualValues(t, ownerID, runner.OwnerID)
|
||||||
|
assert.EqualValues(t, repoID, runner.RepoID)
|
||||||
|
assert.EqualValues(t, name, runner.Name)
|
||||||
|
assert.EqualValues(t, version, runner.Version)
|
||||||
|
assert.EqualValues(t, labelsCopy, runner.AgentLabels)
|
||||||
|
|
||||||
|
// Check that whatever is in the DB has been updated, except for the labels
|
||||||
|
after := unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: runner.ID})
|
||||||
|
assert.EqualValues(t, ownerID, after.OwnerID)
|
||||||
|
assert.EqualValues(t, repoID, after.RepoID)
|
||||||
|
assert.EqualValues(t, name, after.Name)
|
||||||
|
assert.EqualValues(t, version, after.Version)
|
||||||
|
assert.EqualValues(t, labelsCopy, after.AgentLabels)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestActions_RegisterRunner_CreateWithoutLabels(t *testing.T) {
|
||||||
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
ownerID := int64(0)
|
||||||
|
repoID := int64(0)
|
||||||
|
token := "0123456789012345678901234567890123456789"
|
||||||
|
name := "runner"
|
||||||
|
version := "v1.2.3"
|
||||||
|
|
||||||
|
runner, err := RegisterRunner(db.DefaultContext, ownerID, repoID, token, nil, name, version)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Check that the returned record has been updated, except for the labels
|
||||||
|
assert.EqualValues(t, ownerID, runner.OwnerID)
|
||||||
|
assert.EqualValues(t, repoID, runner.RepoID)
|
||||||
|
assert.EqualValues(t, name, runner.Name)
|
||||||
|
assert.EqualValues(t, version, runner.Version)
|
||||||
|
assert.EqualValues(t, []string{}, runner.AgentLabels)
|
||||||
|
|
||||||
|
// Check that whatever is in the DB has been updated, except for the labels
|
||||||
|
after := unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: runner.ID})
|
||||||
|
assert.EqualValues(t, ownerID, after.OwnerID)
|
||||||
|
assert.EqualValues(t, repoID, after.RepoID)
|
||||||
|
assert.EqualValues(t, name, after.Name)
|
||||||
|
assert.EqualValues(t, version, after.Version)
|
||||||
|
assert.EqualValues(t, []string{}, after.AgentLabels)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestActions_RegisterRunner_UpdateWithLabels(t *testing.T) {
|
||||||
|
const recordID = 12345678
|
||||||
|
token := "7e577e577e577e57feedfacefeedfacefeedface"
|
||||||
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: recordID})
|
||||||
|
|
||||||
|
newOwnerID := int64(1)
|
||||||
|
newRepoID := int64(1)
|
||||||
|
newName := "rennur"
|
||||||
|
newVersion := "v4.5.6"
|
||||||
|
newLabels := []string{"warp", "darp"}
|
||||||
|
labelsCopy := newLabels // labels may be affected by the tested function so we copy them
|
||||||
|
|
||||||
|
runner, err := RegisterRunner(db.DefaultContext, newOwnerID, newRepoID, token, &newLabels, newName, newVersion)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Check that the returned record has been updated
|
||||||
|
assert.EqualValues(t, newOwnerID, runner.OwnerID)
|
||||||
|
assert.EqualValues(t, newRepoID, runner.RepoID)
|
||||||
|
assert.EqualValues(t, newName, runner.Name)
|
||||||
|
assert.EqualValues(t, newVersion, runner.Version)
|
||||||
|
assert.EqualValues(t, labelsCopy, runner.AgentLabels)
|
||||||
|
|
||||||
|
// Check that whatever is in the DB has been updated
|
||||||
|
after := unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: recordID})
|
||||||
|
assert.EqualValues(t, newOwnerID, after.OwnerID)
|
||||||
|
assert.EqualValues(t, newRepoID, after.RepoID)
|
||||||
|
assert.EqualValues(t, newName, after.Name)
|
||||||
|
assert.EqualValues(t, newVersion, after.Version)
|
||||||
|
assert.EqualValues(t, labelsCopy, after.AgentLabels)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestActions_RegisterRunner_UpdateWithoutLabels(t *testing.T) {
|
||||||
|
const recordID = 12345678
|
||||||
|
token := "7e577e577e577e57feedfacefeedfacefeedface"
|
||||||
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
before := unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: recordID})
|
||||||
|
|
||||||
|
newOwnerID := int64(1)
|
||||||
|
newRepoID := int64(1)
|
||||||
|
newName := "rennur"
|
||||||
|
newVersion := "v4.5.6"
|
||||||
|
|
||||||
|
runner, err := RegisterRunner(db.DefaultContext, newOwnerID, newRepoID, token, nil, newName, newVersion)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Check that the returned record has been updated, except for the labels
|
||||||
|
assert.EqualValues(t, newOwnerID, runner.OwnerID)
|
||||||
|
assert.EqualValues(t, newRepoID, runner.RepoID)
|
||||||
|
assert.EqualValues(t, newName, runner.Name)
|
||||||
|
assert.EqualValues(t, newVersion, runner.Version)
|
||||||
|
assert.EqualValues(t, before.AgentLabels, runner.AgentLabels)
|
||||||
|
|
||||||
|
// Check that whatever is in the DB has been updated, except for the labels
|
||||||
|
after := unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: recordID})
|
||||||
|
assert.EqualValues(t, newOwnerID, after.OwnerID)
|
||||||
|
assert.EqualValues(t, newRepoID, after.RepoID)
|
||||||
|
assert.EqualValues(t, newName, after.Name)
|
||||||
|
assert.EqualValues(t, newVersion, after.Version)
|
||||||
|
assert.EqualValues(t, before.AgentLabels, after.AgentLabels)
|
||||||
|
}
|
||||||
|
|
|
@ -146,7 +146,11 @@ func (run *ActionRun) GetPushEventPayload() (*api.PushPayload, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (run *ActionRun) GetPullRequestEventPayload() (*api.PullRequestPayload, 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
|
var payload api.PullRequestPayload
|
||||||
if err := json.Unmarshal([]byte(run.EventPayload), &payload); err != nil {
|
if err := json.Unmarshal([]byte(run.EventPayload), &payload); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -6,10 +6,12 @@ package actions
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
auth_model "code.gitea.io/gitea/models/auth"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/shared/types"
|
"code.gitea.io/gitea/models/shared/types"
|
||||||
|
@ -24,14 +26,25 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// ActionRunner represents runner machines
|
// ActionRunner represents runner machines
|
||||||
|
//
|
||||||
|
// It can be:
|
||||||
|
// 1. global runner, OwnerID is 0 and RepoID is 0
|
||||||
|
// 2. org/user level runner, OwnerID is org/user ID and RepoID is 0
|
||||||
|
// 3. repo level runner, OwnerID is 0 and RepoID is repo ID
|
||||||
|
//
|
||||||
|
// Please note that it's not acceptable to have both OwnerID and RepoID to be non-zero,
|
||||||
|
// or it will be complicated to find runners belonging to a specific owner.
|
||||||
|
// For example, conditions like `OwnerID = 1` will also return runner {OwnerID: 1, RepoID: 1},
|
||||||
|
// but it's a repo level runner, not an org/user level runner.
|
||||||
|
// To avoid this, make it clear with {OwnerID: 0, RepoID: 1} for repo level runners.
|
||||||
type ActionRunner struct {
|
type ActionRunner struct {
|
||||||
ID int64
|
ID int64
|
||||||
UUID string `xorm:"CHAR(36) UNIQUE"`
|
UUID string `xorm:"CHAR(36) UNIQUE"`
|
||||||
Name string `xorm:"VARCHAR(255)"`
|
Name string `xorm:"VARCHAR(255)"`
|
||||||
Version string `xorm:"VARCHAR(64)"`
|
Version string `xorm:"VARCHAR(64)"`
|
||||||
OwnerID int64 `xorm:"index"` // org level runner, 0 means system
|
OwnerID int64 `xorm:"index"`
|
||||||
Owner *user_model.User `xorm:"-"`
|
Owner *user_model.User `xorm:"-"`
|
||||||
RepoID int64 `xorm:"index"` // repo level runner, if OwnerID also is zero, then it's a global
|
RepoID int64 `xorm:"index"`
|
||||||
Repo *repo_model.Repository `xorm:"-"`
|
Repo *repo_model.Repository `xorm:"-"`
|
||||||
Description string `xorm:"TEXT"`
|
Description string `xorm:"TEXT"`
|
||||||
Base int // 0 native 1 docker 2 virtual machine
|
Base int // 0 native 1 docker 2 virtual machine
|
||||||
|
@ -151,6 +164,22 @@ func (r *ActionRunner) GenerateToken() (err error) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateSecret updates the hash based on the specified token. It does not
|
||||||
|
// ensure that the runner's UUID matches the first 16 bytes of the token.
|
||||||
|
func (r *ActionRunner) UpdateSecret(token string) error {
|
||||||
|
saltBytes, err := util.CryptoRandomBytes(16)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("CryptoRandomBytes %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
salt := hex.EncodeToString(saltBytes)
|
||||||
|
|
||||||
|
r.Token = token
|
||||||
|
r.TokenSalt = salt
|
||||||
|
r.TokenHash = auth_model.HashToken(token, salt)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
db.RegisterModel(&ActionRunner{})
|
db.RegisterModel(&ActionRunner{})
|
||||||
}
|
}
|
||||||
|
@ -158,7 +187,7 @@ func init() {
|
||||||
type FindRunnerOptions struct {
|
type FindRunnerOptions struct {
|
||||||
db.ListOptions
|
db.ListOptions
|
||||||
RepoID int64
|
RepoID int64
|
||||||
OwnerID int64
|
OwnerID int64 // it will be ignored if RepoID is set
|
||||||
Sort string
|
Sort string
|
||||||
Filter string
|
Filter string
|
||||||
IsOnline optional.Option[bool]
|
IsOnline optional.Option[bool]
|
||||||
|
@ -175,8 +204,7 @@ func (opts FindRunnerOptions) ToConds() builder.Cond {
|
||||||
c = c.Or(builder.Eq{"repo_id": 0, "owner_id": 0})
|
c = c.Or(builder.Eq{"repo_id": 0, "owner_id": 0})
|
||||||
}
|
}
|
||||||
cond = cond.And(c)
|
cond = cond.And(c)
|
||||||
}
|
} else if opts.OwnerID > 0 { // OwnerID is ignored if RepoID is set
|
||||||
if opts.OwnerID > 0 {
|
|
||||||
c := builder.NewCond().And(builder.Eq{"owner_id": opts.OwnerID})
|
c := builder.NewCond().And(builder.Eq{"owner_id": opts.OwnerID})
|
||||||
if opts.WithAvailable {
|
if opts.WithAvailable {
|
||||||
c = c.Or(builder.Eq{"repo_id": 0, "owner_id": 0})
|
c = c.Or(builder.Eq{"repo_id": 0, "owner_id": 0})
|
||||||
|
@ -279,6 +307,11 @@ func DeleteRunner(ctx context.Context, id int64) error {
|
||||||
|
|
||||||
// CreateRunner creates new runner.
|
// CreateRunner creates new runner.
|
||||||
func CreateRunner(ctx context.Context, t *ActionRunner) error {
|
func CreateRunner(ctx context.Context, t *ActionRunner) error {
|
||||||
|
if t.OwnerID != 0 && t.RepoID != 0 {
|
||||||
|
// It's trying to create a runner that belongs to a repository, but OwnerID has been set accidentally.
|
||||||
|
// Remove OwnerID to avoid confusion; it's not worth returning an error here.
|
||||||
|
t.OwnerID = 0
|
||||||
|
}
|
||||||
return db.Insert(ctx, t)
|
return db.Insert(ctx, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,23 +7,39 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
auth_model "code.gitea.io/gitea/models/auth"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TestUpdateSecret checks that ActionRunner.UpdateSecret() sets the Token,
|
||||||
|
// TokenSalt and TokenHash fields based on the specified token.
|
||||||
|
func TestUpdateSecret(t *testing.T) {
|
||||||
|
runner := ActionRunner{}
|
||||||
|
token := "0123456789012345678901234567890123456789"
|
||||||
|
|
||||||
|
err := runner.UpdateSecret(token)
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, token, runner.Token)
|
||||||
|
assert.Regexp(t, "^[0-9a-f]{32}$", runner.TokenSalt)
|
||||||
|
assert.Equal(t, runner.TokenHash, auth_model.HashToken(token, runner.TokenSalt))
|
||||||
|
}
|
||||||
|
|
||||||
func TestDeleteRunner(t *testing.T) {
|
func TestDeleteRunner(t *testing.T) {
|
||||||
const recordID = 12345678
|
const recordID = 12345678
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
before := unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: recordID})
|
before := unittest.AssertExistsAndLoadBean(t, &ActionRunner{ID: recordID})
|
||||||
|
|
||||||
err := DeleteRunner(db.DefaultContext, recordID)
|
err := DeleteRunner(db.DefaultContext, recordID)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
var after ActionRunner
|
var after ActionRunner
|
||||||
found, err := db.GetEngine(db.DefaultContext).ID(recordID).Unscoped().Get(&after)
|
found, err := db.GetEngine(db.DefaultContext).ID(recordID).Unscoped().Get(&after)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.True(t, found)
|
assert.True(t, found)
|
||||||
|
|
||||||
// Most fields (namely Name, Version, OwnerID, RepoID, Description, Base, RepoRange,
|
// Most fields (namely Name, Version, OwnerID, RepoID, Description, Base, RepoRange,
|
||||||
|
|
|
@ -15,12 +15,23 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// ActionRunnerToken represents runner tokens
|
// ActionRunnerToken represents runner tokens
|
||||||
|
//
|
||||||
|
// It can be:
|
||||||
|
// 1. global token, OwnerID is 0 and RepoID is 0
|
||||||
|
// 2. org/user level token, OwnerID is org/user ID and RepoID is 0
|
||||||
|
// 3. repo level token, OwnerID is 0 and RepoID is repo ID
|
||||||
|
//
|
||||||
|
// Please note that it's not acceptable to have both OwnerID and RepoID to be non-zero,
|
||||||
|
// or it will be complicated to find tokens belonging to a specific owner.
|
||||||
|
// For example, conditions like `OwnerID = 1` will also return token {OwnerID: 1, RepoID: 1},
|
||||||
|
// but it's a repo level token, not an org/user level token.
|
||||||
|
// To avoid this, make it clear with {OwnerID: 0, RepoID: 1} for repo level tokens.
|
||||||
type ActionRunnerToken struct {
|
type ActionRunnerToken struct {
|
||||||
ID int64
|
ID int64
|
||||||
Token string `xorm:"UNIQUE"`
|
Token string `xorm:"UNIQUE"`
|
||||||
OwnerID int64 `xorm:"index"` // org level runner, 0 means system
|
OwnerID int64 `xorm:"index"`
|
||||||
Owner *user_model.User `xorm:"-"`
|
Owner *user_model.User `xorm:"-"`
|
||||||
RepoID int64 `xorm:"index"` // repo level runner, if orgid also is zero, then it's a global
|
RepoID int64 `xorm:"index"`
|
||||||
Repo *repo_model.Repository `xorm:"-"`
|
Repo *repo_model.Repository `xorm:"-"`
|
||||||
IsActive bool // true means it can be used
|
IsActive bool // true means it can be used
|
||||||
|
|
||||||
|
@ -58,7 +69,14 @@ func UpdateRunnerToken(ctx context.Context, r *ActionRunnerToken, cols ...string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRunnerToken creates a new active runner token and invalidate all old tokens
|
// NewRunnerToken creates a new active runner token and invalidate all old tokens
|
||||||
|
// ownerID will be ignored and treated as 0 if repoID is non-zero.
|
||||||
func NewRunnerToken(ctx context.Context, ownerID, repoID int64) (*ActionRunnerToken, error) {
|
func NewRunnerToken(ctx context.Context, ownerID, repoID int64) (*ActionRunnerToken, error) {
|
||||||
|
if ownerID != 0 && repoID != 0 {
|
||||||
|
// It's trying to create a runner token that belongs to a repository, but OwnerID has been set accidentally.
|
||||||
|
// Remove OwnerID to avoid confusion; it's not worth returning an error here.
|
||||||
|
ownerID = 0
|
||||||
|
}
|
||||||
|
|
||||||
token, err := util.CryptoRandomString(40)
|
token, err := util.CryptoRandomString(40)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -84,6 +102,12 @@ func NewRunnerToken(ctx context.Context, ownerID, repoID int64) (*ActionRunnerTo
|
||||||
|
|
||||||
// GetLatestRunnerToken returns the latest runner token
|
// GetLatestRunnerToken returns the latest runner token
|
||||||
func GetLatestRunnerToken(ctx context.Context, ownerID, repoID int64) (*ActionRunnerToken, error) {
|
func GetLatestRunnerToken(ctx context.Context, ownerID, repoID int64) (*ActionRunnerToken, error) {
|
||||||
|
if ownerID != 0 && repoID != 0 {
|
||||||
|
// It's trying to get a runner token that belongs to a repository, but OwnerID has been set accidentally.
|
||||||
|
// Remove OwnerID to avoid confusion; it's not worth returning an error here.
|
||||||
|
ownerID = 0
|
||||||
|
}
|
||||||
|
|
||||||
var runnerToken ActionRunnerToken
|
var runnerToken ActionRunnerToken
|
||||||
has, err := db.GetEngine(ctx).Where("owner_id=? AND repo_id=?", ownerID, repoID).
|
has, err := db.GetEngine(ctx).Where("owner_id=? AND repo_id=?", ownerID, repoID).
|
||||||
OrderBy("id DESC").Get(&runnerToken)
|
OrderBy("id DESC").Get(&runnerToken)
|
||||||
|
|
|
@ -10,31 +10,32 @@ import (
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetLatestRunnerToken(t *testing.T) {
|
func TestGetLatestRunnerToken(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
token := unittest.AssertExistsAndLoadBean(t, &ActionRunnerToken{ID: 3})
|
token := unittest.AssertExistsAndLoadBean(t, &ActionRunnerToken{ID: 3})
|
||||||
expectedToken, err := GetLatestRunnerToken(db.DefaultContext, 1, 0)
|
expectedToken, err := GetLatestRunnerToken(db.DefaultContext, 1, 0)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.EqualValues(t, token, expectedToken)
|
assert.EqualValues(t, expectedToken, token)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewRunnerToken(t *testing.T) {
|
func TestNewRunnerToken(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
token, err := NewRunnerToken(db.DefaultContext, 1, 0)
|
token, err := NewRunnerToken(db.DefaultContext, 1, 0)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
expectedToken, err := GetLatestRunnerToken(db.DefaultContext, 1, 0)
|
expectedToken, err := GetLatestRunnerToken(db.DefaultContext, 1, 0)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.EqualValues(t, token, expectedToken)
|
assert.EqualValues(t, expectedToken, token)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUpdateRunnerToken(t *testing.T) {
|
func TestUpdateRunnerToken(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
token := unittest.AssertExistsAndLoadBean(t, &ActionRunnerToken{ID: 3})
|
token := unittest.AssertExistsAndLoadBean(t, &ActionRunnerToken{ID: 3})
|
||||||
token.IsActive = true
|
token.IsActive = true
|
||||||
assert.NoError(t, UpdateRunnerToken(db.DefaultContext, token))
|
require.NoError(t, UpdateRunnerToken(db.DefaultContext, token))
|
||||||
expectedToken, err := GetLatestRunnerToken(db.DefaultContext, 1, 0)
|
expectedToken, err := GetLatestRunnerToken(db.DefaultContext, 1, 0)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.EqualValues(t, token, expectedToken)
|
assert.EqualValues(t, expectedToken, token)
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,8 +13,6 @@ import (
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
webhook_module "code.gitea.io/gitea/modules/webhook"
|
webhook_module "code.gitea.io/gitea/modules/webhook"
|
||||||
|
|
||||||
"github.com/robfig/cron/v3"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ActionSchedule represents a schedule of a workflow file
|
// ActionSchedule represents a schedule of a workflow file
|
||||||
|
@ -53,8 +51,6 @@ func GetReposMapByIDs(ctx context.Context, ids []int64) (map[int64]*repo_model.R
|
||||||
return repos, db.GetEngine(ctx).In("id", ids).Find(&repos)
|
return repos, db.GetEngine(ctx).In("id", ids).Find(&repos)
|
||||||
}
|
}
|
||||||
|
|
||||||
var cronParser = cron.NewParser(cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow | cron.Descriptor)
|
|
||||||
|
|
||||||
// CreateScheduleTask creates new schedule task.
|
// CreateScheduleTask creates new schedule task.
|
||||||
func CreateScheduleTask(ctx context.Context, rows []*ActionSchedule) error {
|
func CreateScheduleTask(ctx context.Context, rows []*ActionSchedule) error {
|
||||||
// Return early if there are no rows to insert
|
// Return early if there are no rows to insert
|
||||||
|
@ -80,19 +76,21 @@ func CreateScheduleTask(ctx context.Context, rows []*ActionSchedule) error {
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
|
|
||||||
for _, spec := range row.Specs {
|
for _, spec := range row.Specs {
|
||||||
|
specRow := &ActionScheduleSpec{
|
||||||
|
RepoID: row.RepoID,
|
||||||
|
ScheduleID: row.ID,
|
||||||
|
Spec: spec,
|
||||||
|
}
|
||||||
// Parse the spec and check for errors
|
// Parse the spec and check for errors
|
||||||
schedule, err := cronParser.Parse(spec)
|
schedule, err := specRow.Parse()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue // skip to the next spec if there's an error
|
continue // skip to the next spec if there's an error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
specRow.Next = timeutil.TimeStamp(schedule.Next(now).Unix())
|
||||||
|
|
||||||
// Insert the new schedule spec row
|
// Insert the new schedule spec row
|
||||||
if err = db.Insert(ctx, &ActionScheduleSpec{
|
if err = db.Insert(ctx, specRow); err != nil {
|
||||||
RepoID: row.RepoID,
|
|
||||||
ScheduleID: row.ID,
|
|
||||||
Spec: spec,
|
|
||||||
Next: timeutil.TimeStamp(schedule.Next(now).Unix()),
|
|
||||||
}); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -120,12 +118,13 @@ func DeleteScheduleTaskByRepo(ctx context.Context, id int64) error {
|
||||||
return committer.Commit()
|
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
|
// 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
|
// 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 {
|
if err := DeleteScheduleTaskByRepo(ctx, repo.ID); err != nil {
|
||||||
return fmt.Errorf("DeleteCronTaskByRepo: %v", err)
|
return fmt.Errorf("DeleteCronTaskByRepo: %v", err)
|
||||||
}
|
}
|
||||||
|
if cancelPreviousJobs {
|
||||||
// cancel running cron jobs of this repository and delete old schedules
|
// cancel running cron jobs of this repository and delete old schedules
|
||||||
if err := CancelPreviousJobs(
|
if err := CancelPreviousJobs(
|
||||||
ctx,
|
ctx,
|
||||||
|
@ -136,5 +135,6 @@ func CleanRepoScheduleTasks(ctx context.Context, repo *repo_model.Repository) er
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return fmt.Errorf("CancelPreviousJobs: %v", err)
|
return fmt.Errorf("CancelPreviousJobs: %v", err)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,8 @@ package actions
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
|
@ -32,8 +34,29 @@ type ActionScheduleSpec struct {
|
||||||
Updated timeutil.TimeStamp `xorm:"updated"`
|
Updated timeutil.TimeStamp `xorm:"updated"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse parses the spec and returns a cron.Schedule
|
||||||
|
// Unlike the default cron parser, Parse uses UTC timezone as the default if none is specified.
|
||||||
func (s *ActionScheduleSpec) Parse() (cron.Schedule, error) {
|
func (s *ActionScheduleSpec) Parse() (cron.Schedule, error) {
|
||||||
return cronParser.Parse(s.Spec)
|
parser := cron.NewParser(cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow | cron.Descriptor)
|
||||||
|
schedule, err := parser.Parse(s.Spec)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the spec has specified a timezone, use it
|
||||||
|
if strings.HasPrefix(s.Spec, "TZ=") || strings.HasPrefix(s.Spec, "CRON_TZ=") {
|
||||||
|
return schedule, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
specSchedule, ok := schedule.(*cron.SpecSchedule)
|
||||||
|
// If it's not a spec schedule, like "@every 5m", timezone is not relevant
|
||||||
|
if !ok {
|
||||||
|
return schedule, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the timezone to UTC
|
||||||
|
specSchedule.Location = time.UTC
|
||||||
|
return specSchedule, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
71
models/actions/schedule_spec_test.go
Normal file
71
models/actions/schedule_spec_test.go
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package actions
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestActionScheduleSpec_Parse(t *testing.T) {
|
||||||
|
// Mock the local timezone is not UTC
|
||||||
|
local := time.Local
|
||||||
|
tz, err := time.LoadLocation("Asia/Shanghai")
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer func() {
|
||||||
|
time.Local = local
|
||||||
|
}()
|
||||||
|
time.Local = tz
|
||||||
|
|
||||||
|
now, err := time.Parse(time.RFC3339, "2024-07-31T15:47:55+08:00")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
spec string
|
||||||
|
want string
|
||||||
|
wantErr assert.ErrorAssertionFunc
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "regular",
|
||||||
|
spec: "0 10 * * *",
|
||||||
|
want: "2024-07-31T10:00:00Z",
|
||||||
|
wantErr: assert.NoError,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid",
|
||||||
|
spec: "0 10 * *",
|
||||||
|
want: "",
|
||||||
|
wantErr: assert.Error,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "with timezone",
|
||||||
|
spec: "TZ=America/New_York 0 10 * * *",
|
||||||
|
want: "2024-07-31T14:00:00Z",
|
||||||
|
wantErr: assert.NoError,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "timezone irrelevant",
|
||||||
|
spec: "@every 5m",
|
||||||
|
want: "2024-07-31T07:52:55Z",
|
||||||
|
wantErr: assert.NoError,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
s := &ActionScheduleSpec{
|
||||||
|
Spec: tt.spec,
|
||||||
|
}
|
||||||
|
got, err := s.Parse()
|
||||||
|
tt.wantErr(t, err)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
assert.Equal(t, tt.want, got.Next(now).UTC().Format(time.RFC3339))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -35,7 +35,7 @@ type ActionTask struct {
|
||||||
RunnerID int64 `xorm:"index"`
|
RunnerID int64 `xorm:"index"`
|
||||||
Status Status `xorm:"index"`
|
Status Status `xorm:"index"`
|
||||||
Started timeutil.TimeStamp `xorm:"index"`
|
Started timeutil.TimeStamp `xorm:"index"`
|
||||||
Stopped timeutil.TimeStamp
|
Stopped timeutil.TimeStamp `xorm:"index(stopped_log_expired)"`
|
||||||
|
|
||||||
RepoID int64 `xorm:"index"`
|
RepoID int64 `xorm:"index"`
|
||||||
OwnerID int64 `xorm:"index"`
|
OwnerID int64 `xorm:"index"`
|
||||||
|
@ -52,7 +52,7 @@ type ActionTask struct {
|
||||||
LogLength int64 // lines count
|
LogLength int64 // lines count
|
||||||
LogSize int64 // blob size
|
LogSize int64 // blob size
|
||||||
LogIndexes LogIndexes `xorm:"LONGBLOB"` // line number to offset
|
LogIndexes LogIndexes `xorm:"LONGBLOB"` // line number to offset
|
||||||
LogExpired bool // files that are too old will be deleted
|
LogExpired bool `xorm:"index(stopped_log_expired)"` // files that are too old will be deleted
|
||||||
|
|
||||||
Created timeutil.TimeStamp `xorm:"created"`
|
Created timeutil.TimeStamp `xorm:"created"`
|
||||||
Updated timeutil.TimeStamp `xorm:"updated index"`
|
Updated timeutil.TimeStamp `xorm:"updated index"`
|
||||||
|
@ -470,6 +470,16 @@ func StopTask(ctx context.Context, taskID int64, status Status) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func FindOldTasksToExpire(ctx context.Context, olderThan timeutil.TimeStamp, limit int) ([]*ActionTask, error) {
|
||||||
|
e := db.GetEngine(ctx)
|
||||||
|
|
||||||
|
tasks := make([]*ActionTask, 0, limit)
|
||||||
|
// Check "stopped > 0" to avoid deleting tasks that are still running
|
||||||
|
return tasks, e.Where("stopped > 0 AND stopped < ? AND log_expired = ?", olderThan, false).
|
||||||
|
Limit(limit).
|
||||||
|
Find(&tasks)
|
||||||
|
}
|
||||||
|
|
||||||
func isSubset(set, subset []string) bool {
|
func isSubset(set, subset []string) bool {
|
||||||
m := make(container.Set[string], len(set))
|
m := make(container.Set[string], len(set))
|
||||||
for _, v := range set {
|
for _, v := range set {
|
||||||
|
@ -492,7 +502,13 @@ func convertTimestamp(timestamp *timestamppb.Timestamp) timeutil.TimeStamp {
|
||||||
}
|
}
|
||||||
|
|
||||||
func logFileName(repoFullName string, taskID int64) string {
|
func logFileName(repoFullName string, taskID int64) string {
|
||||||
return fmt.Sprintf("%s/%02x/%d.log", repoFullName, taskID%256, taskID)
|
ret := fmt.Sprintf("%s/%02x/%d.log", repoFullName, taskID%256, taskID)
|
||||||
|
|
||||||
|
if setting.Actions.LogCompression.IsZstd() {
|
||||||
|
ret += ".zst"
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func getTaskIDFromCache(token string) int64 {
|
func getTaskIDFromCache(token string) int64 {
|
||||||
|
|
|
@ -5,7 +5,6 @@ package actions
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
@ -15,6 +14,18 @@ import (
|
||||||
"xorm.io/builder"
|
"xorm.io/builder"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ActionVariable represents a variable that can be used in actions
|
||||||
|
//
|
||||||
|
// It can be:
|
||||||
|
// 1. global variable, OwnerID is 0 and RepoID is 0
|
||||||
|
// 2. org/user level variable, OwnerID is org/user ID and RepoID is 0
|
||||||
|
// 3. repo level variable, OwnerID is 0 and RepoID is repo ID
|
||||||
|
//
|
||||||
|
// Please note that it's not acceptable to have both OwnerID and RepoID to be non-zero,
|
||||||
|
// or it will be complicated to find variables belonging to a specific owner.
|
||||||
|
// For example, conditions like `OwnerID = 1` will also return variable {OwnerID: 1, RepoID: 1},
|
||||||
|
// but it's a repo level variable, not an org/user level variable.
|
||||||
|
// To avoid this, make it clear with {OwnerID: 0, RepoID: 1} for repo level variables.
|
||||||
type ActionVariable struct {
|
type ActionVariable struct {
|
||||||
ID int64 `xorm:"pk autoincr"`
|
ID int64 `xorm:"pk autoincr"`
|
||||||
OwnerID int64 `xorm:"UNIQUE(owner_repo_name)"`
|
OwnerID int64 `xorm:"UNIQUE(owner_repo_name)"`
|
||||||
|
@ -29,30 +40,26 @@ func init() {
|
||||||
db.RegisterModel(new(ActionVariable))
|
db.RegisterModel(new(ActionVariable))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *ActionVariable) Validate() error {
|
func InsertVariable(ctx context.Context, ownerID, repoID int64, name, data string) (*ActionVariable, error) {
|
||||||
if v.OwnerID != 0 && v.RepoID != 0 {
|
if ownerID != 0 && repoID != 0 {
|
||||||
return errors.New("a variable should not be bound to an owner and a repository at the same time")
|
// It's trying to create a variable that belongs to a repository, but OwnerID has been set accidentally.
|
||||||
}
|
// Remove OwnerID to avoid confusion; it's not worth returning an error here.
|
||||||
return nil
|
ownerID = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func InsertVariable(ctx context.Context, ownerID, repoID int64, name, data string) (*ActionVariable, error) {
|
|
||||||
variable := &ActionVariable{
|
variable := &ActionVariable{
|
||||||
OwnerID: ownerID,
|
OwnerID: ownerID,
|
||||||
RepoID: repoID,
|
RepoID: repoID,
|
||||||
Name: strings.ToUpper(name),
|
Name: strings.ToUpper(name),
|
||||||
Data: data,
|
Data: data,
|
||||||
}
|
}
|
||||||
if err := variable.Validate(); err != nil {
|
|
||||||
return variable, err
|
|
||||||
}
|
|
||||||
return variable, db.Insert(ctx, variable)
|
return variable, db.Insert(ctx, variable)
|
||||||
}
|
}
|
||||||
|
|
||||||
type FindVariablesOpts struct {
|
type FindVariablesOpts struct {
|
||||||
db.ListOptions
|
db.ListOptions
|
||||||
OwnerID int64
|
|
||||||
RepoID int64
|
RepoID int64
|
||||||
|
OwnerID int64 // it will be ignored if RepoID is set
|
||||||
Name string
|
Name string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,8 +67,13 @@ func (opts FindVariablesOpts) ToConds() builder.Cond {
|
||||||
cond := builder.NewCond()
|
cond := builder.NewCond()
|
||||||
// Since we now support instance-level variables,
|
// Since we now support instance-level variables,
|
||||||
// there is no need to check for null values for `owner_id` and `repo_id`
|
// there is no need to check for null values for `owner_id` and `repo_id`
|
||||||
cond = cond.And(builder.Eq{"owner_id": opts.OwnerID})
|
|
||||||
cond = cond.And(builder.Eq{"repo_id": opts.RepoID})
|
cond = cond.And(builder.Eq{"repo_id": opts.RepoID})
|
||||||
|
if opts.RepoID != 0 { // if RepoID is set
|
||||||
|
// ignore OwnerID and treat it as 0
|
||||||
|
cond = cond.And(builder.Eq{"owner_id": 0})
|
||||||
|
} else {
|
||||||
|
cond = cond.And(builder.Eq{"owner_id": opts.OwnerID})
|
||||||
|
}
|
||||||
|
|
||||||
if opts.Name != "" {
|
if opts.Name != "" {
|
||||||
cond = cond.And(builder.Eq{"name": strings.ToUpper(opts.Name)})
|
cond = cond.And(builder.Eq{"name": strings.ToUpper(opts.Name)})
|
||||||
|
|
|
@ -17,10 +17,11 @@ import (
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestAction_GetRepoPath(t *testing.T) {
|
func TestAction_GetRepoPath(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||||
action := &activities_model.Action{RepoID: repo.ID}
|
action := &activities_model.Action{RepoID: repo.ID}
|
||||||
|
@ -28,7 +29,7 @@ func TestAction_GetRepoPath(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAction_GetRepoLink(t *testing.T) {
|
func TestAction_GetRepoLink(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||||
comment := unittest.AssertExistsAndLoadBean(t, &issue_model.Comment{ID: 2})
|
comment := unittest.AssertExistsAndLoadBean(t, &issue_model.Comment{ID: 2})
|
||||||
|
@ -42,7 +43,7 @@ func TestAction_GetRepoLink(t *testing.T) {
|
||||||
|
|
||||||
func TestGetFeeds(t *testing.T) {
|
func TestGetFeeds(t *testing.T) {
|
||||||
// test with an individual user
|
// test with an individual user
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
|
|
||||||
actions, count, err := activities_model.GetFeeds(db.DefaultContext, activities_model.GetFeedsOptions{
|
actions, count, err := activities_model.GetFeeds(db.DefaultContext, activities_model.GetFeedsOptions{
|
||||||
|
@ -52,7 +53,7 @@ func TestGetFeeds(t *testing.T) {
|
||||||
OnlyPerformedBy: false,
|
OnlyPerformedBy: false,
|
||||||
IncludeDeleted: true,
|
IncludeDeleted: true,
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
if assert.Len(t, actions, 1) {
|
if assert.Len(t, actions, 1) {
|
||||||
assert.EqualValues(t, 1, actions[0].ID)
|
assert.EqualValues(t, 1, actions[0].ID)
|
||||||
assert.EqualValues(t, user.ID, actions[0].UserID)
|
assert.EqualValues(t, user.ID, actions[0].UserID)
|
||||||
|
@ -65,13 +66,13 @@ func TestGetFeeds(t *testing.T) {
|
||||||
IncludePrivate: false,
|
IncludePrivate: false,
|
||||||
OnlyPerformedBy: false,
|
OnlyPerformedBy: false,
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Len(t, actions, 0)
|
assert.Empty(t, actions)
|
||||||
assert.Equal(t, int64(0), count)
|
assert.Equal(t, int64(0), count)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetFeedsForRepos(t *testing.T) {
|
func TestGetFeedsForRepos(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
privRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
|
privRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
|
||||||
pubRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 8})
|
pubRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 8})
|
||||||
|
@ -81,8 +82,8 @@ func TestGetFeedsForRepos(t *testing.T) {
|
||||||
RequestedRepo: privRepo,
|
RequestedRepo: privRepo,
|
||||||
IncludePrivate: true,
|
IncludePrivate: true,
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Len(t, actions, 0)
|
assert.Empty(t, actions)
|
||||||
assert.Equal(t, int64(0), count)
|
assert.Equal(t, int64(0), count)
|
||||||
|
|
||||||
// public repo & no login
|
// public repo & no login
|
||||||
|
@ -90,7 +91,7 @@ func TestGetFeedsForRepos(t *testing.T) {
|
||||||
RequestedRepo: pubRepo,
|
RequestedRepo: pubRepo,
|
||||||
IncludePrivate: true,
|
IncludePrivate: true,
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Len(t, actions, 1)
|
assert.Len(t, actions, 1)
|
||||||
assert.Equal(t, int64(1), count)
|
assert.Equal(t, int64(1), count)
|
||||||
|
|
||||||
|
@ -100,7 +101,7 @@ func TestGetFeedsForRepos(t *testing.T) {
|
||||||
IncludePrivate: true,
|
IncludePrivate: true,
|
||||||
Actor: user,
|
Actor: user,
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Len(t, actions, 1)
|
assert.Len(t, actions, 1)
|
||||||
assert.Equal(t, int64(1), count)
|
assert.Equal(t, int64(1), count)
|
||||||
|
|
||||||
|
@ -110,14 +111,14 @@ func TestGetFeedsForRepos(t *testing.T) {
|
||||||
IncludePrivate: true,
|
IncludePrivate: true,
|
||||||
Actor: user,
|
Actor: user,
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Len(t, actions, 1)
|
assert.Len(t, actions, 1)
|
||||||
assert.Equal(t, int64(1), count)
|
assert.Equal(t, int64(1), count)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetFeeds2(t *testing.T) {
|
func TestGetFeeds2(t *testing.T) {
|
||||||
// test with an organization user
|
// test with an organization user
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
org := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3})
|
org := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3})
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
|
|
||||||
|
@ -128,7 +129,7 @@ func TestGetFeeds2(t *testing.T) {
|
||||||
OnlyPerformedBy: false,
|
OnlyPerformedBy: false,
|
||||||
IncludeDeleted: true,
|
IncludeDeleted: true,
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Len(t, actions, 1)
|
assert.Len(t, actions, 1)
|
||||||
if assert.Len(t, actions, 1) {
|
if assert.Len(t, actions, 1) {
|
||||||
assert.EqualValues(t, 2, actions[0].ID)
|
assert.EqualValues(t, 2, actions[0].ID)
|
||||||
|
@ -143,8 +144,8 @@ func TestGetFeeds2(t *testing.T) {
|
||||||
OnlyPerformedBy: false,
|
OnlyPerformedBy: false,
|
||||||
IncludeDeleted: true,
|
IncludeDeleted: true,
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Len(t, actions, 0)
|
assert.Empty(t, actions)
|
||||||
assert.Equal(t, int64(0), count)
|
assert.Equal(t, int64(0), count)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,14 +190,14 @@ func TestActivityReadable(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNotifyWatchers(t *testing.T) {
|
func TestNotifyWatchers(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
action := &activities_model.Action{
|
action := &activities_model.Action{
|
||||||
ActUserID: 8,
|
ActUserID: 8,
|
||||||
RepoID: 1,
|
RepoID: 1,
|
||||||
OpType: activities_model.ActionStarRepo,
|
OpType: activities_model.ActionStarRepo,
|
||||||
}
|
}
|
||||||
assert.NoError(t, activities_model.NotifyWatchers(db.DefaultContext, action))
|
require.NoError(t, activities_model.NotifyWatchers(db.DefaultContext, action))
|
||||||
|
|
||||||
// One watchers are inactive, thus action is only created for user 8, 1, 4, 11
|
// One watchers are inactive, thus action is only created for user 8, 1, 4, 11
|
||||||
unittest.AssertExistsAndLoadBean(t, &activities_model.Action{
|
unittest.AssertExistsAndLoadBean(t, &activities_model.Action{
|
||||||
|
@ -226,7 +227,7 @@ func TestNotifyWatchers(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetFeedsCorrupted(t *testing.T) {
|
func TestGetFeedsCorrupted(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||||
unittest.AssertExistsAndLoadBean(t, &activities_model.Action{
|
unittest.AssertExistsAndLoadBean(t, &activities_model.Action{
|
||||||
ID: 8,
|
ID: 8,
|
||||||
|
@ -238,8 +239,8 @@ func TestGetFeedsCorrupted(t *testing.T) {
|
||||||
Actor: user,
|
Actor: user,
|
||||||
IncludePrivate: true,
|
IncludePrivate: true,
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Len(t, actions, 0)
|
assert.Empty(t, actions)
|
||||||
assert.Equal(t, int64(0), count)
|
assert.Equal(t, int64(0), count)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,47 +248,46 @@ func TestConsistencyUpdateAction(t *testing.T) {
|
||||||
if !setting.Database.Type.IsSQLite3() {
|
if !setting.Database.Type.IsSQLite3() {
|
||||||
t.Skip("Test is only for SQLite database.")
|
t.Skip("Test is only for SQLite database.")
|
||||||
}
|
}
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
id := 8
|
id := 8
|
||||||
unittest.AssertExistsAndLoadBean(t, &activities_model.Action{
|
unittest.AssertExistsAndLoadBean(t, &activities_model.Action{
|
||||||
ID: int64(id),
|
ID: int64(id),
|
||||||
})
|
})
|
||||||
_, err := db.GetEngine(db.DefaultContext).Exec(`UPDATE action SET created_unix = "" WHERE id = ?`, id)
|
_, err := db.GetEngine(db.DefaultContext).Exec(`UPDATE action SET created_unix = "" WHERE id = ?`, id)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
actions := make([]*activities_model.Action, 0, 1)
|
actions := make([]*activities_model.Action, 0, 1)
|
||||||
//
|
//
|
||||||
// XORM returns an error when created_unix is a string
|
// XORM returns an error when created_unix is a string
|
||||||
//
|
//
|
||||||
err = db.GetEngine(db.DefaultContext).Where("id = ?", id).Find(&actions)
|
err = db.GetEngine(db.DefaultContext).Where("id = ?", id).Find(&actions)
|
||||||
if assert.Error(t, err) {
|
require.ErrorContains(t, err, "type string to a int64: invalid syntax")
|
||||||
assert.Contains(t, err.Error(), "type string to a int64: invalid syntax")
|
|
||||||
}
|
|
||||||
//
|
//
|
||||||
// Get rid of incorrectly set created_unix
|
// Get rid of incorrectly set created_unix
|
||||||
//
|
//
|
||||||
count, err := activities_model.CountActionCreatedUnixString(db.DefaultContext)
|
count, err := activities_model.CountActionCreatedUnixString(db.DefaultContext)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.EqualValues(t, 1, count)
|
assert.EqualValues(t, 1, count)
|
||||||
count, err = activities_model.FixActionCreatedUnixString(db.DefaultContext)
|
count, err = activities_model.FixActionCreatedUnixString(db.DefaultContext)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.EqualValues(t, 1, count)
|
assert.EqualValues(t, 1, count)
|
||||||
|
|
||||||
count, err = activities_model.CountActionCreatedUnixString(db.DefaultContext)
|
count, err = activities_model.CountActionCreatedUnixString(db.DefaultContext)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.EqualValues(t, 0, count)
|
assert.EqualValues(t, 0, count)
|
||||||
count, err = activities_model.FixActionCreatedUnixString(db.DefaultContext)
|
count, err = activities_model.FixActionCreatedUnixString(db.DefaultContext)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.EqualValues(t, 0, count)
|
assert.EqualValues(t, 0, count)
|
||||||
|
|
||||||
//
|
//
|
||||||
// XORM must be happy now
|
// XORM must be happy now
|
||||||
//
|
//
|
||||||
assert.NoError(t, db.GetEngine(db.DefaultContext).Where("id = ?", id).Find(&actions))
|
require.NoError(t, db.GetEngine(db.DefaultContext).Where("id = ?", id).Find(&actions))
|
||||||
unittest.CheckConsistencyFor(t, &activities_model.Action{})
|
unittest.CheckConsistencyFor(t, &activities_model.Action{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDeleteIssueActions(t *testing.T) {
|
func TestDeleteIssueActions(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
// load an issue
|
// load an issue
|
||||||
issue := unittest.AssertExistsAndLoadBean(t, &issue_model.Issue{ID: 4})
|
issue := unittest.AssertExistsAndLoadBean(t, &issue_model.Issue{ID: 4})
|
||||||
|
@ -295,26 +295,26 @@ func TestDeleteIssueActions(t *testing.T) {
|
||||||
|
|
||||||
// insert a comment
|
// insert a comment
|
||||||
err := db.Insert(db.DefaultContext, &issue_model.Comment{Type: issue_model.CommentTypeComment, IssueID: issue.ID})
|
err := db.Insert(db.DefaultContext, &issue_model.Comment{Type: issue_model.CommentTypeComment, IssueID: issue.ID})
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
comment := unittest.AssertExistsAndLoadBean(t, &issue_model.Comment{Type: issue_model.CommentTypeComment, IssueID: issue.ID})
|
comment := unittest.AssertExistsAndLoadBean(t, &issue_model.Comment{Type: issue_model.CommentTypeComment, IssueID: issue.ID})
|
||||||
|
|
||||||
// truncate action table and insert some actions
|
// truncate action table and insert some actions
|
||||||
err = db.TruncateBeans(db.DefaultContext, &activities_model.Action{})
|
err = db.TruncateBeans(db.DefaultContext, &activities_model.Action{})
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = db.Insert(db.DefaultContext, &activities_model.Action{
|
err = db.Insert(db.DefaultContext, &activities_model.Action{
|
||||||
OpType: activities_model.ActionCommentIssue,
|
OpType: activities_model.ActionCommentIssue,
|
||||||
CommentID: comment.ID,
|
CommentID: comment.ID,
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = db.Insert(db.DefaultContext, &activities_model.Action{
|
err = db.Insert(db.DefaultContext, &activities_model.Action{
|
||||||
OpType: activities_model.ActionCreateIssue,
|
OpType: activities_model.ActionCreateIssue,
|
||||||
RepoID: issue.RepoID,
|
RepoID: issue.RepoID,
|
||||||
Content: fmt.Sprintf("%d|content...", issue.Index),
|
Content: fmt.Sprintf("%d|content...", issue.Index),
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// assert that the actions exist, then delete them
|
// assert that the actions exist, then delete them
|
||||||
unittest.AssertCount(t, &activities_model.Action{}, 2)
|
unittest.AssertCount(t, &activities_model.Action{}, 2)
|
||||||
assert.NoError(t, activities_model.DeleteIssueActions(db.DefaultContext, issue.RepoID, issue.ID, issue.Index))
|
require.NoError(t, activities_model.DeleteIssueActions(db.DefaultContext, issue.RepoID, issue.ID, issue.Index))
|
||||||
unittest.AssertCount(t, &activities_model.Action{}, 0)
|
unittest.AssertCount(t, &activities_model.Action{}, 0)
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
|
|
||||||
_ "code.gitea.io/gitea/models"
|
_ "code.gitea.io/gitea/models"
|
||||||
_ "code.gitea.io/gitea/models/actions"
|
_ "code.gitea.io/gitea/models/actions"
|
||||||
|
_ "code.gitea.io/gitea/models/forgefed"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
|
|
|
@ -14,13 +14,14 @@ import (
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCreateOrUpdateIssueNotifications(t *testing.T) {
|
func TestCreateOrUpdateIssueNotifications(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 1})
|
issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 1})
|
||||||
|
|
||||||
assert.NoError(t, activities_model.CreateOrUpdateIssueNotifications(db.DefaultContext, issue.ID, 0, 2, 0))
|
require.NoError(t, activities_model.CreateOrUpdateIssueNotifications(db.DefaultContext, issue.ID, 0, 2, 0))
|
||||||
|
|
||||||
// User 9 is inactive, thus notifications for user 1 and 4 are created
|
// User 9 is inactive, thus notifications for user 1 and 4 are created
|
||||||
notf := unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{UserID: 1, IssueID: issue.ID})
|
notf := unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{UserID: 1, IssueID: issue.ID})
|
||||||
|
@ -32,7 +33,7 @@ func TestCreateOrUpdateIssueNotifications(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNotificationsForUser(t *testing.T) {
|
func TestNotificationsForUser(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
notfs, err := db.Find[activities_model.Notification](db.DefaultContext, activities_model.FindNotificationOptions{
|
notfs, err := db.Find[activities_model.Notification](db.DefaultContext, activities_model.FindNotificationOptions{
|
||||||
UserID: user.ID,
|
UserID: user.ID,
|
||||||
|
@ -41,7 +42,7 @@ func TestNotificationsForUser(t *testing.T) {
|
||||||
activities_model.NotificationStatusUnread,
|
activities_model.NotificationStatusUnread,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
if assert.Len(t, notfs, 3) {
|
if assert.Len(t, notfs, 3) {
|
||||||
assert.EqualValues(t, 5, notfs[0].ID)
|
assert.EqualValues(t, 5, notfs[0].ID)
|
||||||
assert.EqualValues(t, user.ID, notfs[0].UserID)
|
assert.EqualValues(t, user.ID, notfs[0].UserID)
|
||||||
|
@ -53,25 +54,25 @@ func TestNotificationsForUser(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNotification_GetRepo(t *testing.T) {
|
func TestNotification_GetRepo(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
notf := unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{RepoID: 1})
|
notf := unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{RepoID: 1})
|
||||||
repo, err := notf.GetRepo(db.DefaultContext)
|
repo, err := notf.GetRepo(db.DefaultContext)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, repo, notf.Repository)
|
assert.Equal(t, repo, notf.Repository)
|
||||||
assert.EqualValues(t, notf.RepoID, repo.ID)
|
assert.EqualValues(t, notf.RepoID, repo.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNotification_GetIssue(t *testing.T) {
|
func TestNotification_GetIssue(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
notf := unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{RepoID: 1})
|
notf := unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{RepoID: 1})
|
||||||
issue, err := notf.GetIssue(db.DefaultContext)
|
issue, err := notf.GetIssue(db.DefaultContext)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, issue, notf.Issue)
|
assert.Equal(t, issue, notf.Issue)
|
||||||
assert.EqualValues(t, notf.IssueID, issue.ID)
|
assert.EqualValues(t, notf.IssueID, issue.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetNotificationCount(t *testing.T) {
|
func TestGetNotificationCount(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||||
cnt, err := db.Count[activities_model.Notification](db.DefaultContext, activities_model.FindNotificationOptions{
|
cnt, err := db.Count[activities_model.Notification](db.DefaultContext, activities_model.FindNotificationOptions{
|
||||||
UserID: user.ID,
|
UserID: user.ID,
|
||||||
|
@ -79,7 +80,7 @@ func TestGetNotificationCount(t *testing.T) {
|
||||||
activities_model.NotificationStatusRead,
|
activities_model.NotificationStatusRead,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.EqualValues(t, 0, cnt)
|
assert.EqualValues(t, 0, cnt)
|
||||||
|
|
||||||
cnt, err = db.Count[activities_model.Notification](db.DefaultContext, activities_model.FindNotificationOptions{
|
cnt, err = db.Count[activities_model.Notification](db.DefaultContext, activities_model.FindNotificationOptions{
|
||||||
|
@ -88,28 +89,28 @@ func TestGetNotificationCount(t *testing.T) {
|
||||||
activities_model.NotificationStatusUnread,
|
activities_model.NotificationStatusUnread,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.EqualValues(t, 1, cnt)
|
assert.EqualValues(t, 1, cnt)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSetNotificationStatus(t *testing.T) {
|
func TestSetNotificationStatus(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
notf := unittest.AssertExistsAndLoadBean(t,
|
notf := unittest.AssertExistsAndLoadBean(t,
|
||||||
&activities_model.Notification{UserID: user.ID, Status: activities_model.NotificationStatusRead})
|
&activities_model.Notification{UserID: user.ID, Status: activities_model.NotificationStatusRead})
|
||||||
_, err := activities_model.SetNotificationStatus(db.DefaultContext, notf.ID, user, activities_model.NotificationStatusPinned)
|
_, err := activities_model.SetNotificationStatus(db.DefaultContext, notf.ID, user, activities_model.NotificationStatusPinned)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
unittest.AssertExistsAndLoadBean(t,
|
unittest.AssertExistsAndLoadBean(t,
|
||||||
&activities_model.Notification{ID: notf.ID, Status: activities_model.NotificationStatusPinned})
|
&activities_model.Notification{ID: notf.ID, Status: activities_model.NotificationStatusPinned})
|
||||||
|
|
||||||
_, err = activities_model.SetNotificationStatus(db.DefaultContext, 1, user, activities_model.NotificationStatusRead)
|
_, err = activities_model.SetNotificationStatus(db.DefaultContext, 1, user, activities_model.NotificationStatusRead)
|
||||||
assert.Error(t, err)
|
require.Error(t, err)
|
||||||
_, err = activities_model.SetNotificationStatus(db.DefaultContext, unittest.NonexistentID, user, activities_model.NotificationStatusRead)
|
_, err = activities_model.SetNotificationStatus(db.DefaultContext, unittest.NonexistentID, user, activities_model.NotificationStatusRead)
|
||||||
assert.Error(t, err)
|
require.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUpdateNotificationStatuses(t *testing.T) {
|
func TestUpdateNotificationStatuses(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
notfUnread := unittest.AssertExistsAndLoadBean(t,
|
notfUnread := unittest.AssertExistsAndLoadBean(t,
|
||||||
&activities_model.Notification{UserID: user.ID, Status: activities_model.NotificationStatusUnread})
|
&activities_model.Notification{UserID: user.ID, Status: activities_model.NotificationStatusUnread})
|
||||||
|
@ -117,7 +118,7 @@ func TestUpdateNotificationStatuses(t *testing.T) {
|
||||||
&activities_model.Notification{UserID: user.ID, Status: activities_model.NotificationStatusRead})
|
&activities_model.Notification{UserID: user.ID, Status: activities_model.NotificationStatusRead})
|
||||||
notfPinned := unittest.AssertExistsAndLoadBean(t,
|
notfPinned := unittest.AssertExistsAndLoadBean(t,
|
||||||
&activities_model.Notification{UserID: user.ID, Status: activities_model.NotificationStatusPinned})
|
&activities_model.Notification{UserID: user.ID, Status: activities_model.NotificationStatusPinned})
|
||||||
assert.NoError(t, activities_model.UpdateNotificationStatuses(db.DefaultContext, user, activities_model.NotificationStatusUnread, activities_model.NotificationStatusRead))
|
require.NoError(t, activities_model.UpdateNotificationStatuses(db.DefaultContext, user, activities_model.NotificationStatusUnread, activities_model.NotificationStatusRead))
|
||||||
unittest.AssertExistsAndLoadBean(t,
|
unittest.AssertExistsAndLoadBean(t,
|
||||||
&activities_model.Notification{ID: notfUnread.ID, Status: activities_model.NotificationStatusRead})
|
&activities_model.Notification{ID: notfUnread.ID, Status: activities_model.NotificationStatusRead})
|
||||||
unittest.AssertExistsAndLoadBean(t,
|
unittest.AssertExistsAndLoadBean(t,
|
||||||
|
@ -127,14 +128,14 @@ func TestUpdateNotificationStatuses(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSetIssueReadBy(t *testing.T) {
|
func TestSetIssueReadBy(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||||
issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 1})
|
issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 1})
|
||||||
assert.NoError(t, db.WithTx(db.DefaultContext, func(ctx context.Context) error {
|
require.NoError(t, db.WithTx(db.DefaultContext, func(ctx context.Context) error {
|
||||||
return activities_model.SetIssueReadBy(ctx, issue.ID, user.ID)
|
return activities_model.SetIssueReadBy(ctx, issue.ID, user.ID)
|
||||||
}))
|
}))
|
||||||
|
|
||||||
nt, err := activities_model.GetIssueNotification(db.DefaultContext, user.ID, issue.ID)
|
nt, err := activities_model.GetIssueNotification(db.DefaultContext, user.ID, issue.ID)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.EqualValues(t, activities_model.NotificationStatusRead, nt.Status)
|
assert.EqualValues(t, activities_model.NotificationStatusRead, nt.Status)
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ type ActivityStats struct {
|
||||||
OpenedPRAuthorCount int64
|
OpenedPRAuthorCount int64
|
||||||
MergedPRs issues_model.PullRequestList
|
MergedPRs issues_model.PullRequestList
|
||||||
MergedPRAuthorCount int64
|
MergedPRAuthorCount int64
|
||||||
|
ActiveIssues issues_model.IssueList
|
||||||
OpenedIssues issues_model.IssueList
|
OpenedIssues issues_model.IssueList
|
||||||
OpenedIssueAuthorCount int64
|
OpenedIssueAuthorCount int64
|
||||||
ClosedIssues issues_model.IssueList
|
ClosedIssues issues_model.IssueList
|
||||||
|
@ -172,7 +173,7 @@ func (stats *ActivityStats) MergedPRPerc() int {
|
||||||
|
|
||||||
// ActiveIssueCount returns total active issue count
|
// ActiveIssueCount returns total active issue count
|
||||||
func (stats *ActivityStats) ActiveIssueCount() int {
|
func (stats *ActivityStats) ActiveIssueCount() int {
|
||||||
return stats.OpenedIssueCount() + stats.ClosedIssueCount()
|
return len(stats.ActiveIssues)
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenedIssueCount returns open issue count
|
// OpenedIssueCount returns open issue count
|
||||||
|
@ -285,13 +286,21 @@ func (stats *ActivityStats) FillIssues(ctx context.Context, repoID int64, fromTi
|
||||||
stats.ClosedIssueAuthorCount = count
|
stats.ClosedIssueAuthorCount = count
|
||||||
|
|
||||||
// New issues
|
// New issues
|
||||||
sess = issuesForActivityStatement(ctx, repoID, fromTime, false, false)
|
sess = newlyCreatedIssues(ctx, repoID, fromTime)
|
||||||
sess.OrderBy("issue.created_unix ASC")
|
sess.OrderBy("issue.created_unix ASC")
|
||||||
stats.OpenedIssues = make(issues_model.IssueList, 0)
|
stats.OpenedIssues = make(issues_model.IssueList, 0)
|
||||||
if err = sess.Find(&stats.OpenedIssues); err != nil {
|
if err = sess.Find(&stats.OpenedIssues); err != nil {
|
||||||
return err
|
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
|
// Opened issue authors
|
||||||
sess = issuesForActivityStatement(ctx, repoID, fromTime, false, false)
|
sess = issuesForActivityStatement(ctx, repoID, fromTime, false, false)
|
||||||
if _, err = sess.Select("count(distinct issue.poster_id) as `count`").Table("issue").Get(&count); err != nil {
|
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)
|
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 {
|
func issuesForActivityStatement(ctx context.Context, repoID int64, fromTime time.Time, closed, unresolved bool) *xorm.Session {
|
||||||
sess := db.GetEngine(ctx).Where("issue.repo_id = ?", repoID).
|
sess := db.GetEngine(ctx).Where("issue.repo_id = ?", repoID).
|
||||||
And("issue.is_closed = ?", closed)
|
And("issue.is_closed = ?", closed)
|
||||||
|
|
30
models/activities/repo_activity_test.go
Normal file
30
models/activities/repo_activity_test.go
Normal 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())
|
||||||
|
}
|
|
@ -4,7 +4,6 @@
|
||||||
package activities_test
|
package activities_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -16,6 +15,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetUserHeatmapDataByUser(t *testing.T) {
|
func TestGetUserHeatmapDataByUser(t *testing.T) {
|
||||||
|
@ -56,7 +56,7 @@ func TestGetUserHeatmapDataByUser(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
// Prepare
|
// Prepare
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
// Mock time
|
// Mock time
|
||||||
timeutil.MockSet(time.Date(2021, 1, 1, 0, 0, 0, 0, time.UTC))
|
timeutil.MockSet(time.Date(2021, 1, 1, 0, 0, 0, 0, time.UTC))
|
||||||
|
@ -67,7 +67,7 @@ func TestGetUserHeatmapDataByUser(t *testing.T) {
|
||||||
|
|
||||||
doer := &user_model.User{ID: tc.doerID}
|
doer := &user_model.User{ID: tc.doerID}
|
||||||
_, err := unittest.LoadBeanIfExists(doer)
|
_, err := unittest.LoadBeanIfExists(doer)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
if tc.doerID == 0 {
|
if tc.doerID == 0 {
|
||||||
doer = nil
|
doer = nil
|
||||||
}
|
}
|
||||||
|
@ -80,7 +80,7 @@ func TestGetUserHeatmapDataByUser(t *testing.T) {
|
||||||
OnlyPerformedBy: true,
|
OnlyPerformedBy: true,
|
||||||
IncludeDeleted: true,
|
IncludeDeleted: true,
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Get the heatmap and compare
|
// Get the heatmap and compare
|
||||||
heatmap, err := activities_model.GetUserHeatmapDataByUser(db.DefaultContext, user, doer)
|
heatmap, err := activities_model.GetUserHeatmapDataByUser(db.DefaultContext, user, doer)
|
||||||
|
@ -88,14 +88,14 @@ func TestGetUserHeatmapDataByUser(t *testing.T) {
|
||||||
for _, hm := range heatmap {
|
for _, hm := range heatmap {
|
||||||
contributions += int(hm.Contributions)
|
contributions += int(hm.Contributions)
|
||||||
}
|
}
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Len(t, actions, contributions, "invalid action count: did the test data became too old?")
|
assert.Len(t, actions, contributions, "invalid action count: did the test data became too old?")
|
||||||
assert.Equal(t, count, int64(contributions))
|
assert.Equal(t, count, int64(contributions))
|
||||||
assert.Equal(t, tc.CountResult, contributions, fmt.Sprintf("testcase '%s'", tc.desc))
|
assert.Equal(t, tc.CountResult, contributions, tc.desc)
|
||||||
|
|
||||||
// Test JSON rendering
|
// Test JSON rendering
|
||||||
jsonData, err := json.Marshal(heatmap)
|
jsonData, err := json.Marshal(heatmap)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, tc.JSONResult, string(jsonData))
|
assert.JSONEq(t, tc.JSONResult, string(jsonData))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,7 +114,7 @@ func readArmoredSign(r io.Reader) (body io.Reader, err error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if block.Type != openpgp.SignatureType {
|
if block.Type != openpgp.SignatureType {
|
||||||
return nil, fmt.Errorf("expected '" + openpgp.SignatureType + "', got: " + block.Type)
|
return nil, fmt.Errorf("expected %q, got: %s", openpgp.SignatureType, block.Type)
|
||||||
}
|
}
|
||||||
return block.Body, nil
|
return block.Body, nil
|
||||||
}
|
}
|
||||||
|
@ -139,7 +139,7 @@ func tryGetKeyIDFromSignature(sig *packet.Signature) string {
|
||||||
if sig.IssuerKeyId != nil && (*sig.IssuerKeyId) != 0 {
|
if sig.IssuerKeyId != nil && (*sig.IssuerKeyId) != 0 {
|
||||||
return fmt.Sprintf("%016X", *sig.IssuerKeyId)
|
return fmt.Sprintf("%016X", *sig.IssuerKeyId)
|
||||||
}
|
}
|
||||||
if sig.IssuerFingerprint != nil && len(sig.IssuerFingerprint) > 0 {
|
if len(sig.IssuerFingerprint) > 0 {
|
||||||
return fmt.Sprintf("%016X", sig.IssuerFingerprint[12:20])
|
return fmt.Sprintf("%016X", sig.IssuerFingerprint[12:20])
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
|
|
|
@ -15,6 +15,7 @@ import (
|
||||||
|
|
||||||
"github.com/ProtonMail/go-crypto/openpgp/packet"
|
"github.com/ProtonMail/go-crypto/openpgp/packet"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCheckArmoredGPGKeyString(t *testing.T) {
|
func TestCheckArmoredGPGKeyString(t *testing.T) {
|
||||||
|
@ -50,7 +51,7 @@ MkM/fdpyc2hY7Dl/+qFmN5MG5yGmMpQcX+RNNR222ibNC1D3wg==
|
||||||
-----END PGP PUBLIC KEY BLOCK-----`
|
-----END PGP PUBLIC KEY BLOCK-----`
|
||||||
|
|
||||||
key, err := checkArmoredGPGKeyString(testGPGArmor)
|
key, err := checkArmoredGPGKeyString(testGPGArmor)
|
||||||
assert.NoError(t, err, "Could not parse a valid GPG public armored rsa key", key)
|
require.NoError(t, err, "Could not parse a valid GPG public armored rsa key", key)
|
||||||
// TODO verify value of key
|
// TODO verify value of key
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +72,7 @@ OyjLLnFQiVmq7kEA/0z0CQe3ZQiQIq5zrs7Nh1XRkFAo8GlU/SGC9XFFi722
|
||||||
-----END PGP PUBLIC KEY BLOCK-----`
|
-----END PGP PUBLIC KEY BLOCK-----`
|
||||||
|
|
||||||
key, err := checkArmoredGPGKeyString(testGPGArmor)
|
key, err := checkArmoredGPGKeyString(testGPGArmor)
|
||||||
assert.NoError(t, err, "Could not parse a valid GPG public armored brainpoolP256r1 key", key)
|
require.NoError(t, err, "Could not parse a valid GPG public armored brainpoolP256r1 key", key)
|
||||||
// TODO verify value of key
|
// TODO verify value of key
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,11 +112,11 @@ MkM/fdpyc2hY7Dl/+qFmN5MG5yGmMpQcX+RNNR222ibNC1D3wg==
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ekey := keys[0]
|
ekey := keys[0]
|
||||||
assert.NoError(t, err, "Could not parse a valid GPG armored key", ekey)
|
require.NoError(t, err, "Could not parse a valid GPG armored key", ekey)
|
||||||
|
|
||||||
pubkey := ekey.PrimaryKey
|
pubkey := ekey.PrimaryKey
|
||||||
content, err := base64EncPubKey(pubkey)
|
content, err := base64EncPubKey(pubkey)
|
||||||
assert.NoError(t, err, "Could not base64 encode a valid PublicKey content", ekey)
|
require.NoError(t, err, "Could not base64 encode a valid PublicKey content", ekey)
|
||||||
|
|
||||||
key := &GPGKey{
|
key := &GPGKey{
|
||||||
KeyID: pubkey.KeyIdString(),
|
KeyID: pubkey.KeyIdString(),
|
||||||
|
@ -176,27 +177,27 @@ Unknown GPG key with good email
|
||||||
`
|
`
|
||||||
// Reading Sign
|
// Reading Sign
|
||||||
goodSig, err := extractSignature(testGoodSigArmor)
|
goodSig, err := extractSignature(testGoodSigArmor)
|
||||||
assert.NoError(t, err, "Could not parse a valid GPG armored signature", testGoodSigArmor)
|
require.NoError(t, err, "Could not parse a valid GPG armored signature", testGoodSigArmor)
|
||||||
badSig, err := extractSignature(testBadSigArmor)
|
badSig, err := extractSignature(testBadSigArmor)
|
||||||
assert.NoError(t, err, "Could not parse a valid GPG armored signature", testBadSigArmor)
|
require.NoError(t, err, "Could not parse a valid GPG armored signature", testBadSigArmor)
|
||||||
|
|
||||||
// Generating hash of commit
|
// Generating hash of commit
|
||||||
goodHash, err := populateHash(goodSig.Hash, []byte(testGoodPayload))
|
goodHash, err := populateHash(goodSig.Hash, []byte(testGoodPayload))
|
||||||
assert.NoError(t, err, "Could not generate a valid hash of payload", testGoodPayload)
|
require.NoError(t, err, "Could not generate a valid hash of payload", testGoodPayload)
|
||||||
badHash, err := populateHash(badSig.Hash, []byte(testBadPayload))
|
badHash, err := populateHash(badSig.Hash, []byte(testBadPayload))
|
||||||
assert.NoError(t, err, "Could not generate a valid hash of payload", testBadPayload)
|
require.NoError(t, err, "Could not generate a valid hash of payload", testBadPayload)
|
||||||
|
|
||||||
// Verify
|
// Verify
|
||||||
err = verifySign(goodSig, goodHash, key)
|
err = verifySign(goodSig, goodHash, key)
|
||||||
assert.NoError(t, err, "Could not validate a good signature")
|
require.NoError(t, err, "Could not validate a good signature")
|
||||||
err = verifySign(badSig, badHash, key)
|
err = verifySign(badSig, badHash, key)
|
||||||
assert.Error(t, err, "Validate a bad signature")
|
require.Error(t, err, "Validate a bad signature")
|
||||||
err = verifySign(goodSig, goodHash, cannotsignkey)
|
err = verifySign(goodSig, goodHash, cannotsignkey)
|
||||||
assert.Error(t, err, "Validate a bad signature with a kay that can not sign")
|
require.Error(t, err, "Validate a bad signature with a kay that can not sign")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCheckGPGUserEmail(t *testing.T) {
|
func TestCheckGPGUserEmail(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
_ = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
_ = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||||
|
|
||||||
|
@ -232,7 +233,7 @@ Q0KHb+QcycSgbDx0ZAvdIacuKvBBcbxrsmFUI4LR+oIup0G9gUc0roPvr014jYQL
|
||||||
-----END PGP PUBLIC KEY BLOCK-----`
|
-----END PGP PUBLIC KEY BLOCK-----`
|
||||||
|
|
||||||
keys, err := AddGPGKey(db.DefaultContext, 1, testEmailWithUpperCaseLetters, "", "")
|
keys, err := AddGPGKey(db.DefaultContext, 1, testEmailWithUpperCaseLetters, "", "")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
if assert.NotEmpty(t, keys) {
|
if assert.NotEmpty(t, keys) {
|
||||||
key := keys[0]
|
key := keys[0]
|
||||||
if assert.Len(t, key.Emails, 1) {
|
if assert.Len(t, key.Emails, 1) {
|
||||||
|
@ -242,10 +243,10 @@ Q0KHb+QcycSgbDx0ZAvdIacuKvBBcbxrsmFUI4LR+oIup0G9gUc0roPvr014jYQL
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCheckGPGRevokedIdentity(t *testing.T) {
|
func TestCheckGPGRevokedIdentity(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
assert.NoError(t, db.Insert(db.DefaultContext, &user_model.EmailAddress{UID: 1, Email: "no-reply@golang.com", IsActivated: true}))
|
require.NoError(t, db.Insert(db.DefaultContext, &user_model.EmailAddress{UID: 1, Email: "no-reply@golang.com", IsActivated: true}))
|
||||||
assert.NoError(t, db.Insert(db.DefaultContext, &user_model.EmailAddress{UID: 1, Email: "revoked@golang.com", IsActivated: true}))
|
require.NoError(t, db.Insert(db.DefaultContext, &user_model.EmailAddress{UID: 1, Email: "revoked@golang.com", IsActivated: true}))
|
||||||
_ = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
_ = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||||
|
|
||||||
revokedUserKey := `-----BEGIN PGP PUBLIC KEY BLOCK-----
|
revokedUserKey := `-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||||
|
@ -289,7 +290,7 @@ heiQvzkApQup5c+BhH5zFDFdKJ2CBByxw9+7QjMFI/wgLixKuE0Ob2kAokXf7RlB
|
||||||
`
|
`
|
||||||
|
|
||||||
keys, err := AddGPGKey(db.DefaultContext, 1, revokedUserKey, "", "")
|
keys, err := AddGPGKey(db.DefaultContext, 1, revokedUserKey, "", "")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Len(t, keys, 1)
|
assert.Len(t, keys, 1)
|
||||||
assert.Len(t, keys[0].Emails, 1)
|
assert.Len(t, keys[0].Emails, 1)
|
||||||
assert.EqualValues(t, "no-reply@golang.com", keys[0].Emails[0].Email)
|
assert.EqualValues(t, "no-reply@golang.com", keys[0].Emails[0].Email)
|
||||||
|
@ -446,7 +447,7 @@ epiDVQ==
|
||||||
-----END PGP PUBLIC KEY BLOCK-----
|
-----END PGP PUBLIC KEY BLOCK-----
|
||||||
`
|
`
|
||||||
keys, err := checkArmoredGPGKeyString(testIssue6599)
|
keys, err := checkArmoredGPGKeyString(testIssue6599)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
if assert.NotEmpty(t, keys) {
|
if assert.NotEmpty(t, keys) {
|
||||||
ekey := keys[0]
|
ekey := keys[0]
|
||||||
expire := getExpiryTime(ekey)
|
expire := getExpiryTime(ekey)
|
||||||
|
|
|
@ -229,35 +229,26 @@ func UpdatePublicKeyUpdated(ctx context.Context, id int64) error {
|
||||||
|
|
||||||
// PublicKeysAreExternallyManaged returns whether the provided KeyID represents an externally managed Key
|
// PublicKeysAreExternallyManaged returns whether the provided KeyID represents an externally managed Key
|
||||||
func PublicKeysAreExternallyManaged(ctx context.Context, keys []*PublicKey) ([]bool, error) {
|
func PublicKeysAreExternallyManaged(ctx context.Context, keys []*PublicKey) ([]bool, error) {
|
||||||
sources := make([]*auth.Source, 0, 5)
|
sourceCache := make(map[int64]*auth.Source, len(keys))
|
||||||
externals := make([]bool, len(keys))
|
externals := make([]bool, len(keys))
|
||||||
keyloop:
|
|
||||||
for i, key := range keys {
|
for i, key := range keys {
|
||||||
if key.LoginSourceID == 0 {
|
if key.LoginSourceID == 0 {
|
||||||
externals[i] = false
|
externals[i] = false
|
||||||
continue keyloop
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var source *auth.Source
|
source, ok := sourceCache[key.LoginSourceID]
|
||||||
|
if !ok {
|
||||||
sourceloop:
|
|
||||||
for _, s := range sources {
|
|
||||||
if s.ID == key.LoginSourceID {
|
|
||||||
source = s
|
|
||||||
break sourceloop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if source == nil {
|
|
||||||
var err error
|
var err error
|
||||||
source, err = auth.GetSourceByID(ctx, key.LoginSourceID)
|
source, err = auth.GetSourceByID(ctx, key.LoginSourceID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if auth.IsErrSourceNotExist(err) {
|
if auth.IsErrSourceNotExist(err) {
|
||||||
externals[i] = false
|
externals[i] = false
|
||||||
sources[i] = &auth.Source{
|
sourceCache[key.LoginSourceID] = &auth.Source{
|
||||||
ID: key.LoginSourceID,
|
ID: key.LoginSourceID,
|
||||||
}
|
}
|
||||||
continue keyloop
|
continue
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,10 +14,11 @@ import (
|
||||||
"code.gitea.io/gitea/modules/test"
|
"code.gitea.io/gitea/modules/test"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestParseCommitWithSSHSignature(t *testing.T) {
|
func TestParseCommitWithSSHSignature(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
sshKey := unittest.AssertExistsAndLoadBean(t, &PublicKey{ID: 1000, OwnerID: 2})
|
sshKey := unittest.AssertExistsAndLoadBean(t, &PublicKey{ID: 1000, OwnerID: 2})
|
||||||
|
|
||||||
|
|
|
@ -12,10 +12,13 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/unittest"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
|
||||||
"github.com/42wim/sshsig"
|
"github.com/42wim/sshsig"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_SSHParsePublicKey(t *testing.T) {
|
func Test_SSHParsePublicKey(t *testing.T) {
|
||||||
|
@ -26,7 +29,6 @@ func Test_SSHParsePublicKey(t *testing.T) {
|
||||||
length int
|
length int
|
||||||
content string
|
content string
|
||||||
}{
|
}{
|
||||||
{"dsa-1024", false, "dsa", 1024, "ssh-dss AAAAB3NzaC1kc3MAAACBAOChCC7lf6Uo9n7BmZ6M8St19PZf4Tn59NriyboW2x/DZuYAz3ibZ2OkQ3S0SqDIa0HXSEJ1zaExQdmbO+Ux/wsytWZmCczWOVsaszBZSl90q8UnWlSH6P+/YA+RWJm5SFtuV9PtGIhyZgoNuz5kBQ7K139wuQsecdKktISwTakzAAAAFQCzKsO2JhNKlL+wwwLGOcLffoAmkwAAAIBpK7/3xvduajLBD/9vASqBQIHrgK2J+wiQnIb/Wzy0UsVmvfn8A+udRbBo+csM8xrSnlnlJnjkJS3qiM5g+eTwsLIV1IdKPEwmwB+VcP53Cw6lSyWyJcvhFb0N6s08NZysLzvj0N+ZC/FnhKTLzIyMtkHf/IrPCwlM+pV/M/96YgAAAIEAqQcGn9CKgzgPaguIZooTAOQdvBLMI5y0bQjOW6734XOpqQGf/Kra90wpoasLKZjSYKNPjE+FRUOrStLrxcNs4BeVKhy2PYTRnybfYVk1/dmKgH6P1YSRONsGKvTsH6c5IyCRG0ncCgYeF8tXppyd642982daopE7zQ/NPAnJfag= nocomment"},
|
|
||||||
{"rsa-1024", false, "rsa", 1024, "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDAu7tvIvX6ZHrRXuZNfkR3XLHSsuCK9Zn3X58lxBcQzuo5xZgB6vRwwm/QtJuF+zZPtY5hsQILBLmF+BZ5WpKZp1jBeSjH2G7lxet9kbcH+kIVj0tPFEoyKI9wvWqIwC4prx/WVk2wLTJjzBAhyNxfEq7C9CeiX9pQEbEqJfkKCQ== nocomment\n"},
|
{"rsa-1024", false, "rsa", 1024, "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDAu7tvIvX6ZHrRXuZNfkR3XLHSsuCK9Zn3X58lxBcQzuo5xZgB6vRwwm/QtJuF+zZPtY5hsQILBLmF+BZ5WpKZp1jBeSjH2G7lxet9kbcH+kIVj0tPFEoyKI9wvWqIwC4prx/WVk2wLTJjzBAhyNxfEq7C9CeiX9pQEbEqJfkKCQ== nocomment\n"},
|
||||||
{"rsa-2048", false, "rsa", 2048, "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDMZXh+1OBUwSH9D45wTaxErQIN9IoC9xl7MKJkqvTvv6O5RR9YW/IK9FbfjXgXsppYGhsCZo1hFOOsXHMnfOORqu/xMDx4yPuyvKpw4LePEcg4TDipaDFuxbWOqc/BUZRZcXu41QAWfDLrInwsltWZHSeG7hjhpacl4FrVv9V1pS6Oc5Q1NxxEzTzuNLS/8diZrTm/YAQQ/+B+mzWI3zEtF4miZjjAljWd1LTBPvU23d29DcBmmFahcZ441XZsTeAwGxG/Q6j8NgNXj9WxMeWwxXV2jeAX/EBSpZrCVlCQ1yJswT6xCp8TuBnTiGWYMBNTbOZvPC4e0WI2/yZW/s5F nocomment"},
|
{"rsa-2048", false, "rsa", 2048, "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDMZXh+1OBUwSH9D45wTaxErQIN9IoC9xl7MKJkqvTvv6O5RR9YW/IK9FbfjXgXsppYGhsCZo1hFOOsXHMnfOORqu/xMDx4yPuyvKpw4LePEcg4TDipaDFuxbWOqc/BUZRZcXu41QAWfDLrInwsltWZHSeG7hjhpacl4FrVv9V1pS6Oc5Q1NxxEzTzuNLS/8diZrTm/YAQQ/+B+mzWI3zEtF4miZjjAljWd1LTBPvU23d29DcBmmFahcZ441XZsTeAwGxG/Q6j8NgNXj9WxMeWwxXV2jeAX/EBSpZrCVlCQ1yJswT6xCp8TuBnTiGWYMBNTbOZvPC4e0WI2/yZW/s5F nocomment"},
|
||||||
{"ecdsa-256", false, "ecdsa", 256, "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFQacN3PrOll7PXmN5B/ZNVahiUIqI05nbBlZk1KXsO3d06ktAWqbNflv2vEmA38bTFTfJ2sbn2B5ksT52cDDbA= nocomment"},
|
{"ecdsa-256", false, "ecdsa", 256, "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFQacN3PrOll7PXmN5B/ZNVahiUIqI05nbBlZk1KXsO3d06ktAWqbNflv2vEmA38bTFTfJ2sbn2B5ksT52cDDbA= nocomment"},
|
||||||
|
@ -39,7 +41,7 @@ func Test_SSHParsePublicKey(t *testing.T) {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
t.Run("Native", func(t *testing.T) {
|
t.Run("Native", func(t *testing.T) {
|
||||||
keyTypeN, lengthN, err := SSHNativeParsePublicKey(tc.content)
|
keyTypeN, lengthN, err := SSHNativeParsePublicKey(tc.content)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, tc.keyType, keyTypeN)
|
assert.Equal(t, tc.keyType, keyTypeN)
|
||||||
assert.EqualValues(t, tc.length, lengthN)
|
assert.EqualValues(t, tc.length, lengthN)
|
||||||
})
|
})
|
||||||
|
@ -75,7 +77,6 @@ func Test_CheckPublicKeyString(t *testing.T) {
|
||||||
for _, test := range []struct {
|
for _, test := range []struct {
|
||||||
content string
|
content string
|
||||||
}{
|
}{
|
||||||
{"ssh-dss AAAAB3NzaC1kc3MAAACBAOChCC7lf6Uo9n7BmZ6M8St19PZf4Tn59NriyboW2x/DZuYAz3ibZ2OkQ3S0SqDIa0HXSEJ1zaExQdmbO+Ux/wsytWZmCczWOVsaszBZSl90q8UnWlSH6P+/YA+RWJm5SFtuV9PtGIhyZgoNuz5kBQ7K139wuQsecdKktISwTakzAAAAFQCzKsO2JhNKlL+wwwLGOcLffoAmkwAAAIBpK7/3xvduajLBD/9vASqBQIHrgK2J+wiQnIb/Wzy0UsVmvfn8A+udRbBo+csM8xrSnlnlJnjkJS3qiM5g+eTwsLIV1IdKPEwmwB+VcP53Cw6lSyWyJcvhFb0N6s08NZysLzvj0N+ZC/FnhKTLzIyMtkHf/IrPCwlM+pV/M/96YgAAAIEAqQcGn9CKgzgPaguIZooTAOQdvBLMI5y0bQjOW6734XOpqQGf/Kra90wpoasLKZjSYKNPjE+FRUOrStLrxcNs4BeVKhy2PYTRnybfYVk1/dmKgH6P1YSRONsGKvTsH6c5IyCRG0ncCgYeF8tXppyd642982daopE7zQ/NPAnJfag= nocomment"},
|
|
||||||
{"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDAu7tvIvX6ZHrRXuZNfkR3XLHSsuCK9Zn3X58lxBcQzuo5xZgB6vRwwm/QtJuF+zZPtY5hsQILBLmF+BZ5WpKZp1jBeSjH2G7lxet9kbcH+kIVj0tPFEoyKI9wvWqIwC4prx/WVk2wLTJjzBAhyNxfEq7C9CeiX9pQEbEqJfkKCQ== nocomment\n"},
|
{"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDAu7tvIvX6ZHrRXuZNfkR3XLHSsuCK9Zn3X58lxBcQzuo5xZgB6vRwwm/QtJuF+zZPtY5hsQILBLmF+BZ5WpKZp1jBeSjH2G7lxet9kbcH+kIVj0tPFEoyKI9wvWqIwC4prx/WVk2wLTJjzBAhyNxfEq7C9CeiX9pQEbEqJfkKCQ== nocomment\n"},
|
||||||
{"ssh-rsa AAAAB3NzaC1yc2EA\r\nAAADAQABAAAAgQDAu7tvIvX6ZHrRXuZNfkR3XLHSsuCK9Zn3X58lxBcQzuo5xZgB6vRwwm/QtJuF+zZPtY5hsQILBLmF+\r\nBZ5WpKZp1jBeSjH2G7lxet9kbcH+kIVj0tPFEoyKI9wvWqIwC4prx/WVk2wLTJjzBAhyNx\r\nfEq7C9CeiX9pQEbEqJfkKCQ== nocomment\r\n\r\n"},
|
{"ssh-rsa AAAAB3NzaC1yc2EA\r\nAAADAQABAAAAgQDAu7tvIvX6ZHrRXuZNfkR3XLHSsuCK9Zn3X58lxBcQzuo5xZgB6vRwwm/QtJuF+zZPtY5hsQILBLmF+\r\nBZ5WpKZp1jBeSjH2G7lxet9kbcH+kIVj0tPFEoyKI9wvWqIwC4prx/WVk2wLTJjzBAhyNx\r\nfEq7C9CeiX9pQEbEqJfkKCQ== nocomment\r\n\r\n"},
|
||||||
{"ssh-rsa AAAAB3NzaC1yc2EA\r\nAAADAQABAAAAgQDAu7tvI\nvX6ZHrRXuZNfkR3XLHSsuCK9Zn3X58lxBcQzuo5xZgB6vRwwm/QtJuF+zZPtY5hsQILBLmF+\r\nBZ5WpKZp1jBeSjH2G7lxet9kbcH+kIVj0tPFEoyKI9wvW\nqIwC4prx/WVk2wLTJjzBAhyNx\r\nfEq7C9CeiX9pQEbEqJfkKCQ== nocomment\r\n\r\n"},
|
{"ssh-rsa AAAAB3NzaC1yc2EA\r\nAAADAQABAAAAgQDAu7tvI\nvX6ZHrRXuZNfkR3XLHSsuCK9Zn3X58lxBcQzuo5xZgB6vRwwm/QtJuF+zZPtY5hsQILBLmF+\r\nBZ5WpKZp1jBeSjH2G7lxet9kbcH+kIVj0tPFEoyKI9wvW\nqIwC4prx/WVk2wLTJjzBAhyNx\r\nfEq7C9CeiX9pQEbEqJfkKCQ== nocomment\r\n\r\n"},
|
||||||
|
@ -146,7 +147,7 @@ AAAAC3NzaC1lZDI1NTE5AAAAICV0MGX/W9IvLA4FXpIuUcdDcbj5KX4syHgsTy7soVgf
|
||||||
`},
|
`},
|
||||||
} {
|
} {
|
||||||
_, err := CheckPublicKeyString(test.content)
|
_, err := CheckPublicKeyString(test.content)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
setting.SSH.MinimumKeySizeCheck = oldValue
|
setting.SSH.MinimumKeySizeCheck = oldValue
|
||||||
for _, invalidKeys := range []struct {
|
for _, invalidKeys := range []struct {
|
||||||
|
@ -159,7 +160,7 @@ AAAAC3NzaC1lZDI1NTE5AAAAICV0MGX/W9IvLA4FXpIuUcdDcbj5KX4syHgsTy7soVgf
|
||||||
{"\r\ntest \r\ngitea\r\n\r\n"},
|
{"\r\ntest \r\ngitea\r\n\r\n"},
|
||||||
} {
|
} {
|
||||||
_, err := CheckPublicKeyString(invalidKeys.content)
|
_, err := CheckPublicKeyString(invalidKeys.content)
|
||||||
assert.Error(t, err)
|
require.Error(t, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,7 +171,6 @@ func Test_calcFingerprint(t *testing.T) {
|
||||||
fp string
|
fp string
|
||||||
content string
|
content string
|
||||||
}{
|
}{
|
||||||
{"dsa-1024", false, "SHA256:fSIHQlpKMDsGPVAXI8BPYfRp+e2sfvSt1sMrPsFiXrc", "ssh-dss AAAAB3NzaC1kc3MAAACBAOChCC7lf6Uo9n7BmZ6M8St19PZf4Tn59NriyboW2x/DZuYAz3ibZ2OkQ3S0SqDIa0HXSEJ1zaExQdmbO+Ux/wsytWZmCczWOVsaszBZSl90q8UnWlSH6P+/YA+RWJm5SFtuV9PtGIhyZgoNuz5kBQ7K139wuQsecdKktISwTakzAAAAFQCzKsO2JhNKlL+wwwLGOcLffoAmkwAAAIBpK7/3xvduajLBD/9vASqBQIHrgK2J+wiQnIb/Wzy0UsVmvfn8A+udRbBo+csM8xrSnlnlJnjkJS3qiM5g+eTwsLIV1IdKPEwmwB+VcP53Cw6lSyWyJcvhFb0N6s08NZysLzvj0N+ZC/FnhKTLzIyMtkHf/IrPCwlM+pV/M/96YgAAAIEAqQcGn9CKgzgPaguIZooTAOQdvBLMI5y0bQjOW6734XOpqQGf/Kra90wpoasLKZjSYKNPjE+FRUOrStLrxcNs4BeVKhy2PYTRnybfYVk1/dmKgH6P1YSRONsGKvTsH6c5IyCRG0ncCgYeF8tXppyd642982daopE7zQ/NPAnJfag= nocomment"},
|
|
||||||
{"rsa-1024", false, "SHA256:vSnDkvRh/xM6kMxPidLgrUhq3mCN7CDaronCEm2joyQ", "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDAu7tvIvX6ZHrRXuZNfkR3XLHSsuCK9Zn3X58lxBcQzuo5xZgB6vRwwm/QtJuF+zZPtY5hsQILBLmF+BZ5WpKZp1jBeSjH2G7lxet9kbcH+kIVj0tPFEoyKI9wvWqIwC4prx/WVk2wLTJjzBAhyNxfEq7C9CeiX9pQEbEqJfkKCQ== nocomment\n"},
|
{"rsa-1024", false, "SHA256:vSnDkvRh/xM6kMxPidLgrUhq3mCN7CDaronCEm2joyQ", "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDAu7tvIvX6ZHrRXuZNfkR3XLHSsuCK9Zn3X58lxBcQzuo5xZgB6vRwwm/QtJuF+zZPtY5hsQILBLmF+BZ5WpKZp1jBeSjH2G7lxet9kbcH+kIVj0tPFEoyKI9wvWqIwC4prx/WVk2wLTJjzBAhyNxfEq7C9CeiX9pQEbEqJfkKCQ== nocomment\n"},
|
||||||
{"rsa-2048", false, "SHA256:ZHD//a1b9VuTq9XSunAeYjKeU1xDa2tBFZYrFr2Okkg", "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDMZXh+1OBUwSH9D45wTaxErQIN9IoC9xl7MKJkqvTvv6O5RR9YW/IK9FbfjXgXsppYGhsCZo1hFOOsXHMnfOORqu/xMDx4yPuyvKpw4LePEcg4TDipaDFuxbWOqc/BUZRZcXu41QAWfDLrInwsltWZHSeG7hjhpacl4FrVv9V1pS6Oc5Q1NxxEzTzuNLS/8diZrTm/YAQQ/+B+mzWI3zEtF4miZjjAljWd1LTBPvU23d29DcBmmFahcZ441XZsTeAwGxG/Q6j8NgNXj9WxMeWwxXV2jeAX/EBSpZrCVlCQ1yJswT6xCp8TuBnTiGWYMBNTbOZvPC4e0WI2/yZW/s5F nocomment"},
|
{"rsa-2048", false, "SHA256:ZHD//a1b9VuTq9XSunAeYjKeU1xDa2tBFZYrFr2Okkg", "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDMZXh+1OBUwSH9D45wTaxErQIN9IoC9xl7MKJkqvTvv6O5RR9YW/IK9FbfjXgXsppYGhsCZo1hFOOsXHMnfOORqu/xMDx4yPuyvKpw4LePEcg4TDipaDFuxbWOqc/BUZRZcXu41QAWfDLrInwsltWZHSeG7hjhpacl4FrVv9V1pS6Oc5Q1NxxEzTzuNLS/8diZrTm/YAQQ/+B+mzWI3zEtF4miZjjAljWd1LTBPvU23d29DcBmmFahcZ441XZsTeAwGxG/Q6j8NgNXj9WxMeWwxXV2jeAX/EBSpZrCVlCQ1yJswT6xCp8TuBnTiGWYMBNTbOZvPC4e0WI2/yZW/s5F nocomment"},
|
||||||
{"ecdsa-256", false, "SHA256:Bqx/xgWqRKLtkZ0Lr4iZpgb+5lYsFpSwXwVZbPwuTRw", "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFQacN3PrOll7PXmN5B/ZNVahiUIqI05nbBlZk1KXsO3d06ktAWqbNflv2vEmA38bTFTfJ2sbn2B5ksT52cDDbA= nocomment"},
|
{"ecdsa-256", false, "SHA256:Bqx/xgWqRKLtkZ0Lr4iZpgb+5lYsFpSwXwVZbPwuTRw", "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFQacN3PrOll7PXmN5B/ZNVahiUIqI05nbBlZk1KXsO3d06ktAWqbNflv2vEmA38bTFTfJ2sbn2B5ksT52cDDbA= nocomment"},
|
||||||
|
@ -183,7 +183,7 @@ func Test_calcFingerprint(t *testing.T) {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
t.Run("Native", func(t *testing.T) {
|
t.Run("Native", func(t *testing.T) {
|
||||||
fpN, err := calcFingerprintNative(tc.content)
|
fpN, err := calcFingerprintNative(tc.content)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, tc.fp, fpN)
|
assert.Equal(t, tc.fp, fpN)
|
||||||
})
|
})
|
||||||
if tc.skipSSHKeygen {
|
if tc.skipSSHKeygen {
|
||||||
|
@ -191,7 +191,7 @@ func Test_calcFingerprint(t *testing.T) {
|
||||||
}
|
}
|
||||||
t.Run("SSHKeygen", func(t *testing.T) {
|
t.Run("SSHKeygen", func(t *testing.T) {
|
||||||
fpK, err := calcFingerprintSSHKeygen(tc.content)
|
fpK, err := calcFingerprintSSHKeygen(tc.content)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, tc.fp, fpK)
|
assert.Equal(t, tc.fp, fpK)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -503,3 +503,11 @@ func runErr(t *testing.T, stdin []byte, args ...string) {
|
||||||
t.Fatal("expected error")
|
t.Fatal("expected error")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_PublicKeysAreExternallyManaged(t *testing.T) {
|
||||||
|
key1 := unittest.AssertExistsAndLoadBean(t, &PublicKey{ID: 1})
|
||||||
|
externals, err := PublicKeysAreExternallyManaged(db.DefaultContext, []*PublicKey{key1})
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Len(t, externals, 1)
|
||||||
|
assert.False(t, externals[0])
|
||||||
|
}
|
||||||
|
|
|
@ -11,15 +11,16 @@ import (
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNewAccessToken(t *testing.T) {
|
func TestNewAccessToken(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
token := &auth_model.AccessToken{
|
token := &auth_model.AccessToken{
|
||||||
UID: 3,
|
UID: 3,
|
||||||
Name: "Token C",
|
Name: "Token C",
|
||||||
}
|
}
|
||||||
assert.NoError(t, auth_model.NewAccessToken(db.DefaultContext, token))
|
require.NoError(t, auth_model.NewAccessToken(db.DefaultContext, token))
|
||||||
unittest.AssertExistsAndLoadBean(t, token)
|
unittest.AssertExistsAndLoadBean(t, token)
|
||||||
|
|
||||||
invalidToken := &auth_model.AccessToken{
|
invalidToken := &auth_model.AccessToken{
|
||||||
|
@ -27,13 +28,13 @@ func TestNewAccessToken(t *testing.T) {
|
||||||
UID: 2,
|
UID: 2,
|
||||||
Name: "Token F",
|
Name: "Token F",
|
||||||
}
|
}
|
||||||
assert.Error(t, auth_model.NewAccessToken(db.DefaultContext, invalidToken))
|
require.Error(t, auth_model.NewAccessToken(db.DefaultContext, invalidToken))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAccessTokenByNameExists(t *testing.T) {
|
func TestAccessTokenByNameExists(t *testing.T) {
|
||||||
name := "Token Gitea"
|
name := "Token Gitea"
|
||||||
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
token := &auth_model.AccessToken{
|
token := &auth_model.AccessToken{
|
||||||
UID: 3,
|
UID: 3,
|
||||||
Name: name,
|
Name: name,
|
||||||
|
@ -41,16 +42,16 @@ func TestAccessTokenByNameExists(t *testing.T) {
|
||||||
|
|
||||||
// Check to make sure it doesn't exists already
|
// Check to make sure it doesn't exists already
|
||||||
exist, err := auth_model.AccessTokenByNameExists(db.DefaultContext, token)
|
exist, err := auth_model.AccessTokenByNameExists(db.DefaultContext, token)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.False(t, exist)
|
assert.False(t, exist)
|
||||||
|
|
||||||
// Save it to the database
|
// Save it to the database
|
||||||
assert.NoError(t, auth_model.NewAccessToken(db.DefaultContext, token))
|
require.NoError(t, auth_model.NewAccessToken(db.DefaultContext, token))
|
||||||
unittest.AssertExistsAndLoadBean(t, token)
|
unittest.AssertExistsAndLoadBean(t, token)
|
||||||
|
|
||||||
// This token must be found by name in the DB now
|
// This token must be found by name in the DB now
|
||||||
exist, err = auth_model.AccessTokenByNameExists(db.DefaultContext, token)
|
exist, err = auth_model.AccessTokenByNameExists(db.DefaultContext, token)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.True(t, exist)
|
assert.True(t, exist)
|
||||||
|
|
||||||
user4Token := &auth_model.AccessToken{
|
user4Token := &auth_model.AccessToken{
|
||||||
|
@ -61,32 +62,32 @@ func TestAccessTokenByNameExists(t *testing.T) {
|
||||||
// Name matches but different user ID, this shouldn't exists in the
|
// Name matches but different user ID, this shouldn't exists in the
|
||||||
// database
|
// database
|
||||||
exist, err = auth_model.AccessTokenByNameExists(db.DefaultContext, user4Token)
|
exist, err = auth_model.AccessTokenByNameExists(db.DefaultContext, user4Token)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.False(t, exist)
|
assert.False(t, exist)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetAccessTokenBySHA(t *testing.T) {
|
func TestGetAccessTokenBySHA(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
token, err := auth_model.GetAccessTokenBySHA(db.DefaultContext, "d2c6c1ba3890b309189a8e618c72a162e4efbf36")
|
token, err := auth_model.GetAccessTokenBySHA(db.DefaultContext, "d2c6c1ba3890b309189a8e618c72a162e4efbf36")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, int64(1), token.UID)
|
assert.Equal(t, int64(1), token.UID)
|
||||||
assert.Equal(t, "Token A", token.Name)
|
assert.Equal(t, "Token A", token.Name)
|
||||||
assert.Equal(t, "2b3668e11cb82d3af8c6e4524fc7841297668f5008d1626f0ad3417e9fa39af84c268248b78c481daa7e5dc437784003494f", token.TokenHash)
|
assert.Equal(t, "2b3668e11cb82d3af8c6e4524fc7841297668f5008d1626f0ad3417e9fa39af84c268248b78c481daa7e5dc437784003494f", token.TokenHash)
|
||||||
assert.Equal(t, "e4efbf36", token.TokenLastEight)
|
assert.Equal(t, "e4efbf36", token.TokenLastEight)
|
||||||
|
|
||||||
_, err = auth_model.GetAccessTokenBySHA(db.DefaultContext, "notahash")
|
_, err = auth_model.GetAccessTokenBySHA(db.DefaultContext, "notahash")
|
||||||
assert.Error(t, err)
|
require.Error(t, err)
|
||||||
assert.True(t, auth_model.IsErrAccessTokenNotExist(err))
|
assert.True(t, auth_model.IsErrAccessTokenNotExist(err))
|
||||||
|
|
||||||
_, err = auth_model.GetAccessTokenBySHA(db.DefaultContext, "")
|
_, err = auth_model.GetAccessTokenBySHA(db.DefaultContext, "")
|
||||||
assert.Error(t, err)
|
require.Error(t, err)
|
||||||
assert.True(t, auth_model.IsErrAccessTokenEmpty(err))
|
assert.True(t, auth_model.IsErrAccessTokenEmpty(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestListAccessTokens(t *testing.T) {
|
func TestListAccessTokens(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
tokens, err := db.Find[auth_model.AccessToken](db.DefaultContext, auth_model.ListAccessTokensOptions{UserID: 1})
|
tokens, err := db.Find[auth_model.AccessToken](db.DefaultContext, auth_model.ListAccessTokensOptions{UserID: 1})
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
if assert.Len(t, tokens, 2) {
|
if assert.Len(t, tokens, 2) {
|
||||||
assert.Equal(t, int64(1), tokens[0].UID)
|
assert.Equal(t, int64(1), tokens[0].UID)
|
||||||
assert.Equal(t, int64(1), tokens[1].UID)
|
assert.Equal(t, int64(1), tokens[1].UID)
|
||||||
|
@ -95,38 +96,38 @@ func TestListAccessTokens(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
tokens, err = db.Find[auth_model.AccessToken](db.DefaultContext, auth_model.ListAccessTokensOptions{UserID: 2})
|
tokens, err = db.Find[auth_model.AccessToken](db.DefaultContext, auth_model.ListAccessTokensOptions{UserID: 2})
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
if assert.Len(t, tokens, 1) {
|
if assert.Len(t, tokens, 1) {
|
||||||
assert.Equal(t, int64(2), tokens[0].UID)
|
assert.Equal(t, int64(2), tokens[0].UID)
|
||||||
assert.Equal(t, "Token A", tokens[0].Name)
|
assert.Equal(t, "Token A", tokens[0].Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
tokens, err = db.Find[auth_model.AccessToken](db.DefaultContext, auth_model.ListAccessTokensOptions{UserID: 100})
|
tokens, err = db.Find[auth_model.AccessToken](db.DefaultContext, auth_model.ListAccessTokensOptions{UserID: 100})
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Empty(t, tokens)
|
assert.Empty(t, tokens)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUpdateAccessToken(t *testing.T) {
|
func TestUpdateAccessToken(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
token, err := auth_model.GetAccessTokenBySHA(db.DefaultContext, "4c6f36e6cf498e2a448662f915d932c09c5a146c")
|
token, err := auth_model.GetAccessTokenBySHA(db.DefaultContext, "4c6f36e6cf498e2a448662f915d932c09c5a146c")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
token.Name = "Token Z"
|
token.Name = "Token Z"
|
||||||
|
|
||||||
assert.NoError(t, auth_model.UpdateAccessToken(db.DefaultContext, token))
|
require.NoError(t, auth_model.UpdateAccessToken(db.DefaultContext, token))
|
||||||
unittest.AssertExistsAndLoadBean(t, token)
|
unittest.AssertExistsAndLoadBean(t, token)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDeleteAccessTokenByID(t *testing.T) {
|
func TestDeleteAccessTokenByID(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
token, err := auth_model.GetAccessTokenBySHA(db.DefaultContext, "4c6f36e6cf498e2a448662f915d932c09c5a146c")
|
token, err := auth_model.GetAccessTokenBySHA(db.DefaultContext, "4c6f36e6cf498e2a448662f915d932c09c5a146c")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, int64(1), token.UID)
|
assert.Equal(t, int64(1), token.UID)
|
||||||
|
|
||||||
assert.NoError(t, auth_model.DeleteAccessTokenByID(db.DefaultContext, token.ID, 1))
|
require.NoError(t, auth_model.DeleteAccessTokenByID(db.DefaultContext, token.ID, 1))
|
||||||
unittest.AssertNotExistsBean(t, token)
|
unittest.AssertNotExistsBean(t, token)
|
||||||
|
|
||||||
err = auth_model.DeleteAccessTokenByID(db.DefaultContext, 100, 100)
|
err = auth_model.DeleteAccessTokenByID(db.DefaultContext, 100, 100)
|
||||||
assert.Error(t, err)
|
require.Error(t, err)
|
||||||
assert.True(t, auth_model.IsErrAccessTokenNotExist(err))
|
assert.True(t, auth_model.IsErrAccessTokenNotExist(err))
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,12 +15,31 @@ import (
|
||||||
"code.gitea.io/gitea/modules/util"
|
"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.
|
// AuthorizationToken represents a authorization token to a user.
|
||||||
type AuthorizationToken struct {
|
type AuthorizationToken struct {
|
||||||
ID int64 `xorm:"pk autoincr"`
|
ID int64 `xorm:"pk autoincr"`
|
||||||
UID int64 `xorm:"INDEX"`
|
UID int64 `xorm:"INDEX"`
|
||||||
LookupKey string `xorm:"INDEX UNIQUE"`
|
LookupKey string `xorm:"INDEX UNIQUE"`
|
||||||
HashedValidator string
|
HashedValidator string
|
||||||
|
Purpose AuthorizationPurpose `xorm:"NOT NULL DEFAULT 'long_term_authorization'"`
|
||||||
Expiry timeutil.TimeStamp
|
Expiry timeutil.TimeStamp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +60,7 @@ func (authToken *AuthorizationToken) IsExpired() bool {
|
||||||
// GenerateAuthToken generates a new authentication token for the given user.
|
// GenerateAuthToken generates a new authentication token for the given user.
|
||||||
// It returns the lookup key and validator values that should be passed to the
|
// It returns the lookup key and validator values that should be passed to the
|
||||||
// user via a long-term cookie.
|
// 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
|
// 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.
|
// and the other 32 bytes will be used for the validator.
|
||||||
rBytes, err := util.CryptoRandomBytes(64)
|
rBytes, err := util.CryptoRandomBytes(64)
|
||||||
|
@ -56,14 +75,15 @@ func GenerateAuthToken(ctx context.Context, userID int64, expiry timeutil.TimeSt
|
||||||
Expiry: expiry,
|
Expiry: expiry,
|
||||||
LookupKey: lookupKey,
|
LookupKey: lookupKey,
|
||||||
HashedValidator: HashValidator(rBytes[32:]),
|
HashedValidator: HashValidator(rBytes[32:]),
|
||||||
|
Purpose: purpose,
|
||||||
})
|
})
|
||||||
return lookupKey, validator, err
|
return lookupKey, validator, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindAuthToken will find a authorization token via the lookup key.
|
// 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
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else if !has {
|
} else if !has {
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
_ "code.gitea.io/gitea/models/actions"
|
_ "code.gitea.io/gitea/models/actions"
|
||||||
_ "code.gitea.io/gitea/models/activities"
|
_ "code.gitea.io/gitea/models/activities"
|
||||||
_ "code.gitea.io/gitea/models/auth"
|
_ "code.gitea.io/gitea/models/auth"
|
||||||
|
_ "code.gitea.io/gitea/models/forgefed"
|
||||||
_ "code.gitea.io/gitea/models/perm/access"
|
_ "code.gitea.io/gitea/models/perm/access"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -14,19 +14,20 @@ import (
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestOAuth2Application_GenerateClientSecret(t *testing.T) {
|
func TestOAuth2Application_GenerateClientSecret(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
app := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: 1})
|
app := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: 1})
|
||||||
secret, err := app.GenerateClientSecret(db.DefaultContext)
|
secret, err := app.GenerateClientSecret(db.DefaultContext)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.True(t, len(secret) > 0)
|
assert.NotEmpty(t, secret)
|
||||||
unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: 1, ClientSecret: app.ClientSecret})
|
unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: 1, ClientSecret: app.ClientSecret})
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkOAuth2Application_GenerateClientSecret(b *testing.B) {
|
func BenchmarkOAuth2Application_GenerateClientSecret(b *testing.B) {
|
||||||
assert.NoError(b, unittest.PrepareTestDatabase())
|
require.NoError(b, unittest.PrepareTestDatabase())
|
||||||
app := unittest.AssertExistsAndLoadBean(b, &auth_model.OAuth2Application{ID: 1})
|
app := unittest.AssertExistsAndLoadBean(b, &auth_model.OAuth2Application{ID: 1})
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
_, _ = app.GenerateClientSecret(db.DefaultContext)
|
_, _ = app.GenerateClientSecret(db.DefaultContext)
|
||||||
|
@ -77,29 +78,29 @@ func TestOAuth2Application_ContainsRedirect_Slash(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestOAuth2Application_ValidateClientSecret(t *testing.T) {
|
func TestOAuth2Application_ValidateClientSecret(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
app := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: 1})
|
app := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: 1})
|
||||||
secret, err := app.GenerateClientSecret(db.DefaultContext)
|
secret, err := app.GenerateClientSecret(db.DefaultContext)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.True(t, app.ValidateClientSecret([]byte(secret)))
|
assert.True(t, app.ValidateClientSecret([]byte(secret)))
|
||||||
assert.False(t, app.ValidateClientSecret([]byte("fewijfowejgfiowjeoifew")))
|
assert.False(t, app.ValidateClientSecret([]byte("fewijfowejgfiowjeoifew")))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetOAuth2ApplicationByClientID(t *testing.T) {
|
func TestGetOAuth2ApplicationByClientID(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
app, err := auth_model.GetOAuth2ApplicationByClientID(db.DefaultContext, "da7da3ba-9a13-4167-856f-3899de0b0138")
|
app, err := auth_model.GetOAuth2ApplicationByClientID(db.DefaultContext, "da7da3ba-9a13-4167-856f-3899de0b0138")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, "da7da3ba-9a13-4167-856f-3899de0b0138", app.ClientID)
|
assert.Equal(t, "da7da3ba-9a13-4167-856f-3899de0b0138", app.ClientID)
|
||||||
|
|
||||||
app, err = auth_model.GetOAuth2ApplicationByClientID(db.DefaultContext, "invalid client id")
|
app, err = auth_model.GetOAuth2ApplicationByClientID(db.DefaultContext, "invalid client id")
|
||||||
assert.Error(t, err)
|
require.Error(t, err)
|
||||||
assert.Nil(t, app)
|
assert.Nil(t, app)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateOAuth2Application(t *testing.T) {
|
func TestCreateOAuth2Application(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
app, err := auth_model.CreateOAuth2Application(db.DefaultContext, auth_model.CreateOAuth2ApplicationOptions{Name: "newapp", UserID: 1})
|
app, err := auth_model.CreateOAuth2Application(db.DefaultContext, auth_model.CreateOAuth2ApplicationOptions{Name: "newapp", UserID: 1})
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, "newapp", app.Name)
|
assert.Equal(t, "newapp", app.Name)
|
||||||
assert.Len(t, app.ClientID, 36)
|
assert.Len(t, app.ClientID, 36)
|
||||||
unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{Name: "newapp"})
|
unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{Name: "newapp"})
|
||||||
|
@ -110,22 +111,22 @@ func TestOAuth2Application_TableName(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestOAuth2Application_GetGrantByUserID(t *testing.T) {
|
func TestOAuth2Application_GetGrantByUserID(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
app := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: 1})
|
app := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: 1})
|
||||||
grant, err := app.GetGrantByUserID(db.DefaultContext, 1)
|
grant, err := app.GetGrantByUserID(db.DefaultContext, 1)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, int64(1), grant.UserID)
|
assert.Equal(t, int64(1), grant.UserID)
|
||||||
|
|
||||||
grant, err = app.GetGrantByUserID(db.DefaultContext, 34923458)
|
grant, err = app.GetGrantByUserID(db.DefaultContext, 34923458)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Nil(t, grant)
|
assert.Nil(t, grant)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestOAuth2Application_CreateGrant(t *testing.T) {
|
func TestOAuth2Application_CreateGrant(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
app := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: 1})
|
app := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: 1})
|
||||||
grant, err := app.CreateGrant(db.DefaultContext, 2, "")
|
grant, err := app.CreateGrant(db.DefaultContext, 2, "")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.NotNil(t, grant)
|
assert.NotNil(t, grant)
|
||||||
assert.Equal(t, int64(2), grant.UserID)
|
assert.Equal(t, int64(2), grant.UserID)
|
||||||
assert.Equal(t, int64(1), grant.ApplicationID)
|
assert.Equal(t, int64(1), grant.ApplicationID)
|
||||||
|
@ -135,26 +136,26 @@ func TestOAuth2Application_CreateGrant(t *testing.T) {
|
||||||
//////////////////// Grant
|
//////////////////// Grant
|
||||||
|
|
||||||
func TestGetOAuth2GrantByID(t *testing.T) {
|
func TestGetOAuth2GrantByID(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
grant, err := auth_model.GetOAuth2GrantByID(db.DefaultContext, 1)
|
grant, err := auth_model.GetOAuth2GrantByID(db.DefaultContext, 1)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, int64(1), grant.ID)
|
assert.Equal(t, int64(1), grant.ID)
|
||||||
|
|
||||||
grant, err = auth_model.GetOAuth2GrantByID(db.DefaultContext, 34923458)
|
grant, err = auth_model.GetOAuth2GrantByID(db.DefaultContext, 34923458)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Nil(t, grant)
|
assert.Nil(t, grant)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestOAuth2Grant_IncreaseCounter(t *testing.T) {
|
func TestOAuth2Grant_IncreaseCounter(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
grant := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Grant{ID: 1, Counter: 1})
|
grant := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Grant{ID: 1, Counter: 1})
|
||||||
assert.NoError(t, grant.IncreaseCounter(db.DefaultContext))
|
require.NoError(t, grant.IncreaseCounter(db.DefaultContext))
|
||||||
assert.Equal(t, int64(2), grant.Counter)
|
assert.Equal(t, int64(2), grant.Counter)
|
||||||
unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Grant{ID: 1, Counter: 2})
|
unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Grant{ID: 1, Counter: 2})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestOAuth2Grant_ScopeContains(t *testing.T) {
|
func TestOAuth2Grant_ScopeContains(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
grant := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Grant{ID: 1, Scope: "openid profile"})
|
grant := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Grant{ID: 1, Scope: "openid profile"})
|
||||||
assert.True(t, grant.ScopeContains("openid"))
|
assert.True(t, grant.ScopeContains("openid"))
|
||||||
assert.True(t, grant.ScopeContains("profile"))
|
assert.True(t, grant.ScopeContains("profile"))
|
||||||
|
@ -163,12 +164,12 @@ func TestOAuth2Grant_ScopeContains(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestOAuth2Grant_GenerateNewAuthorizationCode(t *testing.T) {
|
func TestOAuth2Grant_GenerateNewAuthorizationCode(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
grant := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Grant{ID: 1})
|
grant := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Grant{ID: 1})
|
||||||
code, err := grant.GenerateNewAuthorizationCode(db.DefaultContext, "https://example2.com/callback", "CjvyTLSdR47G5zYenDA-eDWW4lRrO8yvjcWwbD_deOg", "S256")
|
code, err := grant.GenerateNewAuthorizationCode(db.DefaultContext, "https://example2.com/callback", "CjvyTLSdR47G5zYenDA-eDWW4lRrO8yvjcWwbD_deOg", "S256")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.NotNil(t, code)
|
assert.NotNil(t, code)
|
||||||
assert.True(t, len(code.Code) > 32) // secret length > 32
|
assert.Greater(t, len(code.Code), 32) // secret length > 32
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestOAuth2Grant_TableName(t *testing.T) {
|
func TestOAuth2Grant_TableName(t *testing.T) {
|
||||||
|
@ -176,36 +177,36 @@ func TestOAuth2Grant_TableName(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetOAuth2GrantsByUserID(t *testing.T) {
|
func TestGetOAuth2GrantsByUserID(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
result, err := auth_model.GetOAuth2GrantsByUserID(db.DefaultContext, 1)
|
result, err := auth_model.GetOAuth2GrantsByUserID(db.DefaultContext, 1)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Len(t, result, 1)
|
assert.Len(t, result, 1)
|
||||||
assert.Equal(t, int64(1), result[0].ID)
|
assert.Equal(t, int64(1), result[0].ID)
|
||||||
assert.Equal(t, result[0].ApplicationID, result[0].Application.ID)
|
assert.Equal(t, result[0].ApplicationID, result[0].Application.ID)
|
||||||
|
|
||||||
result, err = auth_model.GetOAuth2GrantsByUserID(db.DefaultContext, 34134)
|
result, err = auth_model.GetOAuth2GrantsByUserID(db.DefaultContext, 34134)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Empty(t, result)
|
assert.Empty(t, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRevokeOAuth2Grant(t *testing.T) {
|
func TestRevokeOAuth2Grant(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
assert.NoError(t, auth_model.RevokeOAuth2Grant(db.DefaultContext, 1, 1))
|
require.NoError(t, auth_model.RevokeOAuth2Grant(db.DefaultContext, 1, 1))
|
||||||
unittest.AssertNotExistsBean(t, &auth_model.OAuth2Grant{ID: 1, UserID: 1})
|
unittest.AssertNotExistsBean(t, &auth_model.OAuth2Grant{ID: 1, UserID: 1})
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////// Authorization Code
|
//////////////////// Authorization Code
|
||||||
|
|
||||||
func TestGetOAuth2AuthorizationByCode(t *testing.T) {
|
func TestGetOAuth2AuthorizationByCode(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
code, err := auth_model.GetOAuth2AuthorizationByCode(db.DefaultContext, "authcode")
|
code, err := auth_model.GetOAuth2AuthorizationByCode(db.DefaultContext, "authcode")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.NotNil(t, code)
|
assert.NotNil(t, code)
|
||||||
assert.Equal(t, "authcode", code.Code)
|
assert.Equal(t, "authcode", code.Code)
|
||||||
assert.Equal(t, int64(1), code.ID)
|
assert.Equal(t, int64(1), code.ID)
|
||||||
|
|
||||||
code, err = auth_model.GetOAuth2AuthorizationByCode(db.DefaultContext, "does not exist")
|
code, err = auth_model.GetOAuth2AuthorizationByCode(db.DefaultContext, "does not exist")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Nil(t, code)
|
assert.Nil(t, code)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,18 +249,18 @@ func TestOAuth2AuthorizationCode_GenerateRedirectURI(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
redirect, err := code.GenerateRedirectURI("thestate")
|
redirect, err := code.GenerateRedirectURI("thestate")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, "https://example.com/callback?code=thecode&state=thestate", redirect.String())
|
assert.Equal(t, "https://example.com/callback?code=thecode&state=thestate", redirect.String())
|
||||||
|
|
||||||
redirect, err = code.GenerateRedirectURI("")
|
redirect, err = code.GenerateRedirectURI("")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, "https://example.com/callback?code=thecode", redirect.String())
|
assert.Equal(t, "https://example.com/callback?code=thecode", redirect.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestOAuth2AuthorizationCode_Invalidate(t *testing.T) {
|
func TestOAuth2AuthorizationCode_Invalidate(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
code := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2AuthorizationCode{Code: "authcode"})
|
code := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2AuthorizationCode{Code: "authcode"})
|
||||||
assert.NoError(t, code.Invalidate(db.DefaultContext))
|
require.NoError(t, code.Invalidate(db.DefaultContext))
|
||||||
unittest.AssertNotExistsBean(t, &auth_model.OAuth2AuthorizationCode{Code: "authcode"})
|
unittest.AssertNotExistsBean(t, &auth_model.OAuth2AuthorizationCode{Code: "authcode"})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,18 +282,18 @@ func TestOrphanedOAuth2Applications(t *testing.T) {
|
||||||
Dirs: []string{"models/auth/TestOrphanedOAuth2Applications/"},
|
Dirs: []string{"models/auth/TestOrphanedOAuth2Applications/"},
|
||||||
},
|
},
|
||||||
)()
|
)()
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
count, err := auth_model.CountOrphanedOAuth2Applications(db.DefaultContext)
|
count, err := auth_model.CountOrphanedOAuth2Applications(db.DefaultContext)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.EqualValues(t, 1, count)
|
assert.EqualValues(t, 1, count)
|
||||||
unittest.AssertExistsIf(t, true, &auth_model.OAuth2Application{ID: 1002})
|
unittest.AssertExistsIf(t, true, &auth_model.OAuth2Application{ID: 1002})
|
||||||
|
|
||||||
_, err = auth_model.DeleteOrphanedOAuth2Applications(db.DefaultContext)
|
_, err = auth_model.DeleteOrphanedOAuth2Applications(db.DefaultContext)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
count, err = auth_model.CountOrphanedOAuth2Applications(db.DefaultContext)
|
count, err = auth_model.CountOrphanedOAuth2Applications(db.DefaultContext)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.EqualValues(t, 0, count)
|
assert.EqualValues(t, 0, count)
|
||||||
unittest.AssertExistsIf(t, false, &auth_model.OAuth2Application{ID: 1002})
|
unittest.AssertExistsIf(t, false, &auth_model.OAuth2Application{ID: 1002})
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,10 +13,11 @@ import (
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestAuthSession(t *testing.T) {
|
func TestAuthSession(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
defer timeutil.MockUnset()
|
defer timeutil.MockUnset()
|
||||||
|
|
||||||
key := "I-Like-Free-Software"
|
key := "I-Like-Free-Software"
|
||||||
|
@ -24,30 +25,30 @@ func TestAuthSession(t *testing.T) {
|
||||||
t.Run("Create Session", func(t *testing.T) {
|
t.Run("Create Session", func(t *testing.T) {
|
||||||
// Ensure it doesn't exist.
|
// Ensure it doesn't exist.
|
||||||
ok, err := auth.ExistSession(db.DefaultContext, key)
|
ok, err := auth.ExistSession(db.DefaultContext, key)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.False(t, ok)
|
assert.False(t, ok)
|
||||||
|
|
||||||
preCount, err := auth.CountSessions(db.DefaultContext)
|
preCount, err := auth.CountSessions(db.DefaultContext)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
now := time.Date(2021, 1, 1, 0, 0, 0, 0, time.UTC)
|
now := time.Date(2021, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||||
timeutil.MockSet(now)
|
timeutil.MockSet(now)
|
||||||
|
|
||||||
// New session is created.
|
// New session is created.
|
||||||
sess, err := auth.ReadSession(db.DefaultContext, key)
|
sess, err := auth.ReadSession(db.DefaultContext, key)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.EqualValues(t, key, sess.Key)
|
assert.EqualValues(t, key, sess.Key)
|
||||||
assert.Empty(t, sess.Data)
|
assert.Empty(t, sess.Data)
|
||||||
assert.EqualValues(t, now.Unix(), sess.Expiry)
|
assert.EqualValues(t, now.Unix(), sess.Expiry)
|
||||||
|
|
||||||
// Ensure it exists.
|
// Ensure it exists.
|
||||||
ok, err = auth.ExistSession(db.DefaultContext, key)
|
ok, err = auth.ExistSession(db.DefaultContext, key)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
|
|
||||||
// Ensure the session is taken into account for count..
|
// Ensure the session is taken into account for count..
|
||||||
postCount, err := auth.CountSessions(db.DefaultContext)
|
postCount, err := auth.CountSessions(db.DefaultContext)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Greater(t, postCount, preCount)
|
assert.Greater(t, postCount, preCount)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -58,14 +59,14 @@ func TestAuthSession(t *testing.T) {
|
||||||
|
|
||||||
// Update session.
|
// Update session.
|
||||||
err := auth.UpdateSession(db.DefaultContext, key, data)
|
err := auth.UpdateSession(db.DefaultContext, key, data)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
timeutil.MockSet(time.Date(2021, 1, 1, 0, 0, 0, 0, time.UTC))
|
timeutil.MockSet(time.Date(2021, 1, 1, 0, 0, 0, 0, time.UTC))
|
||||||
|
|
||||||
// Read updated session.
|
// Read updated session.
|
||||||
// Ensure data is updated and expiry is set from the update session call.
|
// Ensure data is updated and expiry is set from the update session call.
|
||||||
sess, err := auth.ReadSession(db.DefaultContext, key)
|
sess, err := auth.ReadSession(db.DefaultContext, key)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.EqualValues(t, key, sess.Key)
|
assert.EqualValues(t, key, sess.Key)
|
||||||
assert.EqualValues(t, data, sess.Data)
|
assert.EqualValues(t, data, sess.Data)
|
||||||
assert.EqualValues(t, now.Unix(), sess.Expiry)
|
assert.EqualValues(t, now.Unix(), sess.Expiry)
|
||||||
|
@ -76,23 +77,23 @@ func TestAuthSession(t *testing.T) {
|
||||||
t.Run("Delete session", func(t *testing.T) {
|
t.Run("Delete session", func(t *testing.T) {
|
||||||
// Ensure it't exist.
|
// Ensure it't exist.
|
||||||
ok, err := auth.ExistSession(db.DefaultContext, key)
|
ok, err := auth.ExistSession(db.DefaultContext, key)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
|
|
||||||
preCount, err := auth.CountSessions(db.DefaultContext)
|
preCount, err := auth.CountSessions(db.DefaultContext)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = auth.DestroySession(db.DefaultContext, key)
|
err = auth.DestroySession(db.DefaultContext, key)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Ensure it doesn't exists.
|
// Ensure it doesn't exists.
|
||||||
ok, err = auth.ExistSession(db.DefaultContext, key)
|
ok, err = auth.ExistSession(db.DefaultContext, key)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.False(t, ok)
|
assert.False(t, ok)
|
||||||
|
|
||||||
// Ensure the session is taken into account for count..
|
// Ensure the session is taken into account for count..
|
||||||
postCount, err := auth.CountSessions(db.DefaultContext)
|
postCount, err := auth.CountSessions(db.DefaultContext)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Less(t, postCount, preCount)
|
assert.Less(t, postCount, preCount)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -100,43 +101,43 @@ func TestAuthSession(t *testing.T) {
|
||||||
timeutil.MockSet(time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC))
|
timeutil.MockSet(time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC))
|
||||||
|
|
||||||
_, err := auth.ReadSession(db.DefaultContext, "sess-1")
|
_, err := auth.ReadSession(db.DefaultContext, "sess-1")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// One minute later.
|
// One minute later.
|
||||||
timeutil.MockSet(time.Date(2023, 1, 1, 0, 1, 0, 0, time.UTC))
|
timeutil.MockSet(time.Date(2023, 1, 1, 0, 1, 0, 0, time.UTC))
|
||||||
_, err = auth.ReadSession(db.DefaultContext, "sess-2")
|
_, err = auth.ReadSession(db.DefaultContext, "sess-2")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// 5 minutes, shouldn't clean up anything.
|
// 5 minutes, shouldn't clean up anything.
|
||||||
err = auth.CleanupSessions(db.DefaultContext, 5*60)
|
err = auth.CleanupSessions(db.DefaultContext, 5*60)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
ok, err := auth.ExistSession(db.DefaultContext, "sess-1")
|
ok, err := auth.ExistSession(db.DefaultContext, "sess-1")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
|
|
||||||
ok, err = auth.ExistSession(db.DefaultContext, "sess-2")
|
ok, err = auth.ExistSession(db.DefaultContext, "sess-2")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
|
|
||||||
// 1 minute, should clean up sess-1.
|
// 1 minute, should clean up sess-1.
|
||||||
err = auth.CleanupSessions(db.DefaultContext, 60)
|
err = auth.CleanupSessions(db.DefaultContext, 60)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
ok, err = auth.ExistSession(db.DefaultContext, "sess-1")
|
ok, err = auth.ExistSession(db.DefaultContext, "sess-1")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.False(t, ok)
|
assert.False(t, ok)
|
||||||
|
|
||||||
ok, err = auth.ExistSession(db.DefaultContext, "sess-2")
|
ok, err = auth.ExistSession(db.DefaultContext, "sess-2")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
|
|
||||||
// Now, should clean up sess-2.
|
// Now, should clean up sess-2.
|
||||||
err = auth.CleanupSessions(db.DefaultContext, 0)
|
err = auth.CleanupSessions(db.DefaultContext, 0)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
ok, err = auth.ExistSession(db.DefaultContext, "sess-2")
|
ok, err = auth.ExistSession(db.DefaultContext, "sess-2")
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.False(t, ok)
|
assert.False(t, ok)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -216,7 +216,7 @@ func CreateSource(ctx context.Context, source *Source) error {
|
||||||
return ErrSourceAlreadyExist{source.Name}
|
return ErrSourceAlreadyExist{source.Name}
|
||||||
}
|
}
|
||||||
// Synchronization is only available with LDAP for now
|
// Synchronization is only available with LDAP for now
|
||||||
if !source.IsLDAP() {
|
if !source.IsLDAP() && !source.IsOAuth2() {
|
||||||
source.IsSyncEnabled = false
|
source.IsSyncEnabled = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/json"
|
"code.gitea.io/gitea/modules/json"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
"xorm.io/xorm/schemas"
|
"xorm.io/xorm/schemas"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -35,10 +36,10 @@ func (source *TestSource) ToDB() ([]byte, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDumpAuthSource(t *testing.T) {
|
func TestDumpAuthSource(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
authSourceSchema, err := db.TableInfo(new(auth_model.Source))
|
authSourceSchema, err := db.TableInfo(new(auth_model.Source))
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
auth_model.RegisterTypeConfig(auth_model.OAuth2, new(TestSource))
|
auth_model.RegisterTypeConfig(auth_model.OAuth2, new(TestSource))
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ func IsErrWebAuthnCredentialNotExist(err error) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// WebAuthnCredential represents the WebAuthn credential data for a public-key
|
// WebAuthnCredential represents the WebAuthn credential data for a public-key
|
||||||
// credential conformant to WebAuthn Level 1
|
// credential conformant to WebAuthn Level 3
|
||||||
type WebAuthnCredential struct {
|
type WebAuthnCredential struct {
|
||||||
ID int64 `xorm:"pk autoincr"`
|
ID int64 `xorm:"pk autoincr"`
|
||||||
Name string
|
Name string
|
||||||
|
@ -52,6 +52,10 @@ type WebAuthnCredential struct {
|
||||||
AAGUID []byte
|
AAGUID []byte
|
||||||
SignCount uint32 `xorm:"BIGINT"`
|
SignCount uint32 `xorm:"BIGINT"`
|
||||||
CloneWarning bool
|
CloneWarning bool
|
||||||
|
BackupEligible bool `XORM:"NOT NULL DEFAULT false"`
|
||||||
|
BackupState bool `XORM:"NOT NULL DEFAULT false"`
|
||||||
|
// If legacy is set to true, backup_eligible and backup_state isn't set.
|
||||||
|
Legacy bool `XORM:"NOT NULL DEFAULT true"`
|
||||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
|
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
|
||||||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
|
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
|
||||||
}
|
}
|
||||||
|
@ -71,6 +75,12 @@ func (cred *WebAuthnCredential) UpdateSignCount(ctx context.Context) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateFromLegacy update the values that aren't present on legacy credentials.
|
||||||
|
func (cred *WebAuthnCredential) UpdateFromLegacy(ctx context.Context) error {
|
||||||
|
_, err := db.GetEngine(ctx).ID(cred.ID).Cols("legacy", "backup_eligible", "backup_state").Update(cred)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// BeforeInsert will be invoked by XORM before updating a record
|
// BeforeInsert will be invoked by XORM before updating a record
|
||||||
func (cred *WebAuthnCredential) BeforeInsert() {
|
func (cred *WebAuthnCredential) BeforeInsert() {
|
||||||
cred.LowerName = strings.ToLower(cred.Name)
|
cred.LowerName = strings.ToLower(cred.Name)
|
||||||
|
@ -97,6 +107,10 @@ func (list WebAuthnCredentialList) ToCredentials() []webauthn.Credential {
|
||||||
ID: cred.CredentialID,
|
ID: cred.CredentialID,
|
||||||
PublicKey: cred.PublicKey,
|
PublicKey: cred.PublicKey,
|
||||||
AttestationType: cred.AttestationType,
|
AttestationType: cred.AttestationType,
|
||||||
|
Flags: webauthn.CredentialFlags{
|
||||||
|
BackupEligible: cred.BackupEligible,
|
||||||
|
BackupState: cred.BackupState,
|
||||||
|
},
|
||||||
Authenticator: webauthn.Authenticator{
|
Authenticator: webauthn.Authenticator{
|
||||||
AAGUID: cred.AAGUID,
|
AAGUID: cred.AAGUID,
|
||||||
SignCount: cred.SignCount,
|
SignCount: cred.SignCount,
|
||||||
|
@ -167,6 +181,9 @@ func CreateCredential(ctx context.Context, userID int64, name string, cred *weba
|
||||||
AAGUID: cred.Authenticator.AAGUID,
|
AAGUID: cred.Authenticator.AAGUID,
|
||||||
SignCount: cred.Authenticator.SignCount,
|
SignCount: cred.Authenticator.SignCount,
|
||||||
CloneWarning: false,
|
CloneWarning: false,
|
||||||
|
BackupEligible: cred.Flags.BackupEligible,
|
||||||
|
BackupState: cred.Flags.BackupState,
|
||||||
|
Legacy: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := db.Insert(ctx, c); err != nil {
|
if err := db.Insert(ctx, c); err != nil {
|
||||||
|
|
|
@ -12,25 +12,26 @@ import (
|
||||||
|
|
||||||
"github.com/go-webauthn/webauthn/webauthn"
|
"github.com/go-webauthn/webauthn/webauthn"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetWebAuthnCredentialByID(t *testing.T) {
|
func TestGetWebAuthnCredentialByID(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
res, err := auth_model.GetWebAuthnCredentialByID(db.DefaultContext, 1)
|
res, err := auth_model.GetWebAuthnCredentialByID(db.DefaultContext, 1)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, "WebAuthn credential", res.Name)
|
assert.Equal(t, "WebAuthn credential", res.Name)
|
||||||
|
|
||||||
_, err = auth_model.GetWebAuthnCredentialByID(db.DefaultContext, 342432)
|
_, err = auth_model.GetWebAuthnCredentialByID(db.DefaultContext, 342432)
|
||||||
assert.Error(t, err)
|
require.Error(t, err)
|
||||||
assert.True(t, auth_model.IsErrWebAuthnCredentialNotExist(err))
|
assert.True(t, auth_model.IsErrWebAuthnCredentialNotExist(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetWebAuthnCredentialsByUID(t *testing.T) {
|
func TestGetWebAuthnCredentialsByUID(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
res, err := auth_model.GetWebAuthnCredentialsByUID(db.DefaultContext, 32)
|
res, err := auth_model.GetWebAuthnCredentialsByUID(db.DefaultContext, 32)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Len(t, res, 1)
|
assert.Len(t, res, 1)
|
||||||
assert.Equal(t, "WebAuthn credential", res[0].Name)
|
assert.Equal(t, "WebAuthn credential", res[0].Name)
|
||||||
}
|
}
|
||||||
|
@ -40,28 +41,38 @@ func TestWebAuthnCredential_TableName(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWebAuthnCredential_UpdateSignCount(t *testing.T) {
|
func TestWebAuthnCredential_UpdateSignCount(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
cred := unittest.AssertExistsAndLoadBean(t, &auth_model.WebAuthnCredential{ID: 1})
|
cred := unittest.AssertExistsAndLoadBean(t, &auth_model.WebAuthnCredential{ID: 1})
|
||||||
cred.SignCount = 1
|
cred.SignCount = 1
|
||||||
assert.NoError(t, cred.UpdateSignCount(db.DefaultContext))
|
require.NoError(t, cred.UpdateSignCount(db.DefaultContext))
|
||||||
unittest.AssertExistsIf(t, true, &auth_model.WebAuthnCredential{ID: 1, SignCount: 1})
|
unittest.AssertExistsIf(t, true, &auth_model.WebAuthnCredential{ID: 1, SignCount: 1})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWebAuthnCredential_UpdateLargeCounter(t *testing.T) {
|
func TestWebAuthnCredential_UpdateLargeCounter(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
cred := unittest.AssertExistsAndLoadBean(t, &auth_model.WebAuthnCredential{ID: 1})
|
cred := unittest.AssertExistsAndLoadBean(t, &auth_model.WebAuthnCredential{ID: 1})
|
||||||
cred.SignCount = 0xffffffff
|
cred.SignCount = 0xffffffff
|
||||||
assert.NoError(t, cred.UpdateSignCount(db.DefaultContext))
|
require.NoError(t, cred.UpdateSignCount(db.DefaultContext))
|
||||||
unittest.AssertExistsIf(t, true, &auth_model.WebAuthnCredential{ID: 1, SignCount: 0xffffffff})
|
unittest.AssertExistsIf(t, true, &auth_model.WebAuthnCredential{ID: 1, SignCount: 0xffffffff})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateCredential(t *testing.T) {
|
func TestWebAuthenCredential_UpdateFromLegacy(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
cred := unittest.AssertExistsAndLoadBean(t, &auth_model.WebAuthnCredential{ID: 1, Legacy: true})
|
||||||
|
cred.Legacy = false
|
||||||
|
cred.BackupEligible = true
|
||||||
|
cred.BackupState = true
|
||||||
|
require.NoError(t, cred.UpdateFromLegacy(db.DefaultContext))
|
||||||
|
unittest.AssertExistsIf(t, true, &auth_model.WebAuthnCredential{ID: 1, BackupEligible: true, BackupState: true}, "legacy = false")
|
||||||
|
}
|
||||||
|
|
||||||
res, err := auth_model.CreateCredential(db.DefaultContext, 1, "WebAuthn Created Credential", &webauthn.Credential{ID: []byte("Test")})
|
func TestCreateCredential(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
res, err := auth_model.CreateCredential(db.DefaultContext, 1, "WebAuthn Created Credential", &webauthn.Credential{ID: []byte("Test"), Flags: webauthn.CredentialFlags{BackupEligible: true, BackupState: true}})
|
||||||
|
require.NoError(t, err)
|
||||||
assert.Equal(t, "WebAuthn Created Credential", res.Name)
|
assert.Equal(t, "WebAuthn Created Credential", res.Name)
|
||||||
assert.Equal(t, []byte("Test"), res.CredentialID)
|
assert.Equal(t, []byte("Test"), res.CredentialID)
|
||||||
|
|
||||||
unittest.AssertExistsIf(t, true, &auth_model.WebAuthnCredential{Name: "WebAuthn Created Credential", UserID: 1})
|
unittest.AssertExistsIf(t, true, &auth_model.WebAuthnCredential{Name: "WebAuthn Created Credential", UserID: 1, BackupEligible: true, BackupState: true}, "legacy = false")
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
|
||||||
"strk.kbt.io/projects/go/libravatar"
|
"code.forgejo.org/forgejo-contrib/go-libravatar"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue