mirror of
https://github.com/go-gitea/gitea.git
synced 2025-11-08 05:02:38 +09:00
Compare commits
71 Commits
v1.22.2
...
v1.21.0-rc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5b670d83e1 | ||
|
|
9207331f4d | ||
|
|
44aca6a65a | ||
|
|
aaf35ee49c | ||
|
|
a9d547f55b | ||
|
|
51001d9ffe | ||
|
|
1ff6b7783c | ||
|
|
99e2071eeb | ||
|
|
1dd84ec3a1 | ||
|
|
290440e1ee | ||
|
|
881a844c9d | ||
|
|
d5da0e622c | ||
|
|
8c6464e39b | ||
|
|
4f02b4a7b9 | ||
|
|
7dc5ab2e95 | ||
|
|
28d970e4a6 | ||
|
|
4e824a735e | ||
|
|
eea79ce586 | ||
|
|
e9340ce9bc | ||
|
|
de387102b4 | ||
|
|
79c17d8b6a | ||
|
|
006c15fb5f | ||
|
|
0c4f97c112 | ||
|
|
f9395eaa08 | ||
|
|
f13a294b47 | ||
|
|
84ee02faa7 | ||
|
|
f77b4cb4a2 | ||
|
|
7ea7f2b37f | ||
|
|
c61b9c5f3c | ||
|
|
e719bf8ead | ||
|
|
9903b8d7ec | ||
|
|
77ccd215e2 | ||
|
|
71d1bfea7f | ||
|
|
b00489886d | ||
|
|
9b698362a3 | ||
|
|
1a923c95dd | ||
|
|
a6a79add68 | ||
|
|
d74fba8175 | ||
|
|
e4cf9d22a7 | ||
|
|
755369df56 | ||
|
|
42f7c2ad89 | ||
|
|
fee8522052 | ||
|
|
34c440996d | ||
|
|
283b19bad5 | ||
|
|
f0045f4113 | ||
|
|
0abd78e6a8 | ||
|
|
fc7d3f7315 | ||
|
|
597b04fe2f | ||
|
|
2774a2afc6 | ||
|
|
89b6f20bf8 | ||
|
|
37c7780e85 | ||
|
|
e0832da7fa | ||
|
|
daaf0ad473 | ||
|
|
9fc24a8f5e | ||
|
|
a1029cb2ca | ||
|
|
134c7636ef | ||
|
|
88271167d6 | ||
|
|
a8086f6148 | ||
|
|
f4f6885c1f | ||
|
|
64c0a6a4e2 | ||
|
|
2181b3713e | ||
|
|
2084c3933d | ||
|
|
b6dab855f5 | ||
|
|
e9fcdf822c | ||
|
|
7750a7313d | ||
|
|
81ae35aa4f | ||
|
|
2e49a4da48 | ||
|
|
8d9e2d07f3 | ||
|
|
b34727c632 | ||
|
|
0ca233258d | ||
|
|
c3b7120042 |
17
.air.toml
17
.air.toml
@@ -2,25 +2,12 @@ root = "."
|
||||
tmp_dir = ".air"
|
||||
|
||||
[build]
|
||||
pre_cmd = ["killall -9 gitea 2>/dev/null || true"] # kill off potential zombie processes from previous runs
|
||||
cmd = "make --no-print-directory backend"
|
||||
bin = "gitea"
|
||||
delay = 2000
|
||||
delay = 1000
|
||||
include_ext = ["go", "tmpl"]
|
||||
include_file = ["main.go"]
|
||||
include_dir = ["cmd", "models", "modules", "options", "routers", "services"]
|
||||
exclude_dir = [
|
||||
"models/fixtures",
|
||||
"models/migrations/fixtures",
|
||||
"modules/avatar/identicon/testdata",
|
||||
"modules/avatar/testdata",
|
||||
"modules/git/tests",
|
||||
"modules/migration/file_format_testdata",
|
||||
"routers/private/tests",
|
||||
"services/gitdiff/testdata",
|
||||
]
|
||||
exclude_dir = ["modules/git/tests", "services/gitdiff/testdata", "modules/avatar/testdata", "models/fixtures", "models/migrations/fixtures", "modules/migration/file_format_testdata", "modules/avatar/identicon/testdata"]
|
||||
exclude_regex = ["_test.go$", "_gen.go$"]
|
||||
stop_on_error = true
|
||||
|
||||
[log]
|
||||
main_only = true
|
||||
|
||||
@@ -13,42 +13,46 @@ groups:
|
||||
-
|
||||
name: BREAKING
|
||||
labels:
|
||||
- pr/breaking
|
||||
- kind/breaking
|
||||
-
|
||||
name: SECURITY
|
||||
labels:
|
||||
- topic/security
|
||||
- kind/security
|
||||
-
|
||||
name: FEATURES
|
||||
labels:
|
||||
- type/feature
|
||||
- kind/feature
|
||||
-
|
||||
name: API
|
||||
labels:
|
||||
- modifies/api
|
||||
- kind/api
|
||||
-
|
||||
name: ENHANCEMENTS
|
||||
labels:
|
||||
- type/enhancement
|
||||
- type/refactoring
|
||||
- topic/ui
|
||||
- kind/enhancement
|
||||
- kind/refactor
|
||||
- kind/ui
|
||||
-
|
||||
name: BUGFIXES
|
||||
labels:
|
||||
- type/bug
|
||||
- kind/bug
|
||||
-
|
||||
name: TESTING
|
||||
labels:
|
||||
- type/testing
|
||||
- kind/testing
|
||||
-
|
||||
name: TRANSLATION
|
||||
labels:
|
||||
- kind/translation
|
||||
-
|
||||
name: BUILD
|
||||
labels:
|
||||
- topic/build
|
||||
- topic/code-linting
|
||||
- kind/build
|
||||
- kind/lint
|
||||
-
|
||||
name: DOCS
|
||||
labels:
|
||||
- type/docs
|
||||
- kind/docs
|
||||
-
|
||||
name: MISC
|
||||
default: true
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
{
|
||||
"name": "Gitea DevContainer",
|
||||
"image": "mcr.microsoft.com/devcontainers/go:1.22-bullseye",
|
||||
"image": "mcr.microsoft.com/devcontainers/go:1.21-bullseye",
|
||||
"features": {
|
||||
// installs nodejs into container
|
||||
"ghcr.io/devcontainers/features/node:1": {
|
||||
"version": "20"
|
||||
"version":"20"
|
||||
},
|
||||
"ghcr.io/devcontainers/features/git-lfs:1.1.0": {},
|
||||
"ghcr.io/devcontainers-contrib/features/poetry:2": {},
|
||||
"ghcr.io/devcontainers/features/python:1": {
|
||||
"version": "3.12"
|
||||
}
|
||||
"ghcr.io/devcontainers/features/python:1": {}
|
||||
},
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
@@ -24,7 +22,7 @@
|
||||
"DavidAnson.vscode-markdownlint",
|
||||
"Vue.volar",
|
||||
"ms-azuretools.vscode-docker",
|
||||
"vitest.explorer",
|
||||
"zixuanchen.vitest-explorer",
|
||||
"qwtel.sqlite-viewer",
|
||||
"GitHub.vscode-pull-request-github"
|
||||
]
|
||||
|
||||
@@ -14,7 +14,7 @@ _test
|
||||
|
||||
# MS VSCode
|
||||
.vscode
|
||||
__debug_bin*
|
||||
__debug_bin
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
@@ -62,6 +62,7 @@ cpu.out
|
||||
/data
|
||||
/indexers
|
||||
/log
|
||||
/public/img/avatar
|
||||
/tests/integration/gitea-integration-*
|
||||
/tests/integration/indexers-*
|
||||
/tests/e2e/gitea-e2e-*
|
||||
@@ -77,7 +78,7 @@ cpu.out
|
||||
/public/assets/js
|
||||
/public/assets/css
|
||||
/public/assets/fonts
|
||||
/public/assets/img/avatar
|
||||
/public/assets/img/webpack
|
||||
/vendor
|
||||
/web_src/fomantic/node_modules
|
||||
/web_src/fomantic/build/*
|
||||
@@ -95,9 +96,6 @@ cpu.out
|
||||
/.air
|
||||
/.go-licenses
|
||||
|
||||
# Files and folders that were previously generated
|
||||
/public/assets/img/webpack
|
||||
|
||||
# Snapcraft
|
||||
snap/.snapcraft/
|
||||
parts/
|
||||
|
||||
428
.drone.yml
Normal file
428
.drone.yml
Normal file
@@ -0,0 +1,428 @@
|
||||
---
|
||||
kind: pipeline
|
||||
name: release-version
|
||||
|
||||
platform:
|
||||
os: linux
|
||||
arch: amd64
|
||||
|
||||
workspace:
|
||||
base: /source
|
||||
path: /
|
||||
|
||||
trigger:
|
||||
event:
|
||||
- tag
|
||||
|
||||
volumes:
|
||||
- name: deps
|
||||
temp: {}
|
||||
|
||||
steps:
|
||||
- name: fetch-tags
|
||||
image: docker:git
|
||||
pull: always
|
||||
commands:
|
||||
- git fetch --tags --force
|
||||
|
||||
- name: deps-frontend
|
||||
image: node:20
|
||||
pull: always
|
||||
commands:
|
||||
- make deps-frontend
|
||||
|
||||
- name: deps-backend
|
||||
image: gitea/test_env:linux-1.20-amd64
|
||||
pull: always
|
||||
commands:
|
||||
- make deps-backend
|
||||
volumes:
|
||||
- name: deps
|
||||
path: /go
|
||||
|
||||
- name: static
|
||||
image: techknowlogick/xgo:go-1.21.x
|
||||
pull: always
|
||||
commands:
|
||||
- apt-get update && apt-get -qqy install ca-certificates curl gnupg
|
||||
- mkdir -p /etc/apt/keyrings && curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
|
||||
- echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_20.x nodistro main" > /etc/apt/sources.list.d/nodesource.list
|
||||
- apt-get update && apt-get -qqy install nodejs
|
||||
- export PATH=$PATH:$GOPATH/bin
|
||||
- make release
|
||||
environment:
|
||||
GOPROXY: https://goproxy.io # proxy.golang.org is blocked in China, this proxy is not
|
||||
TAGS: bindata sqlite sqlite_unlock_notify
|
||||
DEBIAN_FRONTEND: noninteractive
|
||||
depends_on: [fetch-tags]
|
||||
volumes:
|
||||
- name: deps
|
||||
path: /go
|
||||
|
||||
- name: gpg-sign
|
||||
image: plugins/gpgsign:1
|
||||
pull: always
|
||||
settings:
|
||||
detach_sign: true
|
||||
excludes:
|
||||
- "dist/release/*.sha256"
|
||||
files:
|
||||
- "dist/release/*"
|
||||
environment:
|
||||
GPGSIGN_KEY:
|
||||
from_secret: gpgsign_key
|
||||
GPGSIGN_PASSPHRASE:
|
||||
from_secret: gpgsign_passphrase
|
||||
depends_on: [static]
|
||||
|
||||
- name: release-tag
|
||||
image: woodpeckerci/plugin-s3:latest
|
||||
pull: always
|
||||
settings:
|
||||
acl:
|
||||
from_secret: aws_s3_acl
|
||||
region:
|
||||
from_secret: aws_s3_region
|
||||
bucket:
|
||||
from_secret: aws_s3_bucket
|
||||
endpoint:
|
||||
from_secret: aws_s3_endpoint
|
||||
path_style:
|
||||
from_secret: aws_s3_path_style
|
||||
source: "dist/release/*"
|
||||
strip_prefix: dist/release/
|
||||
target: "/gitea/${DRONE_TAG##v}"
|
||||
environment:
|
||||
AWS_ACCESS_KEY_ID:
|
||||
from_secret: aws_access_key_id
|
||||
AWS_SECRET_ACCESS_KEY:
|
||||
from_secret: aws_secret_access_key
|
||||
depends_on: [gpg-sign]
|
||||
|
||||
- name: github
|
||||
image: plugins/github-release:latest
|
||||
pull: always
|
||||
settings:
|
||||
files:
|
||||
- "dist/release/*"
|
||||
file_exists: overwrite
|
||||
environment:
|
||||
GITHUB_TOKEN:
|
||||
from_secret: github_token
|
||||
depends_on: [gpg-sign]
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: docker-linux-amd64-release-version
|
||||
|
||||
platform:
|
||||
os: linux
|
||||
arch: amd64
|
||||
|
||||
trigger:
|
||||
ref:
|
||||
include:
|
||||
- "refs/tags/**"
|
||||
exclude:
|
||||
- "refs/tags/**-rc*"
|
||||
paths:
|
||||
exclude:
|
||||
- "docs/**"
|
||||
|
||||
steps:
|
||||
- name: fetch-tags
|
||||
image: docker:git
|
||||
pull: always
|
||||
commands:
|
||||
- git fetch --tags --force
|
||||
|
||||
- name: publish
|
||||
image: plugins/docker:latest
|
||||
pull: always
|
||||
settings:
|
||||
auto_tag: true
|
||||
auto_tag_suffix: linux-amd64
|
||||
repo: gitea/gitea
|
||||
build_args:
|
||||
- GOPROXY=https://goproxy.io
|
||||
password:
|
||||
from_secret: docker_password
|
||||
username:
|
||||
from_secret: docker_username
|
||||
environment:
|
||||
PLUGIN_MIRROR:
|
||||
from_secret: plugin_mirror
|
||||
DOCKER_BUILDKIT: 1
|
||||
when:
|
||||
event:
|
||||
exclude:
|
||||
- pull_request
|
||||
|
||||
- name: publish-rootless
|
||||
image: plugins/docker:latest
|
||||
settings:
|
||||
dockerfile: Dockerfile.rootless
|
||||
auto_tag: true
|
||||
auto_tag_suffix: linux-amd64-rootless
|
||||
repo: gitea/gitea
|
||||
build_args:
|
||||
- GOPROXY=https://goproxy.io
|
||||
password:
|
||||
from_secret: docker_password
|
||||
username:
|
||||
from_secret: docker_username
|
||||
environment:
|
||||
PLUGIN_MIRROR:
|
||||
from_secret: plugin_mirror
|
||||
DOCKER_BUILDKIT: 1
|
||||
when:
|
||||
event:
|
||||
exclude:
|
||||
- pull_request
|
||||
---
|
||||
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: docker-linux-amd64-release-candidate-version
|
||||
|
||||
platform:
|
||||
os: linux
|
||||
arch: amd64
|
||||
|
||||
trigger:
|
||||
ref:
|
||||
- "refs/tags/**-rc*"
|
||||
paths:
|
||||
exclude:
|
||||
- "docs/**"
|
||||
|
||||
steps:
|
||||
- name: fetch-tags
|
||||
image: docker:git
|
||||
pull: always
|
||||
commands:
|
||||
- git fetch --tags --force
|
||||
|
||||
- name: publish
|
||||
image: plugins/docker:latest
|
||||
pull: always
|
||||
settings:
|
||||
tags: ${DRONE_TAG##v}-linux-amd64
|
||||
repo: gitea/gitea
|
||||
build_args:
|
||||
- GOPROXY=https://goproxy.io
|
||||
password:
|
||||
from_secret: docker_password
|
||||
username:
|
||||
from_secret: docker_username
|
||||
environment:
|
||||
PLUGIN_MIRROR:
|
||||
from_secret: plugin_mirror
|
||||
DOCKER_BUILDKIT: 1
|
||||
when:
|
||||
event:
|
||||
exclude:
|
||||
- pull_request
|
||||
|
||||
- name: publish-rootless
|
||||
image: plugins/docker:latest
|
||||
settings:
|
||||
dockerfile: Dockerfile.rootless
|
||||
tags: ${DRONE_TAG##v}-linux-amd64-rootless
|
||||
repo: gitea/gitea
|
||||
build_args:
|
||||
- GOPROXY=https://goproxy.io
|
||||
password:
|
||||
from_secret: docker_password
|
||||
username:
|
||||
from_secret: docker_username
|
||||
environment:
|
||||
PLUGIN_MIRROR:
|
||||
from_secret: plugin_mirror
|
||||
DOCKER_BUILDKIT: 1
|
||||
when:
|
||||
event:
|
||||
exclude:
|
||||
- pull_request
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: docker-linux-arm64-release-version
|
||||
|
||||
platform:
|
||||
os: linux
|
||||
arch: arm64
|
||||
|
||||
trigger:
|
||||
ref:
|
||||
include:
|
||||
- "refs/tags/**"
|
||||
exclude:
|
||||
- "refs/tags/**-rc*"
|
||||
paths:
|
||||
exclude:
|
||||
- "docs/**"
|
||||
|
||||
steps:
|
||||
- name: fetch-tags
|
||||
image: docker:git
|
||||
pull: always
|
||||
commands:
|
||||
- git fetch --tags --force
|
||||
|
||||
- name: publish
|
||||
image: plugins/docker:latest
|
||||
pull: always
|
||||
settings:
|
||||
auto_tag: true
|
||||
auto_tag_suffix: linux-arm64
|
||||
repo: gitea/gitea
|
||||
build_args:
|
||||
- GOPROXY=https://goproxy.io
|
||||
password:
|
||||
from_secret: docker_password
|
||||
username:
|
||||
from_secret: docker_username
|
||||
environment:
|
||||
PLUGIN_MIRROR:
|
||||
from_secret: plugin_mirror
|
||||
DOCKER_BUILDKIT: 1
|
||||
when:
|
||||
event:
|
||||
exclude:
|
||||
- pull_request
|
||||
|
||||
- name: publish-rootless
|
||||
image: plugins/docker:latest
|
||||
settings:
|
||||
dockerfile: Dockerfile.rootless
|
||||
auto_tag: true
|
||||
auto_tag_suffix: linux-arm64-rootless
|
||||
repo: gitea/gitea
|
||||
build_args:
|
||||
- GOPROXY=https://goproxy.io
|
||||
password:
|
||||
from_secret: docker_password
|
||||
username:
|
||||
from_secret: docker_username
|
||||
environment:
|
||||
PLUGIN_MIRROR:
|
||||
from_secret: plugin_mirror
|
||||
DOCKER_BUILDKIT: 1
|
||||
when:
|
||||
event:
|
||||
exclude:
|
||||
- pull_request
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: docker-linux-arm64-release-candidate-version
|
||||
|
||||
platform:
|
||||
os: linux
|
||||
arch: arm64
|
||||
|
||||
trigger:
|
||||
ref:
|
||||
- "refs/tags/**-rc*"
|
||||
paths:
|
||||
exclude:
|
||||
- "docs/**"
|
||||
|
||||
steps:
|
||||
- name: fetch-tags
|
||||
image: docker:git
|
||||
pull: always
|
||||
commands:
|
||||
- git fetch --tags --force
|
||||
|
||||
- name: publish
|
||||
image: plugins/docker:latest
|
||||
pull: always
|
||||
settings:
|
||||
tags: ${DRONE_TAG##v}-linux-arm64
|
||||
repo: gitea/gitea
|
||||
build_args:
|
||||
- GOPROXY=https://goproxy.io
|
||||
password:
|
||||
from_secret: docker_password
|
||||
username:
|
||||
from_secret: docker_username
|
||||
environment:
|
||||
PLUGIN_MIRROR:
|
||||
from_secret: plugin_mirror
|
||||
DOCKER_BUILDKIT: 1
|
||||
when:
|
||||
event:
|
||||
exclude:
|
||||
- pull_request
|
||||
|
||||
- name: publish-rootless
|
||||
image: plugins/docker:latest
|
||||
settings:
|
||||
dockerfile: Dockerfile.rootless
|
||||
tags: ${DRONE_TAG##v}-linux-arm64-rootless
|
||||
repo: gitea/gitea
|
||||
build_args:
|
||||
- GOPROXY=https://goproxy.io
|
||||
password:
|
||||
from_secret: docker_password
|
||||
username:
|
||||
from_secret: docker_username
|
||||
environment:
|
||||
PLUGIN_MIRROR:
|
||||
from_secret: plugin_mirror
|
||||
DOCKER_BUILDKIT: 1
|
||||
when:
|
||||
event:
|
||||
exclude:
|
||||
- pull_request
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: docker-manifest-version
|
||||
|
||||
platform:
|
||||
os: linux
|
||||
arch: amd64
|
||||
|
||||
steps:
|
||||
- name: manifest-rootless
|
||||
image: plugins/manifest
|
||||
pull: always
|
||||
settings:
|
||||
auto_tag: true
|
||||
ignore_missing: true
|
||||
spec: docker/manifest.rootless.tmpl
|
||||
password:
|
||||
from_secret: docker_password
|
||||
username:
|
||||
from_secret: docker_username
|
||||
|
||||
- name: manifest
|
||||
image: plugins/manifest
|
||||
settings:
|
||||
auto_tag: true
|
||||
ignore_missing: true
|
||||
spec: docker/manifest.tmpl
|
||||
password:
|
||||
from_secret: docker_password
|
||||
username:
|
||||
from_secret: docker_username
|
||||
|
||||
trigger:
|
||||
ref:
|
||||
- "refs/tags/**"
|
||||
paths:
|
||||
exclude:
|
||||
- "docs/**"
|
||||
|
||||
depends_on:
|
||||
- docker-linux-amd64-release-version
|
||||
- docker-linux-amd64-release-candidate-version
|
||||
- docker-linux-arm64-release-version
|
||||
- docker-linux-arm64-release-candidate-version
|
||||
354
.eslintrc.yaml
354
.eslintrc.yaml
@@ -3,7 +3,6 @@ reportUnusedDisableDirectives: true
|
||||
|
||||
ignorePatterns:
|
||||
- /web_src/js/vendor
|
||||
- /web_src/fomantic
|
||||
|
||||
parserOptions:
|
||||
sourceType: module
|
||||
@@ -11,17 +10,14 @@ parserOptions:
|
||||
|
||||
plugins:
|
||||
- "@eslint-community/eslint-plugin-eslint-comments"
|
||||
- "@stylistic/eslint-plugin-js"
|
||||
- eslint-plugin-array-func
|
||||
- eslint-plugin-github
|
||||
- eslint-plugin-i
|
||||
- eslint-plugin-import
|
||||
- eslint-plugin-jquery
|
||||
- eslint-plugin-no-jquery
|
||||
- eslint-plugin-no-use-extend-native
|
||||
- eslint-plugin-regexp
|
||||
- eslint-plugin-sonarjs
|
||||
- eslint-plugin-unicorn
|
||||
- eslint-plugin-vitest
|
||||
- eslint-plugin-vitest-globals
|
||||
- eslint-plugin-wc
|
||||
|
||||
@@ -43,62 +39,16 @@ overrides:
|
||||
worker: true
|
||||
rules:
|
||||
no-restricted-globals: [2, addEventListener, blur, close, closed, confirm, defaultStatus, defaultstatus, error, event, external, find, focus, frameElement, frames, history, innerHeight, innerWidth, isFinite, isNaN, length, locationbar, menubar, moveBy, moveTo, name, onblur, onerror, onfocus, onload, onresize, onunload, open, opener, opera, outerHeight, outerWidth, pageXOffset, pageYOffset, parent, print, removeEventListener, resizeBy, resizeTo, screen, screenLeft, screenTop, screenX, screenY, scroll, scrollbars, scrollBy, scrollTo, scrollX, scrollY, status, statusbar, stop, toolbar, top]
|
||||
- files: ["build/generate-images.js"]
|
||||
rules:
|
||||
import/no-unresolved: [0]
|
||||
import/no-extraneous-dependencies: [0]
|
||||
- files: ["*.config.*"]
|
||||
rules:
|
||||
i/no-unused-modules: [0]
|
||||
import/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]
|
||||
@@ -113,74 +63,11 @@ rules:
|
||||
"@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-bracket-newline: [0]
|
||||
array-bracket-spacing: [2, never]
|
||||
array-callback-return: [2, {checkForEach: true}]
|
||||
array-element-newline: [0]
|
||||
array-func/avoid-reverse: [2]
|
||||
array-func/from-map: [2]
|
||||
array-func/no-unnecessary-this-arg: [2]
|
||||
@@ -188,11 +75,18 @@ rules:
|
||||
array-func/prefer-flat-map: [0] # handled by unicorn/prefer-array-flat-map
|
||||
array-func/prefer-flat: [0] # handled by unicorn/prefer-array-flat
|
||||
arrow-body-style: [0]
|
||||
arrow-parens: [2, always]
|
||||
arrow-spacing: [2, {before: true, after: true}]
|
||||
block-scoped-var: [2]
|
||||
brace-style: [2, 1tbs, {allowSingleLine: true}]
|
||||
camelcase: [0]
|
||||
capitalized-comments: [0]
|
||||
class-methods-use-this: [0]
|
||||
comma-dangle: [2, only-multiline]
|
||||
comma-spacing: [2, {before: false, after: true}]
|
||||
comma-style: [2, last]
|
||||
complexity: [0]
|
||||
computed-property-spacing: [2, never]
|
||||
consistent-return: [0]
|
||||
consistent-this: [0]
|
||||
constructor-super: [2]
|
||||
@@ -200,100 +94,85 @@ rules:
|
||||
default-case-last: [2]
|
||||
default-case: [0]
|
||||
default-param-last: [0]
|
||||
dot-location: [2, property]
|
||||
dot-notation: [0]
|
||||
eol-last: [2]
|
||||
eqeqeq: [2]
|
||||
for-direction: [2]
|
||||
func-call-spacing: [2, never]
|
||||
func-name-matching: [2]
|
||||
func-names: [0]
|
||||
func-style: [0]
|
||||
function-call-argument-newline: [0]
|
||||
function-paren-newline: [0]
|
||||
generator-star-spacing: [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]
|
||||
implicit-arrow-linebreak: [0]
|
||||
import/consistent-type-specifier-style: [0]
|
||||
import/default: [0]
|
||||
import/dynamic-import-chunkname: [0]
|
||||
import/export: [2]
|
||||
import/exports-last: [0]
|
||||
import/extensions: [2, always, {ignorePackages: true}]
|
||||
import/first: [2]
|
||||
import/group-exports: [0]
|
||||
import/max-dependencies: [0]
|
||||
import/named: [2]
|
||||
import/namespace: [0]
|
||||
import/newline-after-import: [0]
|
||||
import/no-absolute-path: [0]
|
||||
import/no-amd: [2]
|
||||
import/no-anonymous-default-export: [0]
|
||||
import/no-commonjs: [2]
|
||||
import/no-cycle: [2, {ignoreExternal: true, maxDepth: 1}]
|
||||
import/no-default-export: [0]
|
||||
import/no-deprecated: [0]
|
||||
import/no-dynamic-require: [0]
|
||||
import/no-empty-named-blocks: [2]
|
||||
import/no-extraneous-dependencies: [2]
|
||||
import/no-import-module-exports: [0]
|
||||
import/no-internal-modules: [0]
|
||||
import/no-mutable-exports: [0]
|
||||
import/no-named-as-default-member: [0]
|
||||
import/no-named-as-default: [2]
|
||||
import/no-named-default: [0]
|
||||
import/no-named-export: [0]
|
||||
import/no-namespace: [0]
|
||||
import/no-nodejs-modules: [0]
|
||||
import/no-relative-packages: [0]
|
||||
import/no-relative-parent-imports: [0]
|
||||
import/no-restricted-paths: [0]
|
||||
import/no-self-import: [2]
|
||||
import/no-unassigned-import: [0]
|
||||
import/no-unresolved: [2, {commonjs: true, ignore: ["\\?.+$", ^vitest/]}]
|
||||
import/no-unused-modules: [2, {unusedExports: true}]
|
||||
import/no-useless-path-segments: [2, {commonjs: true}]
|
||||
import/no-webpack-loader-syntax: [2]
|
||||
import/order: [0]
|
||||
import/prefer-default-export: [0]
|
||||
import/unambiguous: [0]
|
||||
indent: [2, 2, {SwitchCase: 1}]
|
||||
init-declarations: [0]
|
||||
jquery/no-ajax-events: [2]
|
||||
jquery/no-ajax: [2]
|
||||
jquery/no-ajax: [0]
|
||||
jquery/no-animate: [2]
|
||||
jquery/no-attr: [2]
|
||||
jquery/no-attr: [0]
|
||||
jquery/no-bind: [2]
|
||||
jquery/no-class: [0]
|
||||
jquery/no-clone: [2]
|
||||
jquery/no-closest: [0]
|
||||
jquery/no-css: [2]
|
||||
jquery/no-css: [0]
|
||||
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-fade: [0]
|
||||
jquery/no-filter: [0]
|
||||
jquery/no-find: [0]
|
||||
jquery/no-global-eval: [2]
|
||||
@@ -304,23 +183,23 @@ rules:
|
||||
jquery/no-in-array: [2]
|
||||
jquery/no-is-array: [2]
|
||||
jquery/no-is-function: [2]
|
||||
jquery/no-is: [2]
|
||||
jquery/no-is: [0]
|
||||
jquery/no-load: [2]
|
||||
jquery/no-map: [2]
|
||||
jquery/no-map: [0]
|
||||
jquery/no-merge: [2]
|
||||
jquery/no-param: [2]
|
||||
jquery/no-parent: [0]
|
||||
jquery/no-parents: [2]
|
||||
jquery/no-parents: [0]
|
||||
jquery/no-parse-html: [2]
|
||||
jquery/no-prop: [2]
|
||||
jquery/no-prop: [0]
|
||||
jquery/no-proxy: [2]
|
||||
jquery/no-ready: [2]
|
||||
jquery/no-serialize: [2]
|
||||
jquery/no-show: [2]
|
||||
jquery/no-size: [2]
|
||||
jquery/no-sizzle: [2]
|
||||
jquery/no-slide: [2]
|
||||
jquery/no-submit: [2]
|
||||
jquery/no-sizzle: [0]
|
||||
jquery/no-slide: [0]
|
||||
jquery/no-submit: [0]
|
||||
jquery/no-text: [0]
|
||||
jquery/no-toggle: [2]
|
||||
jquery/no-trigger: [0]
|
||||
@@ -328,17 +207,27 @@ rules:
|
||||
jquery/no-val: [0]
|
||||
jquery/no-when: [2]
|
||||
jquery/no-wrap: [2]
|
||||
key-spacing: [2]
|
||||
keyword-spacing: [2]
|
||||
line-comment-position: [0]
|
||||
linebreak-style: [2, unix]
|
||||
lines-around-comment: [0]
|
||||
lines-between-class-members: [0]
|
||||
logical-assignment-operators: [0]
|
||||
max-classes-per-file: [0]
|
||||
max-depth: [0]
|
||||
max-len: [0]
|
||||
max-lines-per-function: [0]
|
||||
max-lines: [0]
|
||||
max-nested-callbacks: [0]
|
||||
max-params: [0]
|
||||
max-statements-per-line: [0]
|
||||
max-statements: [0]
|
||||
multiline-comment-style: [2, separate-lines]
|
||||
multiline-ternary: [0]
|
||||
new-cap: [0]
|
||||
new-parens: [2]
|
||||
newline-per-chained-call: [0]
|
||||
no-alert: [0]
|
||||
no-array-constructor: [2]
|
||||
no-async-promise-executor: [0]
|
||||
@@ -350,6 +239,7 @@ rules:
|
||||
no-class-assign: [2]
|
||||
no-compare-neg-zero: [2]
|
||||
no-cond-assign: [2, except-parens]
|
||||
no-confusing-arrow: [0]
|
||||
no-console: [1, {allow: [debug, info, warn, error]}]
|
||||
no-const-assign: [2]
|
||||
no-constant-binary-expression: [2]
|
||||
@@ -379,7 +269,10 @@ rules:
|
||||
no-extra-bind: [2]
|
||||
no-extra-boolean-cast: [2]
|
||||
no-extra-label: [0]
|
||||
no-extra-parens: [0]
|
||||
no-extra-semi: [2]
|
||||
no-fallthrough: [2]
|
||||
no-floating-decimal: [0]
|
||||
no-func-assign: [2]
|
||||
no-global-assign: [2]
|
||||
no-implicit-coercion: [2]
|
||||
@@ -393,12 +286,12 @@ rules:
|
||||
no-irregular-whitespace: [2]
|
||||
no-iterator: [2]
|
||||
no-jquery/no-ajax-events: [2]
|
||||
no-jquery/no-ajax: [2]
|
||||
no-jquery/no-ajax: [0]
|
||||
no-jquery/no-and-self: [2]
|
||||
no-jquery/no-animate-toggle: [2]
|
||||
no-jquery/no-animate: [2]
|
||||
no-jquery/no-append-html: [2]
|
||||
no-jquery/no-attr: [2]
|
||||
no-jquery/no-append-html: [0]
|
||||
no-jquery/no-attr: [0]
|
||||
no-jquery/no-bind: [2]
|
||||
no-jquery/no-box-model: [2]
|
||||
no-jquery/no-browser: [2]
|
||||
@@ -410,7 +303,7 @@ rules:
|
||||
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-css: [0]
|
||||
no-jquery/no-data: [0]
|
||||
no-jquery/no-deferred: [2]
|
||||
no-jquery/no-delegate: [2]
|
||||
@@ -441,14 +334,14 @@ rules:
|
||||
no-jquery/no-is-numeric: [2]
|
||||
no-jquery/no-is-plain-object: [2]
|
||||
no-jquery/no-is-window: [2]
|
||||
no-jquery/no-is: [2]
|
||||
no-jquery/no-is: [0]
|
||||
no-jquery/no-jquery-constructor: [0]
|
||||
no-jquery/no-live: [2]
|
||||
no-jquery/no-load-shorthand: [2]
|
||||
no-jquery/no-load: [2]
|
||||
no-jquery/no-map-collection: [0]
|
||||
no-jquery/no-map-util: [2]
|
||||
no-jquery/no-map: [2]
|
||||
no-jquery/no-map: [0]
|
||||
no-jquery/no-merge: [2]
|
||||
no-jquery/no-node-name: [2]
|
||||
no-jquery/no-noop: [2]
|
||||
@@ -458,19 +351,19 @@ rules:
|
||||
no-jquery/no-other-utils: [2]
|
||||
no-jquery/no-param: [2]
|
||||
no-jquery/no-parent: [0]
|
||||
no-jquery/no-parents: [2]
|
||||
no-jquery/no-parents: [0]
|
||||
no-jquery/no-parse-html-literal: [0]
|
||||
no-jquery/no-parse-html: [2]
|
||||
no-jquery/no-parse-json: [2]
|
||||
no-jquery/no-parse-xml: [2]
|
||||
no-jquery/no-prop: [2]
|
||||
no-jquery/no-prop: [0]
|
||||
no-jquery/no-proxy: [2]
|
||||
no-jquery/no-ready-shorthand: [2]
|
||||
no-jquery/no-ready: [2]
|
||||
no-jquery/no-selector-prop: [2]
|
||||
no-jquery/no-serialize: [2]
|
||||
no-jquery/no-size: [2]
|
||||
no-jquery/no-sizzle: [2]
|
||||
no-jquery/no-sizzle: [0]
|
||||
no-jquery/no-slide: [2]
|
||||
no-jquery/no-sub: [2]
|
||||
no-jquery/no-support: [2]
|
||||
@@ -484,7 +377,7 @@ rules:
|
||||
no-jquery/no-visibility: [2]
|
||||
no-jquery/no-when: [2]
|
||||
no-jquery/no-wrap: [2]
|
||||
no-jquery/variable-pattern: [2]
|
||||
no-jquery/variable-pattern: [0]
|
||||
no-label-var: [2]
|
||||
no-labels: [0] # handled by no-restricted-syntax
|
||||
no-lone-blocks: [2]
|
||||
@@ -493,7 +386,10 @@ rules:
|
||||
no-loss-of-precision: [2]
|
||||
no-magic-numbers: [0]
|
||||
no-misleading-character-class: [2]
|
||||
no-mixed-operators: [0]
|
||||
no-mixed-spaces-and-tabs: [2]
|
||||
no-multi-assign: [0]
|
||||
no-multi-spaces: [2, {ignoreEOLComments: true, exceptions: {Property: true}}]
|
||||
no-multi-str: [2]
|
||||
no-negated-condition: [0]
|
||||
no-nested-ternary: [0]
|
||||
@@ -527,17 +423,19 @@ rules:
|
||||
no-shadow-restricted-names: [2]
|
||||
no-shadow: [0]
|
||||
no-sparse-arrays: [2]
|
||||
no-tabs: [2]
|
||||
no-template-curly-in-string: [2]
|
||||
no-ternary: [0]
|
||||
no-this-before-super: [2]
|
||||
no-throw-literal: [2]
|
||||
no-trailing-spaces: [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-unneeded-ternary: [0]
|
||||
no-unreachable-loop: [2]
|
||||
no-unreachable: [2]
|
||||
no-unsafe-finally: [2]
|
||||
@@ -560,25 +458,33 @@ rules:
|
||||
no-var: [2]
|
||||
no-void: [2]
|
||||
no-warning-comments: [0]
|
||||
no-whitespace-before-property: [2]
|
||||
no-with: [0] # handled by no-restricted-syntax
|
||||
nonblock-statement-body-position: [2]
|
||||
object-curly-newline: [0]
|
||||
object-curly-spacing: [2, never]
|
||||
object-shorthand: [2, always]
|
||||
one-var-declaration-per-line: [0]
|
||||
one-var: [0]
|
||||
operator-assignment: [2, always]
|
||||
operator-linebreak: [2, after]
|
||||
padded-blocks: [2, never]
|
||||
padding-line-between-statements: [0]
|
||||
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-has-own: [0]
|
||||
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]
|
||||
quote-props: [0]
|
||||
quotes: [2, single, {avoidEscape: true, allowTemplateLiterals: true}]
|
||||
radix: [2, as-needed]
|
||||
regexp/confusing-quantifier: [2]
|
||||
regexp/control-character-escape: [2]
|
||||
@@ -595,7 +501,6 @@ rules:
|
||||
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]
|
||||
@@ -626,8 +531,6 @@ rules:
|
||||
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]
|
||||
@@ -647,12 +550,10 @@ rules:
|
||||
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]
|
||||
@@ -663,6 +564,10 @@ rules:
|
||||
require-await: [0]
|
||||
require-unicode-regexp: [0]
|
||||
require-yield: [2]
|
||||
rest-spread-spacing: [2, never]
|
||||
semi-spacing: [2, {before: false, after: true}]
|
||||
semi-style: [2, last]
|
||||
semi: [2, always, {omitLastInOneLineBlock: true}]
|
||||
sonarjs/cognitive-complexity: [0]
|
||||
sonarjs/elseif-without-else: [0]
|
||||
sonarjs/max-switch-cases: [0]
|
||||
@@ -698,8 +603,16 @@ rules:
|
||||
sort-imports: [0]
|
||||
sort-keys: [0]
|
||||
sort-vars: [0]
|
||||
space-before-blocks: [2, always]
|
||||
space-in-parens: [2, never]
|
||||
space-infix-ops: [2]
|
||||
space-unary-ops: [2]
|
||||
spaced-comment: [2, always]
|
||||
strict: [0]
|
||||
switch-colon-spacing: [2]
|
||||
symbol-description: [2]
|
||||
template-curly-spacing: [2, never]
|
||||
template-tag-spacing: [2, never]
|
||||
unicode-bom: [2, never]
|
||||
unicorn/better-regex: [0]
|
||||
unicorn/catch-error-name: [0]
|
||||
@@ -716,14 +629,12 @@ rules:
|
||||
unicorn/import-style: [0]
|
||||
unicorn/new-for-builtins: [2]
|
||||
unicorn/no-abusive-eslint-disable: [0]
|
||||
unicorn/no-anonymous-default-export: [0]
|
||||
unicorn/no-array-callback-reference: [0]
|
||||
unicorn/no-array-for-each: [2]
|
||||
unicorn/no-array-method-this-argument: [2]
|
||||
unicorn/no-array-push-push: [2]
|
||||
unicorn/no-array-reduce: [2]
|
||||
unicorn/no-await-expression-member: [0]
|
||||
unicorn/no-await-in-promise-methods: [2]
|
||||
unicorn/no-console-spaces: [0]
|
||||
unicorn/no-document-cookie: [2]
|
||||
unicorn/no-empty-file: [2]
|
||||
@@ -740,13 +651,11 @@ rules:
|
||||
unicorn/no-null: [0]
|
||||
unicorn/no-object-as-default-parameter: [0]
|
||||
unicorn/no-process-exit: [0]
|
||||
unicorn/no-single-promise-in-promise-methods: [2]
|
||||
unicorn/no-static-only-class: [2]
|
||||
unicorn/no-thenable: [2]
|
||||
unicorn/no-this-assignment: [2]
|
||||
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]
|
||||
@@ -834,7 +743,7 @@ rules:
|
||||
wc/no-constructor-params: [2]
|
||||
wc/no-constructor: [2]
|
||||
wc/no-customized-built-in-elements: [2]
|
||||
wc/no-exports-with-element: [0]
|
||||
wc/no-exports-with-element: [2]
|
||||
wc/no-invalid-element-name: [2]
|
||||
wc/no-invalid-extends: [2]
|
||||
wc/no-method-prefixed-with-on: [2]
|
||||
@@ -842,4 +751,7 @@ rules:
|
||||
wc/no-typos: [2]
|
||||
wc/require-listener-teardown: [2]
|
||||
wc/tag-name-matches-class: [2]
|
||||
wrap-iife: [2, inside]
|
||||
wrap-regex: [0]
|
||||
yield-star-spacing: [2, after]
|
||||
yoda: [2, never]
|
||||
|
||||
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -1,6 +1,5 @@
|
||||
* text=auto eol=lf
|
||||
*.tmpl linguist-language=Handlebars
|
||||
*.pb.go linguist-generated
|
||||
/assets/*.json linguist-generated
|
||||
/public/assets/img/svg/*.svg linguist-generated
|
||||
/templates/swagger/v1_json.tmpl linguist-generated
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<!--
|
||||
1. Please speak English, this is the language all maintainers can speak and write.
|
||||
2. Please ask questions or configuration/deploy problems on our Discord
|
||||
server (https://discord.gg/gitea) or forum (https://forum.gitea.com).
|
||||
server (https://discord.gg/gitea) or forum (https://discourse.gitea.io).
|
||||
3. Please take a moment to check that your issue doesn't already exist.
|
||||
4. Make sure it's not mentioned in the FAQ (https://docs.gitea.com/help/faq)
|
||||
5. Please give all relevant information below for bug reports, because
|
||||
@@ -21,7 +21,7 @@
|
||||
- [ ] MySQL
|
||||
- [ ] MSSQL
|
||||
- [ ] SQLite
|
||||
- Can you reproduce the bug at https://demo.gitea.com:
|
||||
- Can you reproduce the bug at https://try.gitea.io:
|
||||
- [ ] Yes (provide example URL)
|
||||
- [ ] No
|
||||
- Log gist:
|
||||
|
||||
1
.github/FUNDING.yml
vendored
1
.github/FUNDING.yml
vendored
@@ -1 +1,2 @@
|
||||
open_collective: gitea
|
||||
custom: https://www.bountysource.com/teams/gitea
|
||||
|
||||
6
.github/ISSUE_TEMPLATE/bug-report.yaml
vendored
6
.github/ISSUE_TEMPLATE/bug-report.yaml
vendored
@@ -1,6 +1,6 @@
|
||||
name: Bug Report
|
||||
description: Found something you weren't expecting? Report it here!
|
||||
labels: ["type/bug"]
|
||||
labels: ["kind/bug"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
@@ -37,7 +37,7 @@ body:
|
||||
label: Can you reproduce the bug on the Gitea demo site?
|
||||
description: |
|
||||
If so, please provide a URL in the Description field
|
||||
URL of Gitea demo: https://demo.gitea.com
|
||||
URL of Gitea demo: https://try.gitea.io
|
||||
options:
|
||||
- "Yes"
|
||||
- "No"
|
||||
@@ -74,7 +74,7 @@ body:
|
||||
attributes:
|
||||
label: How are you running Gitea?
|
||||
description: |
|
||||
Please include information on whether you built Gitea yourself, used one of our downloads, are using https://demo.gitea.com or are using some other package
|
||||
Please include information on whether you built Gitea yourself, used one of our downloads, are using https://try.gitea.io or are using some other package
|
||||
Please also tell us how you are running Gitea, e.g. if it is being run from docker, a command-line, systemd etc.
|
||||
If you are using a package or systemd tell us what distribution you are using
|
||||
validations:
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/feature-request.yaml
vendored
2
.github/ISSUE_TEMPLATE/feature-request.yaml
vendored
@@ -1,6 +1,6 @@
|
||||
name: Feature Request
|
||||
description: Got an idea for a feature that Gitea doesn't have currently? Submit your idea here!
|
||||
labels: ["type/proposal"]
|
||||
labels: ["kind/proposal"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
|
||||
4
.github/ISSUE_TEMPLATE/ui.bug-report.yaml
vendored
4
.github/ISSUE_TEMPLATE/ui.bug-report.yaml
vendored
@@ -1,6 +1,6 @@
|
||||
name: Web Interface Bug Report
|
||||
description: Something doesn't look quite as it should? Report it here!
|
||||
labels: ["type/bug", "topic/ui"]
|
||||
labels: ["kind/bug", "kind/ui"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
@@ -46,7 +46,7 @@ body:
|
||||
label: Can you reproduce the bug on the Gitea demo site?
|
||||
description: |
|
||||
If so, please provide a URL in the Description field
|
||||
URL of Gitea demo: https://demo.gitea.com
|
||||
URL of Gitea demo: https://try.gitea.io
|
||||
options:
|
||||
- "Yes"
|
||||
- "No"
|
||||
|
||||
1
.github/actionlint.yaml
vendored
1
.github/actionlint.yaml
vendored
@@ -2,4 +2,3 @@ self-hosted-runner:
|
||||
labels:
|
||||
- actuated-4cpu-8gb
|
||||
- actuated-4cpu-16gb
|
||||
- nscloud
|
||||
|
||||
100
.github/labeler.yml
vendored
100
.github/labeler.yml
vendored
@@ -1,77 +1,35 @@
|
||||
modifies/docs:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "**/*.md"
|
||||
- "docs/**"
|
||||
kind/docs:
|
||||
- "**/*.md"
|
||||
- "docs/**"
|
||||
|
||||
modifies/templates:
|
||||
- changed-files:
|
||||
- all-globs-to-any-file:
|
||||
- "templates/**"
|
||||
- "!templates/swagger/v1_json.tmpl"
|
||||
kind/ui:
|
||||
- "web_src/**/*"
|
||||
- all: ["templates/**", "!templates/swagger/v1_json.tmpl"]
|
||||
|
||||
modifies/api:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "routers/api/**"
|
||||
- "templates/swagger/v1_json.tmpl"
|
||||
kind/api:
|
||||
- "templates/swagger/v1_json.tmpl"
|
||||
- "routers/api/**"
|
||||
|
||||
modifies/cli:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "cmd/**"
|
||||
kind/build:
|
||||
- "Makefile"
|
||||
- "Dockerfile"
|
||||
- "Dockerfile.rootless"
|
||||
- "docker/**"
|
||||
- "webpack.config.js"
|
||||
|
||||
modifies/translation:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "options/locale/*.ini"
|
||||
theme/package-registry:
|
||||
- "modules/packages/**"
|
||||
- "services/packages/**"
|
||||
- "routers/api/packages/**"
|
||||
- "routers/web/shared/packages/**"
|
||||
|
||||
modifies/migrations:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "models/migrations/**"
|
||||
kind/cli:
|
||||
- "cmd/**"
|
||||
|
||||
modifies/internal:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- ".air.toml"
|
||||
- "Makefile"
|
||||
- "Dockerfile"
|
||||
- "Dockerfile.rootless"
|
||||
- ".dockerignore"
|
||||
- "docker/**"
|
||||
- ".editorconfig"
|
||||
- ".eslintrc.yaml"
|
||||
- ".golangci.yml"
|
||||
- ".gitpod.yml"
|
||||
- ".markdownlint.yaml"
|
||||
- ".spectral.yaml"
|
||||
- "stylelint.config.js"
|
||||
- ".yamllint.yaml"
|
||||
- ".github/**"
|
||||
- ".gitea/"
|
||||
- ".devcontainer/**"
|
||||
- "build.go"
|
||||
- "build/**"
|
||||
- "contrib/**"
|
||||
|
||||
modifies/dependencies:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "package.json"
|
||||
- "package-lock.json"
|
||||
- "pyproject.toml"
|
||||
- "poetry.lock"
|
||||
- "go.mod"
|
||||
- "go.sum"
|
||||
|
||||
modifies/go:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "**/*.go"
|
||||
|
||||
modifies/js:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "**/*.js"
|
||||
- "**/*.vue"
|
||||
kind/lint:
|
||||
- ".eslintrc.yaml"
|
||||
- ".golangci.yml"
|
||||
- ".markdownlint.yaml"
|
||||
- ".spectral.yaml"
|
||||
- ".stylelintrc.yaml"
|
||||
- ".yamllint.yaml"
|
||||
|
||||
54
.github/stale.yml
vendored
Normal file
54
.github/stale.yml
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
# Configuration for probot-stale - https://github.com/probot/stale
|
||||
|
||||
# Number of days of inactivity before an Issue or Pull Request becomes stale
|
||||
daysUntilStale: 60
|
||||
|
||||
# Number of days of inactivity before an Issue or Pull Request with the stale label is closed.
|
||||
# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
|
||||
daysUntilClose: 14
|
||||
|
||||
# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
|
||||
exemptLabels:
|
||||
- status/blocked
|
||||
- kind/security
|
||||
- lgtm/done
|
||||
- reviewed/confirmed
|
||||
- priority/critical
|
||||
- kind/proposal
|
||||
|
||||
# Set to true to ignore issues in a project (defaults to false)
|
||||
exemptProjects: false
|
||||
|
||||
# Set to true to ignore issues in a milestone (defaults to false)
|
||||
exemptMilestones: false
|
||||
|
||||
# Label to use when marking as stale
|
||||
staleLabel: stale
|
||||
|
||||
# Comment to post when marking as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had recent activity.
|
||||
I am here to help clear issues left open even if solved or waiting for more insight.
|
||||
This issue will be closed if no further activity occurs during the next 2 weeks.
|
||||
If the issue is still valid just add a comment to keep it alive.
|
||||
Thank you for your contributions.
|
||||
|
||||
# Comment to post when closing a stale Issue or Pull Request.
|
||||
closeComment: >
|
||||
This issue has been automatically closed because of inactivity.
|
||||
You can re-open it if needed.
|
||||
|
||||
# Limit the number of actions per hour, from 1-30. Default is 30
|
||||
limitPerRun: 1
|
||||
|
||||
# Optionally, specify configuration settings that are specific to just 'issues' or 'pulls':
|
||||
pulls:
|
||||
daysUntilStale: 60
|
||||
daysUntilClose: 60
|
||||
markComment: >
|
||||
This pull request has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed if no further activity occurs during the next 2 months. Thank you
|
||||
for your contributions.
|
||||
closeComment: >
|
||||
This pull request has been automatically closed because of inactivity.
|
||||
You can re-open it if needed.
|
||||
6
.github/workflows/cron-licenses.yml
vendored
6
.github/workflows/cron-licenses.yml
vendored
@@ -11,14 +11,14 @@ jobs:
|
||||
if: github.repository == 'go-gitea/gitea'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v5
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
go-version: "~1.21"
|
||||
check-latest: true
|
||||
- run: make generate-license generate-gitignore
|
||||
timeout-minutes: 40
|
||||
- name: push translations to repo
|
||||
uses: appleboy/git-push-action@v0.0.3
|
||||
uses: appleboy/git-push-action@v0.0.2
|
||||
with:
|
||||
author_email: "teabot@gitea.io"
|
||||
author_name: GiteaBot
|
||||
|
||||
22
.github/workflows/cron-lock.yml
vendored
Normal file
22
.github/workflows/cron-lock.yml
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
name: cron-lock
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0 * * *" # every day at 00:00 UTC
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
concurrency:
|
||||
group: lock
|
||||
|
||||
jobs:
|
||||
action:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'go-gitea/gitea'
|
||||
steps:
|
||||
- uses: dessant/lock-threads@v4
|
||||
with:
|
||||
issue-inactive-days: 45
|
||||
35
.github/workflows/cron-translations.yml
vendored
35
.github/workflows/cron-translations.yml
vendored
@@ -11,23 +11,18 @@ jobs:
|
||||
if: github.repository == 'go-gitea/gitea'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: crowdin/github-action@v1
|
||||
with:
|
||||
upload_sources: true
|
||||
upload_translations: false
|
||||
download_sources: false
|
||||
download_translations: true
|
||||
push_translations: false
|
||||
push_sources: false
|
||||
create_pull_request: false
|
||||
config: crowdin.yml
|
||||
- name: download from crowdin
|
||||
uses: docker://jonasfranz/crowdin
|
||||
env:
|
||||
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
|
||||
CROWDIN_KEY: ${{ secrets.CROWDIN_KEY }}
|
||||
PLUGIN_DOWNLOAD: true
|
||||
PLUGIN_EXPORT_DIR: options/locale/
|
||||
PLUGIN_IGNORE_BRANCH: true
|
||||
PLUGIN_PROJECT_IDENTIFIER: gitea
|
||||
- name: update locales
|
||||
run: ./build/update-locales.sh
|
||||
- name: push translations to repo
|
||||
uses: appleboy/git-push-action@v0.0.3
|
||||
uses: appleboy/git-push-action@v0.0.2
|
||||
with:
|
||||
author_email: "teabot@gitea.io"
|
||||
author_name: GiteaBot
|
||||
@@ -36,3 +31,19 @@ jobs:
|
||||
commit_message: "[skip ci] Updated translations via Crowdin"
|
||||
remote: "git@github.com:go-gitea/gitea.git"
|
||||
ssh_key: ${{ secrets.DEPLOY_KEY }}
|
||||
crowdin-push:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'go-gitea/gitea'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: push translations to crowdin
|
||||
uses: docker://jonasfranz/crowdin
|
||||
env:
|
||||
CROWDIN_KEY: ${{ secrets.CROWDIN_KEY }}
|
||||
PLUGIN_UPLOAD: true
|
||||
PLUGIN_EXPORT_DIR: options/locale/
|
||||
PLUGIN_IGNORE_BRANCH: true
|
||||
PLUGIN_PROJECT_IDENTIFIER: gitea
|
||||
PLUGIN_FILES: |
|
||||
locale_en-US.ini: options/locale/locale_en-US.ini
|
||||
PLUGIN_BRANCH: main
|
||||
|
||||
25
.github/workflows/disk-clean.yml
vendored
25
.github/workflows/disk-clean.yml
vendored
@@ -1,25 +0,0 @@
|
||||
name: disk-clean
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
jobs:
|
||||
triage:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Free Disk Space (Ubuntu)
|
||||
uses: jlumbroso/free-disk-space@main
|
||||
with:
|
||||
# this might remove tools that are actually needed,
|
||||
# if set to "true" but frees about 6 GB
|
||||
tool-cache: false
|
||||
|
||||
# all of these default to true, but feel free to set to
|
||||
# "false" if necessary for your workflow
|
||||
android: true
|
||||
dotnet: true
|
||||
haskell: true
|
||||
large-packages: false
|
||||
docker-images: false
|
||||
swap-storage: true
|
||||
6
.github/workflows/files-changed.yml
vendored
6
.github/workflows/files-changed.yml
vendored
@@ -35,7 +35,7 @@ jobs:
|
||||
yaml: ${{ steps.changes.outputs.yaml }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dorny/paths-filter@v3
|
||||
- uses: dorny/paths-filter@v2
|
||||
id: changes
|
||||
with:
|
||||
filters: |
|
||||
@@ -48,7 +48,6 @@ jobs:
|
||||
- "Makefile"
|
||||
- ".golangci.yml"
|
||||
- ".editorconfig"
|
||||
- "options/locale/locale_en-US.ini"
|
||||
|
||||
frontend:
|
||||
- "**/*.js"
|
||||
@@ -58,7 +57,7 @@ jobs:
|
||||
- "package-lock.json"
|
||||
- "Makefile"
|
||||
- ".eslintrc.yaml"
|
||||
- "stylelint.config.js"
|
||||
- ".stylelintrc.yaml"
|
||||
- ".npmrc"
|
||||
|
||||
docs:
|
||||
@@ -73,7 +72,6 @@ jobs:
|
||||
- "Makefile"
|
||||
|
||||
templates:
|
||||
- "tools/lint-templates-*.js"
|
||||
- "templates/**/*.tmpl"
|
||||
- "pyproject.toml"
|
||||
- "poetry.lock"
|
||||
|
||||
63
.github/workflows/pull-compliance.yml
vendored
63
.github/workflows/pull-compliance.yml
vendored
@@ -17,9 +17,9 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v5
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
go-version: "~1.21"
|
||||
check-latest: true
|
||||
- run: make deps-backend deps-tools
|
||||
- run: make lint-backend
|
||||
@@ -32,17 +32,11 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.12"
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: npm
|
||||
cache-dependency-path: package-lock.json
|
||||
python-version: "3.11"
|
||||
- run: pip install poetry
|
||||
- run: make deps-py
|
||||
- run: make deps-frontend
|
||||
- run: make lint-templates
|
||||
|
||||
lint-yaml:
|
||||
@@ -51,9 +45,9 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.12"
|
||||
python-version: "3.11"
|
||||
- run: pip install poetry
|
||||
- run: make deps-py
|
||||
- run: make lint-yaml
|
||||
@@ -64,35 +58,21 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 20
|
||||
cache: npm
|
||||
cache-dependency-path: package-lock.json
|
||||
- run: make deps-frontend
|
||||
- run: make lint-swagger
|
||||
|
||||
lint-spell:
|
||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.frontend == 'true' || needs.files-changed.outputs.actions == 'true' || needs.files-changed.outputs.docs == 'true' || needs.files-changed.outputs.templates == 'true'
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
check-latest: true
|
||||
- run: make lint-spell
|
||||
|
||||
lint-go-windows:
|
||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v5
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
go-version: "~1.21"
|
||||
check-latest: true
|
||||
- run: make deps-backend deps-tools
|
||||
- run: make lint-go-windows lint-go-vet
|
||||
@@ -107,9 +87,9 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v5
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
go-version: "~1.21"
|
||||
check-latest: true
|
||||
- run: make deps-backend deps-tools
|
||||
- run: make lint-go
|
||||
@@ -122,9 +102,9 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v5
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
go-version: "~1.21"
|
||||
check-latest: true
|
||||
- run: make deps-backend deps-tools
|
||||
- run: make --always-make checks-backend # ensure the "go-licenses" make target runs
|
||||
@@ -135,11 +115,9 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 20
|
||||
cache: npm
|
||||
cache-dependency-path: package-lock.json
|
||||
- run: make deps-frontend
|
||||
- run: make lint-frontend
|
||||
- run: make checks-frontend
|
||||
@@ -152,9 +130,9 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v5
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
go-version: "~1.21"
|
||||
check-latest: true
|
||||
# no frontend build here as backend should be able to build
|
||||
# even without any frontend files
|
||||
@@ -184,11 +162,9 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 20
|
||||
cache: npm
|
||||
cache-dependency-path: package-lock.json
|
||||
- run: make deps-frontend
|
||||
- run: make lint-md
|
||||
- run: make docs
|
||||
@@ -199,8 +175,5 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
check-latest: true
|
||||
- uses: actions/setup-go@v4
|
||||
- run: make lint-actions
|
||||
|
||||
98
.github/workflows/pull-db-tests.yml
vendored
98
.github/workflows/pull-db-tests.yml
vendored
@@ -17,7 +17,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
services:
|
||||
pgsql:
|
||||
image: postgres:12
|
||||
image: postgres:15
|
||||
env:
|
||||
POSTGRES_DB: test
|
||||
POSTGRES_PASSWORD: postgres
|
||||
@@ -31,17 +31,17 @@ jobs:
|
||||
minio:
|
||||
# as github actions doesn't support "entrypoint", we need to use a non-official image
|
||||
# that has a custom entrypoint set to "minio server /data"
|
||||
image: bitnami/minio:2023.8.31
|
||||
image: bitnami/minio:2021.3.17
|
||||
env:
|
||||
MINIO_ROOT_USER: 123456
|
||||
MINIO_ROOT_PASSWORD: 12345678
|
||||
MINIO_ACCESS_KEY: 123456
|
||||
MINIO_SECRET_KEY: 12345678
|
||||
ports:
|
||||
- "9000:9000"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v5
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
go-version: "~1.21"
|
||||
check-latest: true
|
||||
- name: Add hosts to /etc/hosts
|
||||
run: '[ -e "/.dockerenv" ] || [ -e "/run/.containerenv" ] || echo "127.0.0.1 pgsql ldap minio" | sudo tee -a /etc/hosts'
|
||||
@@ -49,10 +49,7 @@ jobs:
|
||||
- run: make backend
|
||||
env:
|
||||
TAGS: bindata
|
||||
- name: run migration tests
|
||||
run: make test-pgsql-migration
|
||||
- name: run tests
|
||||
run: make test-pgsql
|
||||
- run: make test-pgsql-migration test-pgsql
|
||||
timeout-minutes: 50
|
||||
env:
|
||||
TAGS: bindata gogit
|
||||
@@ -67,18 +64,15 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v5
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
go-version: "~1.21"
|
||||
check-latest: true
|
||||
- run: make deps-backend
|
||||
- run: make backend
|
||||
env:
|
||||
TAGS: bindata gogit sqlite sqlite_unlock_notify
|
||||
- name: run migration tests
|
||||
run: make test-sqlite-migration
|
||||
- name: run tests
|
||||
run: make test-sqlite
|
||||
- run: make test-sqlite-migration test-sqlite
|
||||
timeout-minutes: 50
|
||||
env:
|
||||
TAGS: bindata gogit sqlite sqlite_unlock_notify
|
||||
@@ -91,6 +85,13 @@ jobs:
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
services:
|
||||
mysql:
|
||||
image: mysql:5.7
|
||||
env:
|
||||
MYSQL_ALLOW_EMPTY_PASSWORD: true
|
||||
MYSQL_DATABASE: test
|
||||
ports:
|
||||
- "3306:3306"
|
||||
elasticsearch:
|
||||
image: elasticsearch:7.5.0
|
||||
env:
|
||||
@@ -103,6 +104,13 @@ jobs:
|
||||
MEILI_ENV: development # disable auth
|
||||
ports:
|
||||
- "7700:7700"
|
||||
smtpimap:
|
||||
image: tabascoterrier/docker-imap-devel:latest
|
||||
ports:
|
||||
- "25:25"
|
||||
- "143:143"
|
||||
- "587:587"
|
||||
- "993:993"
|
||||
redis:
|
||||
image: redis
|
||||
options: >- # wait until redis has started
|
||||
@@ -121,9 +129,9 @@ jobs:
|
||||
- "9000:9000"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v5
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
go-version: "~1.21"
|
||||
check-latest: true
|
||||
- name: Add hosts to /etc/hosts
|
||||
run: '[ -e "/.dockerenv" ] || [ -e "/run/.containerenv" ] || echo "127.0.0.1 mysql elasticsearch meilisearch smtpimap" | sudo tee -a /etc/hosts'
|
||||
@@ -144,16 +152,16 @@ jobs:
|
||||
RACE_ENABLED: true
|
||||
GITHUB_READ_TOKEN: ${{ secrets.GITHUB_READ_TOKEN }}
|
||||
|
||||
test-mysql:
|
||||
test-mysql5:
|
||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
services:
|
||||
mysql:
|
||||
image: mysql:8.0
|
||||
image: mysql:5.7
|
||||
env:
|
||||
MYSQL_ALLOW_EMPTY_PASSWORD: true
|
||||
MYSQL_DATABASE: testgitea
|
||||
MYSQL_DATABASE: test
|
||||
ports:
|
||||
- "3306:3306"
|
||||
elasticsearch:
|
||||
@@ -171,9 +179,9 @@ jobs:
|
||||
- "993:993"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v5
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
go-version: "~1.21"
|
||||
check-latest: true
|
||||
- name: Add hosts to /etc/hosts
|
||||
run: '[ -e "/.dockerenv" ] || [ -e "/run/.containerenv" ] || echo "127.0.0.1 mysql elasticsearch smtpimap" | sudo tee -a /etc/hosts'
|
||||
@@ -181,23 +189,51 @@ jobs:
|
||||
- run: make backend
|
||||
env:
|
||||
TAGS: bindata
|
||||
- name: run migration tests
|
||||
run: make test-mysql-migration
|
||||
- name: run tests
|
||||
run: make integration-test-coverage
|
||||
run: make test-mysql-migration integration-test-coverage
|
||||
env:
|
||||
TAGS: bindata
|
||||
RACE_ENABLED: true
|
||||
USE_REPO_TEST_DIR: 1
|
||||
TEST_INDEXER_CODE_ES_URL: "http://elastic:changeme@elasticsearch:9200"
|
||||
|
||||
test-mysql8:
|
||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
services:
|
||||
mysql8:
|
||||
image: mysql:8
|
||||
env:
|
||||
MYSQL_ALLOW_EMPTY_PASSWORD: true
|
||||
MYSQL_DATABASE: testgitea
|
||||
ports:
|
||||
- "3306:3306"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: "~1.21"
|
||||
check-latest: true
|
||||
- name: Add hosts to /etc/hosts
|
||||
run: '[ -e "/.dockerenv" ] || [ -e "/run/.containerenv" ] || echo "127.0.0.1 mysql8" | sudo tee -a /etc/hosts'
|
||||
- run: make deps-backend
|
||||
- run: make backend
|
||||
env:
|
||||
TAGS: bindata
|
||||
- run: make test-mysql8-migration test-mysql8
|
||||
timeout-minutes: 50
|
||||
env:
|
||||
TAGS: bindata
|
||||
USE_REPO_TEST_DIR: 1
|
||||
|
||||
test-mssql:
|
||||
if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true'
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
services:
|
||||
mssql:
|
||||
image: mcr.microsoft.com/mssql/server:2017-latest
|
||||
image: mcr.microsoft.com/mssql/server:latest
|
||||
env:
|
||||
ACCEPT_EULA: Y
|
||||
MSSQL_PID: Standard
|
||||
@@ -206,9 +242,9 @@ jobs:
|
||||
- "1433:1433"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v5
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
go-version: "~1.21"
|
||||
check-latest: true
|
||||
- name: Add hosts to /etc/hosts
|
||||
run: '[ -e "/.dockerenv" ] || [ -e "/run/.containerenv" ] || echo "127.0.0.1 mssql" | sudo tee -a /etc/hosts'
|
||||
@@ -216,9 +252,7 @@ jobs:
|
||||
- run: make backend
|
||||
env:
|
||||
TAGS: bindata
|
||||
- run: make test-mssql-migration
|
||||
- name: run tests
|
||||
run: make test-mssql
|
||||
- run: make test-mssql-migration test-mssql
|
||||
timeout-minutes: 50
|
||||
env:
|
||||
TAGS: bindata
|
||||
|
||||
8
.github/workflows/pull-docker-dryrun.yml
vendored
8
.github/workflows/pull-docker-dryrun.yml
vendored
@@ -16,8 +16,8 @@ jobs:
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: docker/setup-buildx-action@v3
|
||||
- uses: docker/build-push-action@v5
|
||||
- uses: docker/setup-buildx-action@v2
|
||||
- uses: docker/build-push-action@v4
|
||||
with:
|
||||
push: false
|
||||
tags: gitea/gitea:linux-amd64
|
||||
@@ -27,8 +27,8 @@ jobs:
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: docker/setup-buildx-action@v3
|
||||
- uses: docker/build-push-action@v5
|
||||
- uses: docker/setup-buildx-action@v2
|
||||
- uses: docker/build-push-action@v4
|
||||
with:
|
||||
push: false
|
||||
file: Dockerfile.rootless
|
||||
|
||||
8
.github/workflows/pull-e2e-tests.yml
vendored
8
.github/workflows/pull-e2e-tests.yml
vendored
@@ -17,15 +17,13 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v5
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
go-version: "~1.21"
|
||||
check-latest: true
|
||||
- uses: actions/setup-node@v4
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 20
|
||||
cache: npm
|
||||
cache-dependency-path: package-lock.json
|
||||
- run: make deps-frontend frontend deps-backend
|
||||
- run: npx playwright install --with-deps
|
||||
- run: make test-e2e-sqlite
|
||||
|
||||
5
.github/workflows/pull-labeler.yml
vendored
5
.github/workflows/pull-labeler.yml
vendored
@@ -9,12 +9,13 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
labeler:
|
||||
label:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: actions/labeler@v5
|
||||
- uses: actions/labeler@v4
|
||||
with:
|
||||
dot: true
|
||||
sync-labels: true
|
||||
|
||||
64
.github/workflows/release-nightly.yml
vendored
64
.github/workflows/release-nightly.yml
vendored
@@ -1,32 +1,28 @@
|
||||
name: release-nightly
|
||||
name: release-nightly-assets
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, release/v*]
|
||||
branches: [ main, release/v* ]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
disk-clean:
|
||||
uses: ./.github/workflows/disk-clean.yml
|
||||
nightly-binary:
|
||||
runs-on: nscloud
|
||||
runs-on: actuated-4cpu-16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
||||
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
|
||||
- run: git fetch --unshallow --quiet --tags --force
|
||||
- uses: actions/setup-go@v5
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
go-version: "~1.21"
|
||||
check-latest: true
|
||||
- uses: actions/setup-node@v4
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 20
|
||||
cache: npm
|
||||
cache-dependency-path: package-lock.json
|
||||
- run: make deps-frontend deps-backend
|
||||
# xgo build
|
||||
- run: make release
|
||||
@@ -34,7 +30,7 @@ jobs:
|
||||
TAGS: bindata sqlite sqlite_unlock_notify
|
||||
- name: import gpg key
|
||||
id: import_gpg
|
||||
uses: crazy-max/ghaction-import-gpg@v6
|
||||
uses: crazy-max/ghaction-import-gpg@v5
|
||||
with:
|
||||
gpg_private_key: ${{ secrets.GPGSIGN_KEY }}
|
||||
passphrase: ${{ secrets.GPGSIGN_PASSPHRASE }}
|
||||
@@ -49,29 +45,29 @@ jobs:
|
||||
run: |
|
||||
REF_NAME=$(echo "${{ github.ref }}" | sed -e 's/refs\/heads\///' -e 's/refs\/tags\///' -e 's/release\/v//')
|
||||
echo "Cleaned name is ${REF_NAME}"
|
||||
echo "branch=${REF_NAME}-nightly" >> "$GITHUB_OUTPUT"
|
||||
- name: configure aws
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
aws-region: ${{ secrets.AWS_REGION }}
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
echo "branch=${REF_NAME}" >> "$GITHUB_OUTPUT"
|
||||
- name: upload binaries to s3
|
||||
run: |
|
||||
aws s3 sync dist/release s3://${{ secrets.AWS_S3_BUCKET }}/gitea/${{ steps.clean_name.outputs.branch }} --no-progress
|
||||
uses: jakejarvis/s3-sync-action@master
|
||||
env:
|
||||
AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }}
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
AWS_REGION: ${{ secrets.AWS_REGION }}
|
||||
SOURCE_DIR: dist/release
|
||||
DEST_DIR: gitea/${{ steps.clean_name.outputs.branch }}
|
||||
nightly-docker-rootful:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: actuated-4cpu-16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
||||
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
|
||||
- run: git fetch --unshallow --quiet --tags --force
|
||||
- uses: actions/setup-go@v5
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
go-version: "~1.21"
|
||||
check-latest: true
|
||||
- uses: docker/setup-qemu-action@v3
|
||||
- uses: docker/setup-buildx-action@v3
|
||||
- uses: docker/setup-qemu-action@v2
|
||||
- uses: docker/setup-buildx-action@v2
|
||||
- name: Get cleaned branch name
|
||||
id: clean_name
|
||||
run: |
|
||||
@@ -83,32 +79,32 @@ jobs:
|
||||
REF_NAME=$(echo "${{ github.ref }}" | sed -e 's/refs\/heads\///' -e 's/refs\/tags\///' -e 's/release\/v//')
|
||||
echo "branch=${REF_NAME}-nightly" >> "$GITHUB_OUTPUT"
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: fetch go modules
|
||||
run: make vendor
|
||||
- name: build rootful docker image
|
||||
uses: docker/build-push-action@v5
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: gitea/gitea:${{ steps.clean_name.outputs.branch }}
|
||||
nightly-docker-rootless:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: actuated-4cpu-16gb
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
||||
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
|
||||
- run: git fetch --unshallow --quiet --tags --force
|
||||
- uses: actions/setup-go@v5
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
go-version: "~1.21"
|
||||
check-latest: true
|
||||
- uses: docker/setup-qemu-action@v3
|
||||
- uses: docker/setup-buildx-action@v3
|
||||
- uses: docker/setup-qemu-action@v2
|
||||
- uses: docker/setup-buildx-action@v2
|
||||
- name: Get cleaned branch name
|
||||
id: clean_name
|
||||
run: |
|
||||
@@ -120,14 +116,14 @@ jobs:
|
||||
REF_NAME=$(echo "${{ github.ref }}" | sed -e 's/refs\/heads\///' -e 's/refs\/tags\///' -e 's/release\/v//')
|
||||
echo "branch=${REF_NAME}-nightly" >> "$GITHUB_OUTPUT"
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: fetch go modules
|
||||
run: make vendor
|
||||
- name: build rootless docker image
|
||||
uses: docker/build-push-action@v5
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
|
||||
134
.github/workflows/release-tag-rc.yml
vendored
134
.github/workflows/release-tag-rc.yml
vendored
@@ -1,134 +0,0 @@
|
||||
name: release-tag-rc
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v1*-rc*"
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
binary:
|
||||
runs-on: nscloud
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
||||
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
|
||||
- run: git fetch --unshallow --quiet --tags --force
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
check-latest: true
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: npm
|
||||
cache-dependency-path: package-lock.json
|
||||
- run: make deps-frontend deps-backend
|
||||
# xgo build
|
||||
- run: make release
|
||||
env:
|
||||
TAGS: bindata sqlite sqlite_unlock_notify
|
||||
- name: import gpg key
|
||||
id: import_gpg
|
||||
uses: crazy-max/ghaction-import-gpg@v6
|
||||
with:
|
||||
gpg_private_key: ${{ secrets.GPGSIGN_KEY }}
|
||||
passphrase: ${{ secrets.GPGSIGN_PASSPHRASE }}
|
||||
- name: sign binaries
|
||||
run: |
|
||||
for f in dist/release/*; do
|
||||
echo '${{ secrets.GPGSIGN_PASSPHRASE }}' | gpg --pinentry-mode loopback --passphrase-fd 0 --batch --yes --detach-sign -u ${{ steps.import_gpg.outputs.fingerprint }} --output "$f.asc" "$f"
|
||||
done
|
||||
# clean branch name to get the folder name in S3
|
||||
- name: Get cleaned branch name
|
||||
id: clean_name
|
||||
run: |
|
||||
REF_NAME=$(echo "${{ github.ref }}" | sed -e 's/refs\/heads\///' -e 's/refs\/tags\/v//' -e 's/release\/v//')
|
||||
echo "Cleaned name is ${REF_NAME}"
|
||||
echo "branch=${REF_NAME}" >> "$GITHUB_OUTPUT"
|
||||
- name: configure aws
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
aws-region: ${{ secrets.AWS_REGION }}
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
- name: upload binaries to s3
|
||||
run: |
|
||||
aws s3 sync dist/release s3://${{ secrets.AWS_S3_BUCKET }}/gitea/${{ steps.clean_name.outputs.branch }} --no-progress
|
||||
- name: Install GH CLI
|
||||
uses: dev-hanz-ops/install-gh-cli-action@v0.1.0
|
||||
with:
|
||||
gh-cli-version: 2.39.1
|
||||
- name: create github release
|
||||
run: |
|
||||
gh release create ${{ github.ref_name }} --title ${{ github.ref_name }} --draft --notes-from-tag dist/release/*
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||
docker-rootful:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
||||
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
|
||||
- run: git fetch --unshallow --quiet --tags --force
|
||||
- uses: docker/setup-qemu-action@v3
|
||||
- uses: docker/setup-buildx-action@v3
|
||||
- uses: docker/metadata-action@v5
|
||||
id: meta
|
||||
with:
|
||||
images: gitea/gitea
|
||||
flavor: |
|
||||
latest=false
|
||||
# 1.2.3-rc0
|
||||
tags: |
|
||||
type=semver,pattern={{version}}
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: build rootful docker image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
docker-rootless:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
||||
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
|
||||
- run: git fetch --unshallow --quiet --tags --force
|
||||
- uses: docker/setup-qemu-action@v3
|
||||
- uses: docker/setup-buildx-action@v3
|
||||
- uses: docker/metadata-action@v5
|
||||
id: meta
|
||||
with:
|
||||
images: gitea/gitea
|
||||
# each tag below will have the suffix of -rootless
|
||||
flavor: |
|
||||
latest=false
|
||||
suffix=-rootless
|
||||
# 1.2.3-rc0
|
||||
tags: |
|
||||
type=semver,pattern={{version}}
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: build rootless docker image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
file: Dockerfile.rootless
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
145
.github/workflows/release-tag-version.yml
vendored
145
.github/workflows/release-tag-version.yml
vendored
@@ -1,145 +0,0 @@
|
||||
name: release-tag-version
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v1.*"
|
||||
- "!v1*-rc*"
|
||||
- "!v1*-dev"
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
binary:
|
||||
runs-on: nscloud
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
||||
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
|
||||
- run: git fetch --unshallow --quiet --tags --force
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
check-latest: true
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: npm
|
||||
cache-dependency-path: package-lock.json
|
||||
- run: make deps-frontend deps-backend
|
||||
# xgo build
|
||||
- run: make release
|
||||
env:
|
||||
TAGS: bindata sqlite sqlite_unlock_notify
|
||||
- name: import gpg key
|
||||
id: import_gpg
|
||||
uses: crazy-max/ghaction-import-gpg@v6
|
||||
with:
|
||||
gpg_private_key: ${{ secrets.GPGSIGN_KEY }}
|
||||
passphrase: ${{ secrets.GPGSIGN_PASSPHRASE }}
|
||||
- name: sign binaries
|
||||
run: |
|
||||
for f in dist/release/*; do
|
||||
echo '${{ secrets.GPGSIGN_PASSPHRASE }}' | gpg --pinentry-mode loopback --passphrase-fd 0 --batch --yes --detach-sign -u ${{ steps.import_gpg.outputs.fingerprint }} --output "$f.asc" "$f"
|
||||
done
|
||||
# clean branch name to get the folder name in S3
|
||||
- name: Get cleaned branch name
|
||||
id: clean_name
|
||||
run: |
|
||||
REF_NAME=$(echo "${{ github.ref }}" | sed -e 's/refs\/heads\///' -e 's/refs\/tags\/v//' -e 's/release\/v//')
|
||||
echo "Cleaned name is ${REF_NAME}"
|
||||
echo "branch=${REF_NAME}" >> "$GITHUB_OUTPUT"
|
||||
- name: configure aws
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
aws-region: ${{ secrets.AWS_REGION }}
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
- name: upload binaries to s3
|
||||
run: |
|
||||
aws s3 sync dist/release s3://${{ secrets.AWS_S3_BUCKET }}/gitea/${{ steps.clean_name.outputs.branch }} --no-progress
|
||||
- name: Install GH CLI
|
||||
uses: dev-hanz-ops/install-gh-cli-action@v0.1.0
|
||||
with:
|
||||
gh-cli-version: 2.39.1
|
||||
- name: create github release
|
||||
run: |
|
||||
gh release create ${{ github.ref_name }} --title ${{ github.ref_name }} --notes-from-tag dist/release/*
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||
docker-rootful:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
||||
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
|
||||
- run: git fetch --unshallow --quiet --tags --force
|
||||
- uses: docker/setup-qemu-action@v3
|
||||
- uses: docker/setup-buildx-action@v3
|
||||
- uses: docker/metadata-action@v5
|
||||
id: meta
|
||||
with:
|
||||
images: gitea/gitea
|
||||
# this will generate tags in the following format:
|
||||
# latest
|
||||
# 1
|
||||
# 1.2
|
||||
# 1.2.3
|
||||
tags: |
|
||||
type=semver,pattern={{major}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=semver,pattern={{version}}
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: build rootful docker image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
docker-rootless:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
||||
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
|
||||
- run: git fetch --unshallow --quiet --tags --force
|
||||
- uses: docker/setup-qemu-action@v3
|
||||
- uses: docker/setup-buildx-action@v3
|
||||
- uses: docker/metadata-action@v5
|
||||
id: meta
|
||||
with:
|
||||
images: gitea/gitea
|
||||
# each tag below will have the suffix of -rootless
|
||||
flavor: |
|
||||
suffix=-rootless,onlatest=true
|
||||
# this will generate tags in the following format (with -rootless suffix added):
|
||||
# latest
|
||||
# 1
|
||||
# 1.2
|
||||
# 1.2.3
|
||||
tags: |
|
||||
type=semver,pattern={{major}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=semver,pattern={{version}}
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: build rootless docker image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
file: Dockerfile.rootless
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
12
.gitignore
vendored
12
.gitignore
vendored
@@ -11,11 +11,10 @@ _test
|
||||
.idea
|
||||
# Goland's output filename can not be set manually
|
||||
/go_build_*
|
||||
/gitea_*
|
||||
|
||||
# MS VSCode
|
||||
.vscode
|
||||
__debug_bin*
|
||||
__debug_bin
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
@@ -58,7 +57,7 @@ cpu.out
|
||||
/data
|
||||
/indexers
|
||||
/log
|
||||
/public/assets/img/avatar
|
||||
/public/img/avatar
|
||||
/tests/integration/gitea-integration-*
|
||||
/tests/integration/indexers-*
|
||||
/tests/e2e/gitea-e2e-*
|
||||
@@ -77,6 +76,7 @@ cpu.out
|
||||
/public/assets/css
|
||||
/public/assets/fonts
|
||||
/public/assets/licenses.txt
|
||||
/public/assets/img/webpack
|
||||
/vendor
|
||||
/web_src/fomantic/node_modules
|
||||
/web_src/fomantic/build/*
|
||||
@@ -94,9 +94,6 @@ cpu.out
|
||||
/.air
|
||||
/.go-licenses
|
||||
|
||||
# Files and folders that were previously generated
|
||||
/public/assets/img/webpack
|
||||
|
||||
# Snapcraft
|
||||
/gitea_a*.txt
|
||||
snap/.snapcraft/
|
||||
@@ -108,9 +105,6 @@ prime/
|
||||
*_source.tar.bz2
|
||||
.DS_Store
|
||||
|
||||
# nix-direnv generated files
|
||||
.direnv/
|
||||
|
||||
# Make evidence files
|
||||
/.make_evidence
|
||||
|
||||
|
||||
17
.gitpod.yml
17
.gitpod.yml
@@ -10,19 +10,10 @@ tasks:
|
||||
- name: Run backend
|
||||
command: |
|
||||
gp sync-await setup
|
||||
|
||||
# Get the URL and extract the domain
|
||||
url=$(gp url 3000)
|
||||
domain=$(echo $url | awk -F[/:] '{print $4}')
|
||||
|
||||
if [ -f custom/conf/app.ini ]; then
|
||||
sed -i "s|^ROOT_URL =.*|ROOT_URL = ${url}/|" custom/conf/app.ini
|
||||
sed -i "s|^DOMAIN =.*|DOMAIN = ${domain}|" custom/conf/app.ini
|
||||
sed -i "s|^SSH_DOMAIN =.*|SSH_DOMAIN = ${domain}|" custom/conf/app.ini
|
||||
sed -i "s|^NO_REPLY_ADDRESS =.*|SSH_DOMAIN = noreply.${domain}|" custom/conf/app.ini
|
||||
else
|
||||
if [ ! -f custom/conf/app.ini ]
|
||||
then
|
||||
mkdir -p custom/conf/
|
||||
echo -e "[server]\nROOT_URL = ${url}/" > custom/conf/app.ini
|
||||
echo -e "[server]\nROOT_URL=$(gp url 3000)/" > custom/conf/app.ini
|
||||
echo -e "\n[database]\nDB_TYPE = sqlite3\nPATH = $GITPOD_REPO_ROOT/data/gitea.db" >> custom/conf/app.ini
|
||||
fi
|
||||
export TAGS="sqlite sqlite_unlock_notify"
|
||||
@@ -42,7 +33,7 @@ vscode:
|
||||
- DavidAnson.vscode-markdownlint
|
||||
- Vue.volar
|
||||
- ms-azuretools.vscode-docker
|
||||
- vitest.explorer
|
||||
- zixuanchen.vitest-explorer
|
||||
- qwtel.sqlite-viewer
|
||||
- GitHub.vscode-pull-request-github
|
||||
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
linters:
|
||||
enable-all: false
|
||||
disable-all: true
|
||||
fast: false
|
||||
enable:
|
||||
- bidichk
|
||||
# - deadcode # deprecated - https://github.com/golangci/golangci-lint/issues/1841
|
||||
- depguard
|
||||
- dupl
|
||||
- errcheck
|
||||
- forbidigo
|
||||
- gocritic
|
||||
# - gocyclo # The cyclomatic complexety of a lot of functions is too high, we should refactor those another time.
|
||||
- gofmt
|
||||
- gofumpt
|
||||
- gosimple
|
||||
@@ -18,17 +17,24 @@ linters:
|
||||
- nolintlint
|
||||
- revive
|
||||
- staticcheck
|
||||
# - structcheck # deprecated - https://github.com/golangci/golangci-lint/issues/1841
|
||||
- stylecheck
|
||||
- typecheck
|
||||
- unconvert
|
||||
- unused
|
||||
# - varcheck # deprecated - https://github.com/golangci/golangci-lint/issues/1841
|
||||
- wastedassign
|
||||
enable-all: false
|
||||
disable-all: true
|
||||
fast: false
|
||||
|
||||
run:
|
||||
go: "1.21"
|
||||
timeout: 10m
|
||||
|
||||
output:
|
||||
sort-results: true
|
||||
skip-dirs:
|
||||
- node_modules
|
||||
- public
|
||||
- web_src
|
||||
|
||||
linters-settings:
|
||||
stylecheck:
|
||||
@@ -46,39 +52,30 @@ linters-settings:
|
||||
errorCode: 1
|
||||
warningCode: 1
|
||||
rules:
|
||||
- name: atomic
|
||||
- name: bare-return
|
||||
- name: blank-imports
|
||||
- name: constant-logical-expr
|
||||
- name: context-as-argument
|
||||
- name: context-keys-type
|
||||
- name: dot-imports
|
||||
- name: duplicated-imports
|
||||
- name: empty-lines
|
||||
- name: error-naming
|
||||
- name: error-return
|
||||
- name: error-strings
|
||||
- name: errorf
|
||||
- name: error-naming
|
||||
- name: exported
|
||||
- name: identical-branches
|
||||
- name: if-return
|
||||
- name: increment-decrement
|
||||
- name: indent-error-flow
|
||||
- name: modifies-value-receiver
|
||||
- name: var-naming
|
||||
- name: var-declaration
|
||||
- name: package-comments
|
||||
- name: range
|
||||
- name: receiver-naming
|
||||
- name: redefines-builtin-id
|
||||
- name: string-of-int
|
||||
- name: superfluous-else
|
||||
- name: time-naming
|
||||
- name: unconditional-recursion
|
||||
- name: unexported-return
|
||||
- name: unreachable-code
|
||||
- name: var-declaration
|
||||
- name: var-naming
|
||||
- name: indent-error-flow
|
||||
- name: errorf
|
||||
- name: duplicated-imports
|
||||
- name: modifies-value-receiver
|
||||
gofumpt:
|
||||
extra-rules: true
|
||||
lang-version: "1.21"
|
||||
depguard:
|
||||
rules:
|
||||
main:
|
||||
@@ -95,15 +92,12 @@ linters-settings:
|
||||
desc: do not use the internal package, use AddXxx function instead
|
||||
- pkg: gopkg.in/ini.v1
|
||||
desc: do not use the ini package, use gitea's config system instead
|
||||
- pkg: gitea.com/go-chi/cache
|
||||
desc: do not use the go-chi cache package, use gitea's cache system
|
||||
|
||||
issues:
|
||||
max-issues-per-linter: 0
|
||||
max-same-issues: 0
|
||||
exclude-dirs: [node_modules, public, web_src]
|
||||
exclude-case-sensitive: true
|
||||
exclude-rules:
|
||||
# Exclude some linters from running on tests files.
|
||||
- path: _test\.go
|
||||
linters:
|
||||
- gocyclo
|
||||
@@ -121,19 +115,19 @@ issues:
|
||||
- path: cmd
|
||||
linters:
|
||||
- forbidigo
|
||||
- text: "webhook"
|
||||
linters:
|
||||
- linters:
|
||||
- dupl
|
||||
- text: "`ID' should not be capitalized"
|
||||
linters:
|
||||
text: "webhook"
|
||||
- linters:
|
||||
- gocritic
|
||||
- text: "swagger"
|
||||
linters:
|
||||
text: "`ID' should not be capitalized"
|
||||
- linters:
|
||||
- unused
|
||||
- deadcode
|
||||
- text: "argument x is overwritten before first use"
|
||||
linters:
|
||||
text: "swagger"
|
||||
- linters:
|
||||
- staticcheck
|
||||
text: "argument x is overwritten before first use"
|
||||
- text: "commentFormatting: put a space between `//` and comment text"
|
||||
linters:
|
||||
- gocritic
|
||||
|
||||
4
.ignore
4
.ignore
@@ -4,8 +4,6 @@
|
||||
/modules/options/bindata.go
|
||||
/modules/public/bindata.go
|
||||
/modules/templates/bindata.go
|
||||
/options/gitignore
|
||||
/options/license
|
||||
/public/assets
|
||||
/vendor
|
||||
/public/assets
|
||||
node_modules
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
commands-show-output: false
|
||||
fenced-code-language: false
|
||||
first-line-h1: false
|
||||
heading-increment: false
|
||||
header-increment: false
|
||||
line-length: {code_blocks: false, tables: false, stern: true, line_length: -1}
|
||||
no-alt-text: false
|
||||
no-bare-urls: false
|
||||
no-emphasis-as-heading: false
|
||||
no-blanks-blockquote: false
|
||||
no-duplicate-header: {allow_different_nesting: true}
|
||||
no-emphasis-as-header: false
|
||||
no-empty-links: false
|
||||
no-hard-tabs: {code_blocks: false}
|
||||
no-inline-html: false
|
||||
no-space-in-code: false
|
||||
no-space-in-emphasis: false
|
||||
no-trailing-punctuation: false
|
||||
no-trailing-spaces: {br_spaces: 0}
|
||||
single-h1: false
|
||||
|
||||
221
.stylelintrc.yaml
Normal file
221
.stylelintrc.yaml
Normal file
@@ -0,0 +1,221 @@
|
||||
plugins:
|
||||
- stylelint-declaration-strict-value
|
||||
- stylelint-declaration-block-no-ignored-properties
|
||||
- stylelint-stylistic
|
||||
|
||||
ignoreFiles:
|
||||
- "**/*.go"
|
||||
|
||||
overrides:
|
||||
- files: ["**/chroma/*", "**/codemirror/*", "**/standalone/*", "**/console.css", "font_i18n.css"]
|
||||
rules:
|
||||
scale-unlimited/declaration-strict-value: null
|
||||
- files: ["**/chroma/*", "**/codemirror/*"]
|
||||
rules:
|
||||
block-no-empty: null
|
||||
- files: ["**/*.vue"]
|
||||
customSyntax: postcss-html
|
||||
|
||||
rules:
|
||||
alpha-value-notation: null
|
||||
annotation-no-unknown: true
|
||||
at-rule-allowed-list: null
|
||||
at-rule-disallowed-list: null
|
||||
at-rule-empty-line-before: null
|
||||
at-rule-no-unknown: true
|
||||
at-rule-no-vendor-prefix: true
|
||||
at-rule-property-required-list: null
|
||||
block-no-empty: true
|
||||
color-function-notation: null
|
||||
color-hex-alpha: null
|
||||
color-hex-length: null
|
||||
color-named: null
|
||||
color-no-hex: null
|
||||
color-no-invalid-hex: true
|
||||
comment-empty-line-before: null
|
||||
comment-no-empty: true
|
||||
comment-pattern: null
|
||||
comment-whitespace-inside: null
|
||||
comment-word-disallowed-list: null
|
||||
custom-media-pattern: null
|
||||
custom-property-empty-line-before: null
|
||||
custom-property-no-missing-var-function: true
|
||||
custom-property-pattern: null
|
||||
declaration-block-no-duplicate-custom-properties: true
|
||||
declaration-block-no-duplicate-properties: [true, {ignore: [consecutive-duplicates-with-different-values]}]
|
||||
declaration-block-no-redundant-longhand-properties: null
|
||||
declaration-block-no-shorthand-property-overrides: null
|
||||
declaration-block-single-line-max-declarations: null
|
||||
declaration-empty-line-before: null
|
||||
declaration-no-important: null
|
||||
declaration-property-max-values: null
|
||||
declaration-property-unit-allowed-list: null
|
||||
declaration-property-unit-disallowed-list: {line-height: [em]}
|
||||
declaration-property-value-allowed-list: null
|
||||
declaration-property-value-disallowed-list: null
|
||||
declaration-property-value-no-unknown: true
|
||||
font-family-name-quotes: always-where-recommended
|
||||
font-family-no-duplicate-names: true
|
||||
font-family-no-missing-generic-family-keyword: true
|
||||
font-weight-notation: null
|
||||
function-allowed-list: null
|
||||
function-calc-no-unspaced-operator: true
|
||||
function-disallowed-list: null
|
||||
function-linear-gradient-no-nonstandard-direction: true
|
||||
function-name-case: lower
|
||||
function-no-unknown: null
|
||||
function-url-no-scheme-relative: null
|
||||
function-url-quotes: always
|
||||
function-url-scheme-allowed-list: null
|
||||
function-url-scheme-disallowed-list: null
|
||||
hue-degree-notation: null
|
||||
import-notation: string
|
||||
keyframe-block-no-duplicate-selectors: true
|
||||
keyframe-declaration-no-important: true
|
||||
keyframe-selector-notation: null
|
||||
keyframes-name-pattern: null
|
||||
length-zero-no-unit: true
|
||||
max-nesting-depth: null
|
||||
media-feature-name-allowed-list: null
|
||||
media-feature-name-disallowed-list: null
|
||||
media-feature-name-no-unknown: true
|
||||
media-feature-name-no-vendor-prefix: true
|
||||
media-feature-name-unit-allowed-list: null
|
||||
media-feature-name-value-allowed-list: null
|
||||
media-feature-name-value-no-unknown: true
|
||||
media-feature-range-notation: null
|
||||
media-query-no-invalid: true
|
||||
named-grid-areas-no-invalid: true
|
||||
no-descending-specificity: null
|
||||
no-duplicate-at-import-rules: true
|
||||
no-duplicate-selectors: true
|
||||
no-empty-source: true
|
||||
no-invalid-double-slash-comments: true
|
||||
no-invalid-position-at-import-rule: null
|
||||
no-irregular-whitespace: true
|
||||
no-unknown-animations: null
|
||||
no-unknown-custom-properties: null
|
||||
number-max-precision: null
|
||||
plugin/declaration-block-no-ignored-properties: true
|
||||
property-allowed-list: null
|
||||
property-disallowed-list: null
|
||||
property-no-unknown: true
|
||||
property-no-vendor-prefix: null
|
||||
rule-empty-line-before: null
|
||||
rule-selector-property-disallowed-list: null
|
||||
scale-unlimited/declaration-strict-value: [[color, background-color, border-color, font-weight], {ignoreValues: /^(inherit|transparent|unset|initial|currentcolor|none)$/, ignoreFunctions: false, disableFix: true}]
|
||||
selector-attribute-name-disallowed-list: null
|
||||
selector-attribute-operator-allowed-list: null
|
||||
selector-attribute-operator-disallowed-list: null
|
||||
selector-attribute-quotes: always
|
||||
selector-class-pattern: null
|
||||
selector-combinator-allowed-list: null
|
||||
selector-combinator-disallowed-list: null
|
||||
selector-disallowed-list: null
|
||||
selector-id-pattern: null
|
||||
selector-max-attribute: null
|
||||
selector-max-class: null
|
||||
selector-max-combinators: null
|
||||
selector-max-compound-selectors: null
|
||||
selector-max-id: null
|
||||
selector-max-pseudo-class: null
|
||||
selector-max-specificity: null
|
||||
selector-max-type: null
|
||||
selector-max-universal: null
|
||||
selector-nested-pattern: null
|
||||
selector-no-qualifying-type: null
|
||||
selector-no-vendor-prefix: true
|
||||
selector-not-notation: null
|
||||
selector-pseudo-class-allowed-list: null
|
||||
selector-pseudo-class-disallowed-list: null
|
||||
selector-pseudo-class-no-unknown: true
|
||||
selector-pseudo-element-allowed-list: null
|
||||
selector-pseudo-element-colon-notation: double
|
||||
selector-pseudo-element-disallowed-list: null
|
||||
selector-pseudo-element-no-unknown: true
|
||||
selector-type-case: lower
|
||||
selector-type-no-unknown: [true, {ignore: [custom-elements]}]
|
||||
shorthand-property-no-redundant-values: true
|
||||
string-no-newline: true
|
||||
stylistic/at-rule-name-case: null
|
||||
stylistic/at-rule-name-newline-after: null
|
||||
stylistic/at-rule-name-space-after: null
|
||||
stylistic/at-rule-semicolon-newline-after: null
|
||||
stylistic/at-rule-semicolon-space-before: null
|
||||
stylistic/block-closing-brace-empty-line-before: null
|
||||
stylistic/block-closing-brace-newline-after: null
|
||||
stylistic/block-closing-brace-newline-before: null
|
||||
stylistic/block-closing-brace-space-after: null
|
||||
stylistic/block-closing-brace-space-before: null
|
||||
stylistic/block-opening-brace-newline-after: null
|
||||
stylistic/block-opening-brace-newline-before: null
|
||||
stylistic/block-opening-brace-space-after: null
|
||||
stylistic/block-opening-brace-space-before: null
|
||||
stylistic/color-hex-case: lower
|
||||
stylistic/declaration-bang-space-after: never
|
||||
stylistic/declaration-bang-space-before: null
|
||||
stylistic/declaration-block-semicolon-newline-after: null
|
||||
stylistic/declaration-block-semicolon-newline-before: null
|
||||
stylistic/declaration-block-semicolon-space-after: null
|
||||
stylistic/declaration-block-semicolon-space-before: never
|
||||
stylistic/declaration-block-trailing-semicolon: null
|
||||
stylistic/declaration-colon-newline-after: null
|
||||
stylistic/declaration-colon-space-after: null
|
||||
stylistic/declaration-colon-space-before: never
|
||||
stylistic/function-comma-newline-after: null
|
||||
stylistic/function-comma-newline-before: null
|
||||
stylistic/function-comma-space-after: null
|
||||
stylistic/function-comma-space-before: null
|
||||
stylistic/function-max-empty-lines: 0
|
||||
stylistic/function-parentheses-newline-inside: never-multi-line
|
||||
stylistic/function-parentheses-space-inside: null
|
||||
stylistic/function-whitespace-after: null
|
||||
stylistic/indentation: 2
|
||||
stylistic/linebreaks: null
|
||||
stylistic/max-empty-lines: 1
|
||||
stylistic/max-line-length: null
|
||||
stylistic/media-feature-colon-space-after: null
|
||||
stylistic/media-feature-colon-space-before: never
|
||||
stylistic/media-feature-name-case: null
|
||||
stylistic/media-feature-parentheses-space-inside: null
|
||||
stylistic/media-feature-range-operator-space-after: always
|
||||
stylistic/media-feature-range-operator-space-before: always
|
||||
stylistic/media-query-list-comma-newline-after: null
|
||||
stylistic/media-query-list-comma-newline-before: null
|
||||
stylistic/media-query-list-comma-space-after: null
|
||||
stylistic/media-query-list-comma-space-before: null
|
||||
stylistic/no-empty-first-line: null
|
||||
stylistic/no-eol-whitespace: true
|
||||
stylistic/no-extra-semicolons: true
|
||||
stylistic/no-missing-end-of-source-newline: null
|
||||
stylistic/number-leading-zero: null
|
||||
stylistic/number-no-trailing-zeros: null
|
||||
stylistic/property-case: lower
|
||||
stylistic/selector-attribute-brackets-space-inside: null
|
||||
stylistic/selector-attribute-operator-space-after: null
|
||||
stylistic/selector-attribute-operator-space-before: null
|
||||
stylistic/selector-combinator-space-after: null
|
||||
stylistic/selector-combinator-space-before: null
|
||||
stylistic/selector-descendant-combinator-no-non-space: null
|
||||
stylistic/selector-list-comma-newline-after: null
|
||||
stylistic/selector-list-comma-newline-before: null
|
||||
stylistic/selector-list-comma-space-after: always-single-line
|
||||
stylistic/selector-list-comma-space-before: never-single-line
|
||||
stylistic/selector-max-empty-lines: 0
|
||||
stylistic/selector-pseudo-class-case: lower
|
||||
stylistic/selector-pseudo-class-parentheses-space-inside: never
|
||||
stylistic/selector-pseudo-element-case: lower
|
||||
stylistic/string-quotes: double
|
||||
stylistic/unicode-bom: null
|
||||
stylistic/unit-case: lower
|
||||
stylistic/value-list-comma-newline-after: null
|
||||
stylistic/value-list-comma-newline-before: null
|
||||
stylistic/value-list-comma-space-after: null
|
||||
stylistic/value-list-comma-space-before: null
|
||||
stylistic/value-list-max-empty-lines: 0
|
||||
time-min-milliseconds: null
|
||||
unit-allowed-list: null
|
||||
unit-disallowed-list: null
|
||||
unit-no-unknown: true
|
||||
value-keyword-case: null
|
||||
value-no-vendor-prefix: [true, {ignoreValues: [box, inline-box]}]
|
||||
@@ -24,6 +24,8 @@ rules:
|
||||
document-start:
|
||||
level: error
|
||||
present: false
|
||||
ignore: |
|
||||
/.drone.yml
|
||||
|
||||
document-end:
|
||||
present: false
|
||||
|
||||
@@ -42,13 +42,13 @@ GARGS = "--no-print-directory"
|
||||
|
||||
# The GNU convention is to use the lowercased `prefix` variable/macro to
|
||||
# specify the installation directory. Humor them.
|
||||
GPREFIX =
|
||||
GPREFIX = ""
|
||||
.if defined(PREFIX) && ! defined(prefix)
|
||||
GPREFIX = 'prefix = "$(PREFIX)"'
|
||||
.endif
|
||||
|
||||
.BEGIN: .SILENT
|
||||
which $(GMAKE) || (printf "Error: GNU Make is required!\n\n" 1>&2 && false)
|
||||
which $(GMAKE) || printf "Error: GNU Make is required!\n\n" 1>&2 && false
|
||||
|
||||
.PHONY: FRC
|
||||
$(.TARGETS): FRC
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
6354
CHANGELOG.md
6354
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,6 @@
|
||||
- [How to report issues](#how-to-report-issues)
|
||||
- [Types of issues](#types-of-issues)
|
||||
- [Discuss your design before the implementation](#discuss-your-design-before-the-implementation)
|
||||
- [Issue locking](#issue-locking)
|
||||
- [Building Gitea](#building-gitea)
|
||||
- [Dependencies](#dependencies)
|
||||
- [Backend](#backend)
|
||||
@@ -48,7 +47,6 @@
|
||||
- [Release Cycle](#release-cycle)
|
||||
- [Maintainers](#maintainers)
|
||||
- [Technical Oversight Committee (TOC)](#technical-oversight-committee-toc)
|
||||
- [TOC election process](#toc-election-process)
|
||||
- [Current TOC members](#current-toc-members)
|
||||
- [Previous TOC/owners members](#previous-tocowners-members)
|
||||
- [Governance Compensation](#governance-compensation)
|
||||
@@ -77,7 +75,7 @@ If your issue has not been reported yet, [open an issue](https://github.com/go-g
|
||||
and answer the questions so we can understand and reproduce the problematic behavior. \
|
||||
Please write clear and concise instructions so that we can reproduce the behavior — even if it seems obvious. \
|
||||
The more detailed and specific you are, the faster we can fix the issue. \
|
||||
It is really helpful if you can reproduce your problem on a site running on the latest commits, i.e. <https://demo.gitea.com>, as perhaps your problem has already been fixed on a current version. \
|
||||
It is really helpful if you can reproduce your problem on a site running on the latest commits, i.e. <https://try.gitea.io>, as perhaps your problem has already been fixed on a current version. \
|
||||
Please follow the guidelines described in [How to Report Bugs Effectively](http://www.chiark.greenend.org.uk/~sgtatham/bugs.html) for your report.
|
||||
|
||||
Please be kind, remember that Gitea comes at no cost to you, and you're getting free help.
|
||||
@@ -104,13 +102,6 @@ the goals for the project and tools.
|
||||
|
||||
Pull requests should not be the place for architecture discussions.
|
||||
|
||||
### Issue locking
|
||||
|
||||
Commenting on closed or merged issues/PRs is strongly discouraged.
|
||||
Such comments will likely be overlooked as some maintainers may not view notifications on closed issues, thinking that the item is resolved.
|
||||
As such, commenting on closed/merged issues/PRs may be disabled prior to the scheduled auto-locking if a discussion starts or if unrelated comments are posted.
|
||||
If further discussion is needed, we encourage you to open a new issue instead and we recommend linking to the issue/PR in question for context.
|
||||
|
||||
## Building Gitea
|
||||
|
||||
See the [development setup instructions](https://docs.gitea.com/development/hacking-on-gitea).
|
||||
@@ -119,7 +110,7 @@ See the [development setup instructions](https://docs.gitea.com/development/hack
|
||||
|
||||
### Backend
|
||||
|
||||
Go dependencies are managed using [Go Modules](https://go.dev/cmd/go/#hdr-Module_maintenance). \
|
||||
Go dependencies are managed using [Go Modules](https://golang.org/cmd/go/#hdr-Module_maintenance). \
|
||||
You can find more details in the [go mod documentation](https://go.dev/ref/mod) and the [Go Modules Wiki](https://github.com/golang/go/wiki/Modules).
|
||||
|
||||
Pull requests should only modify `go.mod` and `go.sum` where it is related to your change, be it a bugfix or a new feature. \
|
||||
@@ -176,7 +167,7 @@ Here's how to run the test suite:
|
||||
|
||||
| Command | Action | |
|
||||
| :------------------------------------- | :----------------------------------------------- | ------------ |
|
||||
|``make test[\#SpecificTestName]`` | run unit test(s) | |
|
||||
|``make test[\#SpecificTestName]`` | run unit test(s) |
|
||||
|``make test-sqlite[\#SpecificTestName]``| run [integration](tests/integration) test(s) for SQLite |[More details](tests/integration/README.md) |
|
||||
|``make test-e2e-sqlite[\#SpecificTestName]``| run [end-to-end](tests/e2e) test(s) for SQLite |[More details](tests/e2e/README.md) |
|
||||
|
||||
@@ -212,20 +203,10 @@ Some of the key points:
|
||||
|
||||
In the PR title, describe the problem you are fixing, not how you are fixing it. \
|
||||
Use the first comment as a summary of your PR. \
|
||||
In the PR summary, you can describe exactly how you are fixing this problem.
|
||||
|
||||
In the PR summary, you can describe exactly how you are fixing this problem. \
|
||||
Keep this summary up-to-date as the PR evolves. \
|
||||
If your PR changes the UI, you must add **after** screenshots in the PR summary. \
|
||||
If you are not implementing a new feature, you should also post **before** screenshots for comparison.
|
||||
|
||||
If you are implementing a new feature, your PR will only be merged if your screenshots are up to date.\
|
||||
Furthermore, feature PRs will only be merged if their summary contains a clear usage description (understandable for users) and testing description (understandable for reviewers).
|
||||
You should strive to combine both into a single description.
|
||||
|
||||
Another requirement for merging PRs is that the PR is labeled correctly.\
|
||||
However, this is not your job as a contributor, but the job of the person merging your PR.\
|
||||
If you think that your PR was labeled incorrectly, or notice that it was merged without labels, please let us know.
|
||||
|
||||
If you are not implementing a new feature, you should also post **before** screenshots for comparison. \
|
||||
If your PR closes some issues, you must note that in a way that both GitHub and Gitea understand, i.e. by appending a paragraph like
|
||||
|
||||
```text
|
||||
@@ -244,20 +225,17 @@ PRs without a milestone may not be merged.
|
||||
|
||||
### Labels
|
||||
|
||||
Almost all labels used inside Gitea can be classified as one of the following:
|
||||
|
||||
- `modifies/…`: Determines which parts of the codebase are affected. These labels will be set through the CI.
|
||||
- `topic/…`: Determines the conceptual component of Gitea that is affected, i.e. issues, projects, or authentication. At best, PRs should only target one component but there might be overlap. Must be set manually.
|
||||
- `type/…`: Determines the type of an issue or PR (feature, refactoring, docs, bug, …). If GitHub supported scoped labels, these labels would be exclusive, so you should set **exactly** one, not more or less (every PR should fall into one of the provided categories, and only one).
|
||||
- `issue/…` / `pr/…`: Labels that are specific to issues or PRs respectively and that are only necessary in a given context, i.e. `issue/not-a-bug` or `pr/need-2-approvals`
|
||||
|
||||
Every PR should be labeled correctly with every label that applies.
|
||||
|
||||
There are also some labels that will be managed automatically.\
|
||||
In particular, these are
|
||||
Every PR should be labeled correctly with every label that applies. \
|
||||
This includes especially the distinction between `bug` (fixing existing functionality), `feature` (new functionality), `enhancement` (upgrades for existing functionality), and `refactoring` (improving the internal code structure without changing the output (much)). \
|
||||
Furthermore,
|
||||
|
||||
- the amount of pending required approvals
|
||||
- has all `backport`s or needs a manual backport
|
||||
- whether this PR is `blocked`, a `backport` or `breaking`
|
||||
- if it targets the `ui` or `api`
|
||||
- if it increases the application `speed`
|
||||
- reduces `memory usage`
|
||||
|
||||
are oftentimes notable labels.
|
||||
|
||||
### Breaking PRs
|
||||
|
||||
@@ -274,16 +252,13 @@ Changing the default value of a setting or replacing the setting with another on
|
||||
|
||||
#### How to handle breaking PRs?
|
||||
|
||||
If your PR has a breaking change, you must add two things to the summary of your PR:
|
||||
If your PR has a breaking change, you must add a `BREAKING` section to your PR summary, e.g.
|
||||
|
||||
1. A reasoning why this breaking change is necessary
|
||||
2. A `BREAKING` section explaining in simple terms (understandable for a typical user) how this PR affects users and how to mitigate these changes. This section can look for example like
|
||||
|
||||
```md
|
||||
```
|
||||
## :warning: BREAKING :warning:
|
||||
```
|
||||
|
||||
Breaking PRs will not be merged as long as not both of these requirements are met.
|
||||
To explain how this will affect users and how to mitigate these changes.
|
||||
|
||||
### Maintaining open PRs
|
||||
|
||||
@@ -362,7 +337,7 @@ If you add a new feature or change an existing aspect of Gitea, the documentatio
|
||||
|
||||
## API v1
|
||||
|
||||
The API is documented by [swagger](https://gitea.com/api/swagger) and is based on [the GitHub API](https://docs.github.com/en/rest).
|
||||
The API is documented by [swagger](http://try.gitea.io/api/swagger) and is based on [the GitHub API](https://docs.github.com/en/rest).
|
||||
|
||||
### GitHub API compatibility
|
||||
|
||||
@@ -464,7 +439,7 @@ We assume in good faith that the information you provide is legally binding.
|
||||
We adopted a release schedule to streamline the process of working on, finishing, and issuing releases. \
|
||||
The overall goal is to make a major release every three or four months, which breaks down into two or three months of general development followed by one month of testing and polishing known as the release freeze. \
|
||||
All the feature pull requests should be
|
||||
merged before feature freeze. All feature pull requests haven't been merged before this feature freeze will be moved to next milestone, please notice our feature freeze announcement on discord. And, during the frozen period, a corresponding
|
||||
merged before feature freeze. And, during the frozen period, a corresponding
|
||||
release branch is open for fixes backported from main branch. Release candidates
|
||||
are made during this period for user testing to
|
||||
obtain a final version that is maintained in this branch.
|
||||
@@ -495,53 +470,36 @@ if possible provide GPG signed commits.
|
||||
https://help.github.com/articles/securing-your-account-with-two-factor-authentication-2fa/
|
||||
https://help.github.com/articles/signing-commits-with-gpg/
|
||||
|
||||
Furthermore, any account with write access (like bots and TOC members) **must** use 2FA.
|
||||
https://help.github.com/articles/securing-your-account-with-two-factor-authentication-2fa/
|
||||
|
||||
## Technical Oversight Committee (TOC)
|
||||
|
||||
At the start of 2023, the `Owners` team was dissolved. Instead, the governance charter proposed a technical oversight committee (TOC) which expands the ownership team of the Gitea project from three elected positions to six positions. Three positions are elected as it has been over the past years, and the other three consist of appointed members from the Gitea company.
|
||||
At the start of 2023, the `Owners` team was dissolved. Instead, the governance charter proposed a technical oversight committee (TOC) which expands the ownership team of the Gitea project from three elected positions to six positions. Three positions would be elected as it has been over the past years, and the other three would consist of appointed members from the Gitea company.
|
||||
https://blog.gitea.com/quarterly-23q1/
|
||||
|
||||
### TOC election process
|
||||
|
||||
Any maintainer is eligible to be part of the community TOC if they are not associated with the Gitea company.
|
||||
A maintainer can either nominate themselves, or can be nominated by other maintainers to be a candidate for the TOC election.
|
||||
If you are nominated by someone else, you must first accept your nomination before the vote starts to be a candidate.
|
||||
|
||||
The TOC is elected for one year, the TOC election happens yearly.
|
||||
After the announcement of the results of the TOC election, elected members have two weeks time to confirm or refuse the seat.
|
||||
If an elected member does not answer within this timeframe, they are automatically assumed to refuse the seat.
|
||||
Refusals result in the person with the next highest vote getting the same choice.
|
||||
As long as seats are empty in the TOC, members of the previous TOC can fill them until an elected member accepts the seat.
|
||||
|
||||
If an elected member that accepts the seat does not have 2FA configured yet, they will be temporarily counted as `answer pending` until they manage to configure 2FA, thus leaving their seat empty for this duration.
|
||||
When the new community members have been elected, the old members will give up ownership to the newly elected members. For security reasons, TOC members or any account with write access (like a bot) must use 2FA.
|
||||
https://help.github.com/articles/securing-your-account-with-two-factor-authentication-2fa/
|
||||
|
||||
### Current TOC members
|
||||
|
||||
- 2024-01-01 ~ 2024-12-31
|
||||
- 2023-01-01 ~ 2023-12-31 - https://blog.gitea.com/quarterly-23q1/
|
||||
- Company
|
||||
- [Jason Song](https://gitea.com/wolfogre) <i@wolfogre.com>
|
||||
- [Lunny Xiao](https://gitea.com/lunny) <xiaolunwen@gmail.com>
|
||||
- [Matti Ranta](https://gitea.com/techknowlogick) <techknowlogick@gitea.com>
|
||||
- [Matti Ranta](https://gitea.com/techknowlogick) <techknowlogick@gitea.io>
|
||||
- Community
|
||||
- [6543](https://gitea.com/6543) <6543@obermui.de>
|
||||
- [delvh](https://gitea.com/delvh) <dev.lh@web.de>
|
||||
- [Andrew Thornton](https://gitea.com/zeripath) <art27@cantab.net>
|
||||
- [John Olheiser](https://gitea.com/jolheiser) <john.olheiser@gmail.com>
|
||||
|
||||
### Previous TOC/owners members
|
||||
|
||||
Here's the history of the owners and the time they served:
|
||||
|
||||
- [Lunny Xiao](https://gitea.com/lunny) - 2016, 2017, [2018](https://github.com/go-gitea/gitea/issues/3255), [2019](https://github.com/go-gitea/gitea/issues/5572), [2020](https://github.com/go-gitea/gitea/issues/9230), [2021](https://github.com/go-gitea/gitea/issues/13801), [2022](https://github.com/go-gitea/gitea/issues/17872), 2023
|
||||
- [Lunny Xiao](https://gitea.com/lunny) - 2016, 2017, [2018](https://github.com/go-gitea/gitea/issues/3255), [2019](https://github.com/go-gitea/gitea/issues/5572), [2020](https://github.com/go-gitea/gitea/issues/9230), [2021](https://github.com/go-gitea/gitea/issues/13801), [2022](https://github.com/go-gitea/gitea/issues/17872)
|
||||
- [Kim Carlbäcker](https://github.com/bkcsoft) - 2016, 2017
|
||||
- [Thomas Boerger](https://gitea.com/tboerger) - 2016, 2017
|
||||
- [Lauris Bukšis-Haberkorns](https://gitea.com/lafriks) - [2018](https://github.com/go-gitea/gitea/issues/3255), [2019](https://github.com/go-gitea/gitea/issues/5572), [2020](https://github.com/go-gitea/gitea/issues/9230), [2021](https://github.com/go-gitea/gitea/issues/13801)
|
||||
- [Matti Ranta](https://gitea.com/techknowlogick) - [2019](https://github.com/go-gitea/gitea/issues/5572), [2020](https://github.com/go-gitea/gitea/issues/9230), [2021](https://github.com/go-gitea/gitea/issues/13801), [2022](https://github.com/go-gitea/gitea/issues/17872), 2023
|
||||
- [Andrew Thornton](https://gitea.com/zeripath) - [2020](https://github.com/go-gitea/gitea/issues/9230), [2021](https://github.com/go-gitea/gitea/issues/13801), [2022](https://github.com/go-gitea/gitea/issues/17872), 2023
|
||||
- [6543](https://gitea.com/6543) - 2023
|
||||
- [John Olheiser](https://gitea.com/jolheiser) - 2023
|
||||
- [Jason Song](https://gitea.com/wolfogre) - 2023
|
||||
- [Matti Ranta](https://gitea.com/techknowlogick) - [2019](https://github.com/go-gitea/gitea/issues/5572), [2020](https://github.com/go-gitea/gitea/issues/9230), [2021](https://github.com/go-gitea/gitea/issues/13801), [2022](https://github.com/go-gitea/gitea/issues/17872)
|
||||
- [Andrew Thornton](https://gitea.com/zeripath) - [2020](https://github.com/go-gitea/gitea/issues/9230), [2021](https://github.com/go-gitea/gitea/issues/13801), [2022](https://github.com/go-gitea/gitea/issues/17872)
|
||||
|
||||
## Governance Compensation
|
||||
|
||||
|
||||
48
Dockerfile
48
Dockerfile
@@ -1,47 +1,29 @@
|
||||
# Build stage
|
||||
FROM docker.io/library/golang:1.22-alpine3.20 AS build-env
|
||||
#Build stage
|
||||
FROM docker.io/library/golang:1.21-alpine3.18 AS build-env
|
||||
|
||||
ARG GOPROXY
|
||||
ENV GOPROXY=${GOPROXY:-direct}
|
||||
ENV GOPROXY ${GOPROXY:-direct}
|
||||
|
||||
ARG GITEA_VERSION
|
||||
ARG TAGS="sqlite sqlite_unlock_notify"
|
||||
ENV TAGS="bindata timetzdata $TAGS"
|
||||
ENV TAGS "bindata timetzdata $TAGS"
|
||||
ARG CGO_EXTRA_CFLAGS
|
||||
|
||||
# Build deps
|
||||
RUN apk --no-cache add \
|
||||
build-base \
|
||||
git \
|
||||
nodejs \
|
||||
npm \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
#Build deps
|
||||
RUN apk --no-cache add build-base git nodejs npm
|
||||
|
||||
# Setup repo
|
||||
#Setup repo
|
||||
COPY . ${GOPATH}/src/code.gitea.io/gitea
|
||||
WORKDIR ${GOPATH}/src/code.gitea.io/gitea
|
||||
|
||||
# Checkout version if set
|
||||
#Checkout version if set
|
||||
RUN if [ -n "${GITEA_VERSION}" ]; then git checkout "${GITEA_VERSION}"; fi \
|
||||
&& make clean-all build
|
||||
|
||||
# Begin env-to-ini build
|
||||
RUN go build contrib/environment-to-ini/environment-to-ini.go
|
||||
|
||||
# Copy local files
|
||||
COPY docker/root /tmp/local
|
||||
|
||||
# Set permissions
|
||||
RUN chmod 755 /tmp/local/usr/bin/entrypoint \
|
||||
/tmp/local/usr/local/bin/gitea \
|
||||
/tmp/local/etc/s6/gitea/* \
|
||||
/tmp/local/etc/s6/openssh/* \
|
||||
/tmp/local/etc/s6/.s6-svscan/* \
|
||||
/go/src/code.gitea.io/gitea/gitea \
|
||||
/go/src/code.gitea.io/gitea/environment-to-ini
|
||||
RUN chmod 644 /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete
|
||||
|
||||
FROM docker.io/library/alpine:3.20
|
||||
FROM docker.io/library/alpine:3.18
|
||||
LABEL maintainer="maintainers@gitea.io"
|
||||
|
||||
EXPOSE 22 3000
|
||||
@@ -57,8 +39,7 @@ RUN apk --no-cache add \
|
||||
s6 \
|
||||
sqlite \
|
||||
su-exec \
|
||||
gnupg \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
gnupg
|
||||
|
||||
RUN addgroup \
|
||||
-S -g 1000 \
|
||||
@@ -72,15 +53,18 @@ RUN addgroup \
|
||||
git && \
|
||||
echo "git:*" | chpasswd -e
|
||||
|
||||
ENV USER=git
|
||||
ENV GITEA_CUSTOM=/data/gitea
|
||||
ENV USER git
|
||||
ENV GITEA_CUSTOM /data/gitea
|
||||
|
||||
VOLUME ["/data"]
|
||||
|
||||
ENTRYPOINT ["/usr/bin/entrypoint"]
|
||||
CMD ["/bin/s6-svscan", "/etc/s6"]
|
||||
|
||||
COPY --from=build-env /tmp/local /
|
||||
COPY docker/root /
|
||||
COPY --from=build-env /go/src/code.gitea.io/gitea/gitea /app/gitea/gitea
|
||||
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
|
||||
RUN chmod 755 /usr/bin/entrypoint /app/gitea/gitea /usr/local/bin/gitea /usr/local/bin/environment-to-ini
|
||||
RUN chmod 755 /etc/s6/gitea/* /etc/s6/openssh/* /etc/s6/.s6-svscan/*
|
||||
RUN chmod 644 /etc/profile.d/gitea_bash_autocomplete.sh
|
||||
|
||||
@@ -1,45 +1,29 @@
|
||||
# Build stage
|
||||
FROM docker.io/library/golang:1.22-alpine3.20 AS build-env
|
||||
#Build stage
|
||||
FROM docker.io/library/golang:1.21-alpine3.18 AS build-env
|
||||
|
||||
ARG GOPROXY
|
||||
ENV GOPROXY=${GOPROXY:-direct}
|
||||
ENV GOPROXY ${GOPROXY:-direct}
|
||||
|
||||
ARG GITEA_VERSION
|
||||
ARG TAGS="sqlite sqlite_unlock_notify"
|
||||
ENV TAGS="bindata timetzdata $TAGS"
|
||||
ENV TAGS "bindata timetzdata $TAGS"
|
||||
ARG CGO_EXTRA_CFLAGS
|
||||
|
||||
#Build deps
|
||||
RUN apk --no-cache add \
|
||||
build-base \
|
||||
git \
|
||||
nodejs \
|
||||
npm \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
RUN apk --no-cache add build-base git nodejs npm
|
||||
|
||||
# Setup repo
|
||||
#Setup repo
|
||||
COPY . ${GOPATH}/src/code.gitea.io/gitea
|
||||
WORKDIR ${GOPATH}/src/code.gitea.io/gitea
|
||||
|
||||
# Checkout version if set
|
||||
#Checkout version if set
|
||||
RUN if [ -n "${GITEA_VERSION}" ]; then git checkout "${GITEA_VERSION}"; fi \
|
||||
&& make clean-all build
|
||||
|
||||
# Begin env-to-ini build
|
||||
RUN go build contrib/environment-to-ini/environment-to-ini.go
|
||||
|
||||
# Copy local files
|
||||
COPY docker/rootless /tmp/local
|
||||
|
||||
# Set permissions
|
||||
RUN chmod 755 /tmp/local/usr/local/bin/docker-entrypoint.sh \
|
||||
/tmp/local/usr/local/bin/docker-setup.sh \
|
||||
/tmp/local/usr/local/bin/gitea \
|
||||
/go/src/code.gitea.io/gitea/gitea \
|
||||
/go/src/code.gitea.io/gitea/environment-to-ini
|
||||
RUN chmod 644 /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete
|
||||
|
||||
FROM docker.io/library/alpine:3.20
|
||||
FROM docker.io/library/alpine:3.18
|
||||
LABEL maintainer="maintainers@gitea.io"
|
||||
|
||||
EXPOSE 2222 3000
|
||||
@@ -51,8 +35,7 @@ RUN apk --no-cache add \
|
||||
gettext \
|
||||
git \
|
||||
curl \
|
||||
gnupg \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
gnupg
|
||||
|
||||
RUN addgroup \
|
||||
-S -g 1000 \
|
||||
@@ -68,23 +51,26 @@ RUN addgroup \
|
||||
RUN mkdir -p /var/lib/gitea /etc/gitea
|
||||
RUN chown git:git /var/lib/gitea /etc/gitea
|
||||
|
||||
COPY --from=build-env /tmp/local /
|
||||
COPY docker/rootless /
|
||||
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/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
|
||||
RUN chmod 755 /usr/local/bin/docker-entrypoint.sh /usr/local/bin/docker-setup.sh /app/gitea/gitea /usr/local/bin/gitea /usr/local/bin/environment-to-ini
|
||||
RUN chmod 644 /etc/profile.d/gitea_bash_autocomplete.sh
|
||||
|
||||
# git:git
|
||||
#git:git
|
||||
USER 1000:1000
|
||||
ENV GITEA_WORK_DIR=/var/lib/gitea
|
||||
ENV GITEA_CUSTOM=/var/lib/gitea/custom
|
||||
ENV GITEA_TEMP=/tmp/gitea
|
||||
ENV TMPDIR=/tmp/gitea
|
||||
ENV GITEA_WORK_DIR /var/lib/gitea
|
||||
ENV GITEA_CUSTOM /var/lib/gitea/custom
|
||||
ENV GITEA_TEMP /tmp/gitea
|
||||
ENV TMPDIR /tmp/gitea
|
||||
|
||||
# TODO add to docs the ability to define the ini to load (useful to test and revert a config)
|
||||
ENV GITEA_APP_INI=/etc/gitea/app.ini
|
||||
ENV HOME="/var/lib/gitea/git"
|
||||
#TODO add to docs the ability to define the ini to load (useful to test and revert a config)
|
||||
ENV GITEA_APP_INI /etc/gitea/app.ini
|
||||
ENV HOME "/var/lib/gitea/git"
|
||||
VOLUME ["/var/lib/gitea", "/etc/gitea"]
|
||||
WORKDIR /var/lib/gitea
|
||||
|
||||
ENTRYPOINT ["/usr/bin/dumb-init", "--", "/usr/local/bin/docker-entrypoint.sh"]
|
||||
CMD []
|
||||
|
||||
|
||||
@@ -57,7 +57,3 @@ Punit Inani <punitinani1@gmail.com> (@puni9869)
|
||||
CaiCandong <1290147055@qq.com> (@caicandong)
|
||||
Rui Chen <rui@chenrui.dev> (@chenrui333)
|
||||
Nanguan Lin <nanguanlin6@gmail.com> (@lng2020)
|
||||
kerwin612 <kerwin612@qq.com> (@kerwin612)
|
||||
Gary Wang <git@blumia.net> (@BLumia)
|
||||
Tim-Niclas Oelschläger <zokki.softwareschmiede@gmail.com> (@zokkis)
|
||||
Yu Liu <1240335630@qq.com> (@HEREYUA)
|
||||
|
||||
203
Makefile
203
Makefile
@@ -23,37 +23,36 @@ SHASUM ?= shasum -a 256
|
||||
HAS_GO := $(shell hash $(GO) > /dev/null 2>&1 && echo yes)
|
||||
COMMA := ,
|
||||
|
||||
XGO_VERSION := go-1.22.x
|
||||
XGO_VERSION := go-1.21.x
|
||||
|
||||
AIR_PACKAGE ?= github.com/air-verse/air@v1
|
||||
AIR_PACKAGE ?= github.com/cosmtrek/air@v1.44.0
|
||||
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/cmd/editorconfig-checker@2.7.0
|
||||
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.6.0
|
||||
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.57.2
|
||||
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.5.0
|
||||
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.54.1
|
||||
GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.11
|
||||
MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.5.1
|
||||
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@db51e79a0e37c572d8b59ae0c58bf2bbbbe53285
|
||||
MISSPELL_PACKAGE ?= github.com/client9/misspell/cmd/misspell@v0.3.4
|
||||
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.30.5
|
||||
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
|
||||
GO_LICENSES_PACKAGE ?= github.com/google/go-licenses@v1
|
||||
GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@v1
|
||||
ACTIONLINT_PACKAGE ?= github.com/rhysd/actionlint/cmd/actionlint@v1
|
||||
GO_LICENSES_PACKAGE ?= github.com/google/go-licenses@v1.6.0
|
||||
GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@v1.0.1
|
||||
ACTIONLINT_PACKAGE ?= github.com/rhysd/actionlint/cmd/actionlint@v1.6.25
|
||||
|
||||
DOCKER_IMAGE ?= gitea/gitea
|
||||
DOCKER_TAG ?= latest
|
||||
DOCKER_REF := $(DOCKER_IMAGE):$(DOCKER_TAG)
|
||||
|
||||
ifeq ($(HAS_GO), yes)
|
||||
GOPATH ?= $(shell $(GO) env GOPATH)
|
||||
export PATH := $(GOPATH)/bin:$(PATH)
|
||||
|
||||
CGO_EXTRA_CFLAGS := -DSQLITE_MAX_VARIABLE_NUMBER=32766
|
||||
CGO_CFLAGS ?= $(shell $(GO) env CGO_CFLAGS) $(CGO_EXTRA_CFLAGS)
|
||||
endif
|
||||
|
||||
ifeq ($(GOOS),windows)
|
||||
IS_WINDOWS := yes
|
||||
else ifeq ($(patsubst Windows%,Windows,$(OS)),Windows)
|
||||
ifeq ($(GOOS),)
|
||||
IS_WINDOWS := yes
|
||||
endif
|
||||
endif
|
||||
ifeq ($(IS_WINDOWS),yes)
|
||||
ifeq ($(OS), Windows_NT)
|
||||
GOFLAGS := -v -buildmode=exe
|
||||
EXECUTABLE ?= gitea.exe
|
||||
else ifeq ($(OS), Windows)
|
||||
GOFLAGS := -v -buildmode=exe
|
||||
EXECUTABLE ?= gitea.exe
|
||||
else
|
||||
@@ -88,7 +87,7 @@ ifneq ($(GITHUB_REF_TYPE),branch)
|
||||
GITEA_VERSION ?= $(VERSION)
|
||||
else
|
||||
ifneq ($(GITHUB_REF_NAME),)
|
||||
VERSION ?= $(subst release/v,,$(GITHUB_REF_NAME))-nightly
|
||||
VERSION ?= $(subst release/v,,$(GITHUB_REF_NAME))
|
||||
else
|
||||
VERSION ?= main
|
||||
endif
|
||||
@@ -110,15 +109,15 @@ LDFLAGS := $(LDFLAGS) -X "main.MakeVersion=$(MAKE_VERSION)" -X "main.Version=$(G
|
||||
|
||||
LINUX_ARCHS ?= linux/amd64,linux/386,linux/arm-5,linux/arm-6,linux/arm64
|
||||
|
||||
GO_PACKAGES ?= $(filter-out code.gitea.io/gitea/tests/integration/migration-test code.gitea.io/gitea/tests code.gitea.io/gitea/tests/integration code.gitea.io/gitea/tests/e2e,$(shell $(GO) list ./... | grep -v /vendor/))
|
||||
GO_TEST_PACKAGES ?= $(filter-out $(shell $(GO) list code.gitea.io/gitea/models/migrations/...) code.gitea.io/gitea/tests/integration/migration-test code.gitea.io/gitea/tests code.gitea.io/gitea/tests/integration code.gitea.io/gitea/tests/e2e,$(shell $(GO) list ./... | grep -v /vendor/))
|
||||
MIGRATE_TEST_PACKAGES ?= $(shell $(GO) list code.gitea.io/gitea/models/migrations/...)
|
||||
|
||||
FOMANTIC_WORK_DIR := web_src/fomantic
|
||||
|
||||
WEBPACK_SOURCES := $(shell find web_src/js web_src/css -type f)
|
||||
WEBPACK_CONFIGS := webpack.config.js tailwind.config.js
|
||||
WEBPACK_CONFIGS := webpack.config.js
|
||||
WEBPACK_DEST := public/assets/js/index.js public/assets/css/index.css
|
||||
WEBPACK_DEST_ENTRIES := public/assets/js public/assets/css public/assets/fonts
|
||||
WEBPACK_DEST_ENTRIES := public/assets/js public/assets/css public/assets/fonts public/assets/img/webpack
|
||||
|
||||
BINDATA_DEST := modules/public/bindata.go modules/options/bindata.go modules/templates/bindata.go
|
||||
BINDATA_HASH := $(addsuffix .hash,$(BINDATA_DEST))
|
||||
@@ -136,18 +135,13 @@ TAGS ?=
|
||||
TAGS_SPLIT := $(subst $(COMMA), ,$(TAGS))
|
||||
TAGS_EVIDENCE := $(MAKE_EVIDENCE_DIR)/tags
|
||||
|
||||
TEST_TAGS ?= $(TAGS_SPLIT) sqlite sqlite_unlock_notify
|
||||
TEST_TAGS ?= sqlite sqlite_unlock_notify
|
||||
|
||||
TAR_EXCLUDES := .git data indexers queues log node_modules $(EXECUTABLE) $(FOMANTIC_WORK_DIR)/node_modules $(DIST) $(MAKE_EVIDENCE_DIR) $(AIR_TMP_DIR) $(GO_LICENSE_TMP_DIR)
|
||||
|
||||
GO_DIRS := build cmd models modules routers services tests
|
||||
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
|
||||
SPELLCHECK_FILES := $(GO_DIRS) $(WEB_DIRS) docs/content templates options/locale/locale_en-US.ini .github $(filter-out CHANGELOG.md, $(wildcard *.go *.js *.md *.yml *.yaml *.toml))
|
||||
EDITORCONFIG_FILES := templates .github/workflows options/locale/locale_en-US.ini
|
||||
|
||||
GO_SOURCES := $(wildcard *.go)
|
||||
GO_SOURCES += $(shell find $(GO_DIRS) -type f -name "*.go" ! -path modules/options/bindata.go ! -path modules/public/bindata.go ! -path modules/templates/bindata.go)
|
||||
GO_SOURCES += $(GENERATED_GO_DEST)
|
||||
@@ -164,8 +158,8 @@ ifdef DEPS_PLAYWRIGHT
|
||||
endif
|
||||
|
||||
SWAGGER_SPEC := templates/swagger/v1_json.tmpl
|
||||
SWAGGER_SPEC_S_TMPL := s|"basePath": *"/api/v1"|"basePath": "{{AppSubUrl \| JSEscape}}/api/v1"|g
|
||||
SWAGGER_SPEC_S_JSON := s|"basePath": *"{{AppSubUrl \| JSEscape}}/api/v1"|"basePath": "/api/v1"|g
|
||||
SWAGGER_SPEC_S_TMPL := s|"basePath": *"/api/v1"|"basePath": "{{AppSubUrl \| JSEscape \| Safe}}/api/v1"|g
|
||||
SWAGGER_SPEC_S_JSON := s|"basePath": *"{{AppSubUrl \| JSEscape \| Safe}}/api/v1"|"basePath": "/api/v1"|g
|
||||
SWAGGER_EXCLUDE := code.gitea.io/sdk
|
||||
SWAGGER_NEWLINE_COMMAND := -e '$$a\'
|
||||
|
||||
@@ -173,6 +167,10 @@ TEST_MYSQL_HOST ?= mysql:3306
|
||||
TEST_MYSQL_DBNAME ?= testgitea
|
||||
TEST_MYSQL_USERNAME ?= root
|
||||
TEST_MYSQL_PASSWORD ?=
|
||||
TEST_MYSQL8_HOST ?= mysql8:3306
|
||||
TEST_MYSQL8_DBNAME ?= testgitea
|
||||
TEST_MYSQL8_USERNAME ?= root
|
||||
TEST_MYSQL8_PASSWORD ?=
|
||||
TEST_PGSQL_HOST ?= pgsql:5432
|
||||
TEST_PGSQL_DBNAME ?= testgitea
|
||||
TEST_PGSQL_USERNAME ?= postgres
|
||||
@@ -221,8 +219,6 @@ help:
|
||||
@echo " - lint-swagger lint swagger files"
|
||||
@echo " - lint-templates lint template files"
|
||||
@echo " - lint-yaml lint yaml files"
|
||||
@echo " - lint-spell lint spelling"
|
||||
@echo " - lint-spell-fix lint spelling and fix issues"
|
||||
@echo " - checks run various consistency checks"
|
||||
@echo " - checks-frontend check frontend files"
|
||||
@echo " - checks-backend check backend files"
|
||||
@@ -282,19 +278,20 @@ clean-all: clean
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
$(GO) clean -i ./...
|
||||
rm -rf $(EXECUTABLE) $(DIST) $(BINDATA_DEST) $(BINDATA_HASH) \
|
||||
integrations*.test \
|
||||
e2e*.test \
|
||||
tests/integration/gitea-integration-* \
|
||||
tests/integration/indexers-* \
|
||||
tests/mysql.ini tests/pgsql.ini tests/mssql.ini man/ \
|
||||
tests/e2e/gitea-e2e-*/ \
|
||||
tests/e2e/indexers-*/ \
|
||||
tests/e2e/reports/ tests/e2e/test-artifacts/ tests/e2e/test-snapshots/
|
||||
tests/integration/gitea-integration-pgsql/ tests/integration/gitea-integration-mysql/ tests/integration/gitea-integration-mysql8/ tests/integration/gitea-integration-sqlite/ \
|
||||
tests/integration/gitea-integration-mssql/ tests/integration/indexers-mysql/ tests/integration/indexers-mysql8/ tests/integration/indexers-pgsql tests/integration/indexers-sqlite \
|
||||
tests/integration/indexers-mssql tests/mysql.ini tests/mysql8.ini tests/pgsql.ini tests/mssql.ini man/ \
|
||||
tests/e2e/gitea-e2e-pgsql/ tests/e2e/gitea-e2e-mysql/ tests/e2e/gitea-e2e-mysql8/ tests/e2e/gitea-e2e-sqlite/ \
|
||||
tests/e2e/gitea-e2e-mssql/ tests/e2e/indexers-mysql/ tests/e2e/indexers-mysql8/ tests/e2e/indexers-pgsql/ tests/e2e/indexers-sqlite/ \
|
||||
tests/e2e/indexers-mssql/ tests/e2e/reports/ tests/e2e/test-artifacts/ tests/e2e/test-snapshots/
|
||||
|
||||
.PHONY: fmt
|
||||
fmt:
|
||||
@GOFUMPT_PACKAGE=$(GOFUMPT_PACKAGE) $(GO) run build/code-batch-process.go gitea-fmt -w '{file-list}'
|
||||
GOFUMPT_PACKAGE=$(GOFUMPT_PACKAGE) $(GO) run build/code-batch-process.go gitea-fmt -w '{file-list}'
|
||||
$(eval TEMPLATES := $(shell find templates -type f -name '*.tmpl'))
|
||||
@# strip whitespace after '{{' or '(' and before '}}' or ')' unless there is only
|
||||
@# whitespace before it
|
||||
@@ -312,6 +309,10 @@ fmt-check: fmt
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
.PHONY: misspell-check
|
||||
misspell-check:
|
||||
go run $(MISSPELL_PACKAGE) -error $(GO_DIRS) $(WEB_DIRS)
|
||||
|
||||
.PHONY: $(TAGS_EVIDENCE)
|
||||
$(TAGS_EVIDENCE):
|
||||
@mkdir -p $(MAKE_EVIDENCE_DIR)
|
||||
@@ -351,13 +352,13 @@ checks: checks-frontend checks-backend
|
||||
checks-frontend: lockfile-check svg-check
|
||||
|
||||
.PHONY: checks-backend
|
||||
checks-backend: tidy-check swagger-check fmt-check swagger-validate security-check
|
||||
checks-backend: tidy-check swagger-check fmt-check misspell-check swagger-validate security-check
|
||||
|
||||
.PHONY: lint
|
||||
lint: lint-frontend lint-backend lint-spell
|
||||
lint: lint-frontend lint-backend
|
||||
|
||||
.PHONY: lint-fix
|
||||
lint-fix: lint-frontend-fix lint-backend-fix lint-spell-fix
|
||||
lint-fix: lint-frontend-fix lint-backend-fix
|
||||
|
||||
.PHONY: lint-frontend
|
||||
lint-frontend: lint-js lint-css
|
||||
@@ -373,19 +374,19 @@ lint-backend-fix: lint-go-fix lint-go-vet lint-editorconfig
|
||||
|
||||
.PHONY: lint-js
|
||||
lint-js: node_modules
|
||||
npx eslint --color --max-warnings=0 --ext js,vue $(ESLINT_FILES)
|
||||
npx eslint --color --max-warnings=0 --ext js,vue web_src/js build *.config.js tests/e2e
|
||||
|
||||
.PHONY: lint-js-fix
|
||||
lint-js-fix: node_modules
|
||||
npx eslint --color --max-warnings=0 --ext js,vue $(ESLINT_FILES) --fix
|
||||
npx eslint --color --max-warnings=0 --ext js,vue web_src/js build *.config.js tests/e2e --fix
|
||||
|
||||
.PHONY: lint-css
|
||||
lint-css: node_modules
|
||||
npx stylelint --color --max-warnings=0 $(STYLELINT_FILES)
|
||||
npx stylelint --color --max-warnings=0 web_src/css web_src/js/components/*.vue
|
||||
|
||||
.PHONY: lint-css-fix
|
||||
lint-css-fix: node_modules
|
||||
npx stylelint --color --max-warnings=0 $(STYLELINT_FILES) --fix
|
||||
npx stylelint --color --max-warnings=0 web_src/css web_src/js/components/*.vue --fix
|
||||
|
||||
.PHONY: lint-swagger
|
||||
lint-swagger: node_modules
|
||||
@@ -395,14 +396,6 @@ lint-swagger: node_modules
|
||||
lint-md: node_modules
|
||||
npx markdownlint docs *.md
|
||||
|
||||
.PHONY: lint-spell
|
||||
lint-spell:
|
||||
@go run $(MISSPELL_PACKAGE) -dict tools/misspellings.csv -error $(SPELLCHECK_FILES)
|
||||
|
||||
.PHONY: lint-spell-fix
|
||||
lint-spell-fix:
|
||||
@go run $(MISSPELL_PACKAGE) -dict tools/misspellings.csv -w $(SPELLCHECK_FILES)
|
||||
|
||||
.PHONY: lint-go
|
||||
lint-go:
|
||||
$(GO) run $(GOLANGCI_LINT_PACKAGE) run
|
||||
@@ -422,19 +415,18 @@ lint-go-windows:
|
||||
lint-go-vet:
|
||||
@echo "Running go vet..."
|
||||
@GOOS= GOARCH= $(GO) build code.gitea.io/gitea-vet
|
||||
@$(GO) vet -vettool=gitea-vet ./...
|
||||
@$(GO) vet -vettool=gitea-vet $(GO_PACKAGES)
|
||||
|
||||
.PHONY: lint-editorconfig
|
||||
lint-editorconfig:
|
||||
@$(GO) run $(EDITORCONFIG_CHECKER_PACKAGE) $(EDITORCONFIG_FILES)
|
||||
$(GO) run $(EDITORCONFIG_CHECKER_PACKAGE) templates .github/workflows
|
||||
|
||||
.PHONY: lint-actions
|
||||
lint-actions:
|
||||
$(GO) run $(ACTIONLINT_PACKAGE)
|
||||
|
||||
.PHONY: lint-templates
|
||||
lint-templates: .venv node_modules
|
||||
@node tools/lint-templates-svg.js
|
||||
lint-templates: .venv
|
||||
@poetry run djlint $(shell find templates -type f -iname '*.tmpl')
|
||||
|
||||
.PHONY: lint-yaml
|
||||
@@ -443,7 +435,7 @@ lint-yaml: .venv
|
||||
|
||||
.PHONY: watch
|
||||
watch:
|
||||
@bash tools/watch.sh
|
||||
@bash build/watch.sh
|
||||
|
||||
.PHONY: watch-frontend
|
||||
watch-frontend: node-check node_modules
|
||||
@@ -559,6 +551,27 @@ test-mysql\#%: integrations.mysql.test generate-ini-mysql
|
||||
.PHONY: test-mysql-migration
|
||||
test-mysql-migration: migrations.mysql.test migrations.individual.mysql.test
|
||||
|
||||
generate-ini-mysql8:
|
||||
sed -e 's|{{TEST_MYSQL8_HOST}}|${TEST_MYSQL8_HOST}|g' \
|
||||
-e 's|{{TEST_MYSQL8_DBNAME}}|${TEST_MYSQL8_DBNAME}|g' \
|
||||
-e 's|{{TEST_MYSQL8_USERNAME}}|${TEST_MYSQL8_USERNAME}|g' \
|
||||
-e 's|{{TEST_MYSQL8_PASSWORD}}|${TEST_MYSQL8_PASSWORD}|g' \
|
||||
-e 's|{{REPO_TEST_DIR}}|${REPO_TEST_DIR}|g' \
|
||||
-e 's|{{TEST_LOGGER}}|$(or $(TEST_LOGGER),test$(COMMA)file)|g' \
|
||||
-e 's|{{TEST_TYPE}}|$(or $(TEST_TYPE),integration)|g' \
|
||||
tests/mysql8.ini.tmpl > tests/mysql8.ini
|
||||
|
||||
.PHONY: test-mysql8
|
||||
test-mysql8: integrations.mysql8.test generate-ini-mysql8
|
||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql8.ini ./integrations.mysql8.test
|
||||
|
||||
.PHONY: test-mysql8\#%
|
||||
test-mysql8\#%: integrations.mysql8.test generate-ini-mysql8
|
||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql8.ini ./integrations.mysql8.test -test.run $(subst .,/,$*)
|
||||
|
||||
.PHONY: test-mysql8-migration
|
||||
test-mysql8-migration: migrations.mysql8.test migrations.individual.mysql8.test
|
||||
|
||||
generate-ini-pgsql:
|
||||
sed -e 's|{{TEST_PGSQL_HOST}}|${TEST_PGSQL_HOST}|g' \
|
||||
-e 's|{{TEST_PGSQL_DBNAME}}|${TEST_PGSQL_DBNAME}|g' \
|
||||
@@ -603,7 +616,8 @@ test-mssql\#%: integrations.mssql.test generate-ini-mssql
|
||||
test-mssql-migration: migrations.mssql.test migrations.individual.mssql.test
|
||||
|
||||
.PHONY: playwright
|
||||
playwright: deps-frontend
|
||||
playwright: $(PLAYWRIGHT_DIR)
|
||||
npm install --no-save @playwright/test
|
||||
npx playwright install $(PLAYWRIGHT_FLAGS)
|
||||
|
||||
.PHONY: test-e2e%
|
||||
@@ -630,6 +644,14 @@ 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/$*
|
||||
|
||||
.PHONY: test-e2e-mysql8
|
||||
test-e2e-mysql8: playwright e2e.mysql8.test generate-ini-mysql8
|
||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql8.ini ./e2e.mysql8.test
|
||||
|
||||
.PHONY: test-e2e-mysql8\#%
|
||||
test-e2e-mysql8\#%: playwright e2e.mysql8.test generate-ini-mysql8
|
||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql8.ini ./e2e.mysql8.test -test.run TestE2e/$*
|
||||
|
||||
.PHONY: test-e2e-pgsql
|
||||
test-e2e-pgsql: playwright e2e.pgsql.test generate-ini-pgsql
|
||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini ./e2e.pgsql.test
|
||||
@@ -673,6 +695,9 @@ integration-test-coverage-sqlite: integrations.cover.sqlite.test generate-ini-sq
|
||||
integrations.mysql.test: git-check $(GO_SOURCES)
|
||||
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -o integrations.mysql.test
|
||||
|
||||
integrations.mysql8.test: git-check $(GO_SOURCES)
|
||||
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -o integrations.mysql8.test
|
||||
|
||||
integrations.pgsql.test: git-check $(GO_SOURCES)
|
||||
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -o integrations.pgsql.test
|
||||
|
||||
@@ -693,6 +718,11 @@ migrations.mysql.test: $(GO_SOURCES) generate-ini-mysql
|
||||
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration/migration-test -o migrations.mysql.test
|
||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini ./migrations.mysql.test
|
||||
|
||||
.PHONY: migrations.mysql8.test
|
||||
migrations.mysql8.test: $(GO_SOURCES) generate-ini-mysql8
|
||||
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration/migration-test -o migrations.mysql8.test
|
||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql8.ini ./migrations.mysql8.test
|
||||
|
||||
.PHONY: migrations.pgsql.test
|
||||
migrations.pgsql.test: $(GO_SOURCES) generate-ini-pgsql
|
||||
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration/migration-test -o migrations.pgsql.test
|
||||
@@ -710,23 +740,36 @@ migrations.sqlite.test: $(GO_SOURCES) generate-ini-sqlite
|
||||
|
||||
.PHONY: migrations.individual.mysql.test
|
||||
migrations.individual.mysql.test: $(GO_SOURCES)
|
||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini $(GO) test $(GOTESTFLAGS) -tags='$(TEST_TAGS)' -p 1 $(MIGRATE_TEST_PACKAGES)
|
||||
for pkg in $(shell $(GO) list code.gitea.io/gitea/models/migrations/...); do \
|
||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg; \
|
||||
done
|
||||
|
||||
.PHONY: migrations.individual.sqlite.test\#%
|
||||
.PHONY: migrations.individual.mysql8.test
|
||||
migrations.individual.mysql8.test: $(GO_SOURCES)
|
||||
for pkg in $(shell $(GO) list code.gitea.io/gitea/models/migrations/...); do \
|
||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql8.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg; \
|
||||
done
|
||||
|
||||
.PHONY: migrations.individual.mysql8.test\#%
|
||||
migrations.individual.sqlite.test\#%: $(GO_SOURCES) generate-ini-sqlite
|
||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' code.gitea.io/gitea/models/migrations/$*
|
||||
|
||||
.PHONY: migrations.individual.pgsql.test
|
||||
migrations.individual.pgsql.test: $(GO_SOURCES)
|
||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini $(GO) test $(GOTESTFLAGS) -tags='$(TEST_TAGS)' -p 1 $(MIGRATE_TEST_PACKAGES)
|
||||
for pkg in $(shell $(GO) list code.gitea.io/gitea/models/migrations/...); do \
|
||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg; \
|
||||
done
|
||||
|
||||
.PHONY: migrations.individual.pgsql.test\#%
|
||||
migrations.individual.pgsql.test\#%: $(GO_SOURCES) generate-ini-pgsql
|
||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' code.gitea.io/gitea/models/migrations/$*
|
||||
|
||||
|
||||
.PHONY: migrations.individual.mssql.test
|
||||
migrations.individual.mssql.test: $(GO_SOURCES) generate-ini-mssql
|
||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini $(GO) test $(GOTESTFLAGS) -tags='$(TEST_TAGS)' -p 1 $(MIGRATE_TEST_PACKAGES)
|
||||
for pkg in $(shell $(GO) list code.gitea.io/gitea/models/migrations/...); do \
|
||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mssql.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg -test.failfast; \
|
||||
done
|
||||
|
||||
.PHONY: migrations.individual.mssql.test\#%
|
||||
migrations.individual.mssql.test\#%: $(GO_SOURCES) generate-ini-mssql
|
||||
@@ -734,7 +777,9 @@ migrations.individual.mssql.test\#%: $(GO_SOURCES) generate-ini-mssql
|
||||
|
||||
.PHONY: migrations.individual.sqlite.test
|
||||
migrations.individual.sqlite.test: $(GO_SOURCES) generate-ini-sqlite
|
||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini $(GO) test $(GOTESTFLAGS) -tags='$(TEST_TAGS)' -p 1 $(MIGRATE_TEST_PACKAGES)
|
||||
for pkg in $(shell $(GO) list code.gitea.io/gitea/models/migrations/...); do \
|
||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg; \
|
||||
done
|
||||
|
||||
.PHONY: migrations.individual.sqlite.test\#%
|
||||
migrations.individual.sqlite.test\#%: $(GO_SOURCES) generate-ini-sqlite
|
||||
@@ -743,6 +788,9 @@ migrations.individual.sqlite.test\#%: $(GO_SOURCES) generate-ini-sqlite
|
||||
e2e.mysql.test: $(GO_SOURCES)
|
||||
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/e2e -o e2e.mysql.test
|
||||
|
||||
e2e.mysql8.test: $(GO_SOURCES)
|
||||
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/e2e -o e2e.mysql8.test
|
||||
|
||||
e2e.pgsql.test: $(GO_SOURCES)
|
||||
$(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/e2e -o e2e.pgsql.test
|
||||
|
||||
@@ -778,7 +826,7 @@ generate-backend: $(TAGS_PREREQ) generate-go
|
||||
.PHONY: generate-go
|
||||
generate-go: $(TAGS_PREREQ)
|
||||
@echo "Running go generate..."
|
||||
@CC= GOOS= GOARCH= CGO_ENABLED=0 $(GO) generate -tags '$(TAGS)' ./...
|
||||
@CC= GOOS= GOARCH= $(GO) generate -tags '$(TAGS)' $(GO_PACKAGES)
|
||||
|
||||
.PHONY: security-check
|
||||
security-check:
|
||||
@@ -838,6 +886,10 @@ release-sources: | $(DIST_DIRS)
|
||||
release-docs: | $(DIST_DIRS) docs
|
||||
tar -czf $(DIST)/release/gitea-docs-$(VERSION).tar.gz -C ./docs .
|
||||
|
||||
.PHONY: docs
|
||||
docs:
|
||||
cd docs; bash scripts/trans-copy.sh;
|
||||
|
||||
.PHONY: deps
|
||||
deps: deps-frontend deps-backend deps-tools deps-py
|
||||
|
||||
@@ -870,7 +922,7 @@ node_modules: package-lock.json
|
||||
@touch node_modules
|
||||
|
||||
.venv: poetry.lock
|
||||
poetry install --no-root
|
||||
poetry install
|
||||
@touch .venv
|
||||
|
||||
.PHONY: update
|
||||
@@ -887,7 +939,7 @@ update-js: node-check | node_modules
|
||||
update-py: node-check | node_modules
|
||||
npx updates -u -f pyproject.toml
|
||||
rm -rf .venv poetry.lock
|
||||
poetry install --no-root
|
||||
poetry install
|
||||
@touch .venv
|
||||
|
||||
.PHONY: fomantic
|
||||
@@ -896,7 +948,6 @@ fomantic:
|
||||
cd $(FOMANTIC_WORK_DIR) && npm install --no-save
|
||||
cp -f $(FOMANTIC_WORK_DIR)/theme.config.less $(FOMANTIC_WORK_DIR)/node_modules/fomantic-ui/src/theme.config
|
||||
cp -rf $(FOMANTIC_WORK_DIR)/_site $(FOMANTIC_WORK_DIR)/node_modules/fomantic-ui/src/
|
||||
$(SED_INPLACE) -e 's/ overrideBrowserslist\r/ overrideBrowserslist: ["defaults"]\r/g' $(FOMANTIC_WORK_DIR)/node_modules/fomantic-ui/tasks/config/tasks.js
|
||||
cd $(FOMANTIC_WORK_DIR) && npx gulp -f node_modules/fomantic-ui/gulpfile.js build
|
||||
# fomantic uses "touchstart" as click event for some browsers, it's not ideal, so we force fomantic to always use "click" as click event
|
||||
$(SED_INPLACE) -e 's/clickEvent[ \t]*=/clickEvent = "click", unstableClickEvent =/g' $(FOMANTIC_WORK_DIR)/build/semantic.js
|
||||
@@ -908,15 +959,14 @@ webpack: $(WEBPACK_DEST)
|
||||
|
||||
$(WEBPACK_DEST): $(WEBPACK_SOURCES) $(WEBPACK_CONFIGS) package-lock.json
|
||||
@$(MAKE) -s node-check node_modules
|
||||
@rm -rf $(WEBPACK_DEST_ENTRIES)
|
||||
@echo "Running webpack..."
|
||||
@BROWSERSLIST_IGNORE_OLD_DATA=true npx webpack
|
||||
rm -rf $(WEBPACK_DEST_ENTRIES)
|
||||
npx webpack
|
||||
@touch $(WEBPACK_DEST)
|
||||
|
||||
.PHONY: svg
|
||||
svg: node-check | node_modules
|
||||
rm -rf $(SVG_DEST_DIR)
|
||||
node tools/generate-svg.js
|
||||
node build/generate-svg.js
|
||||
|
||||
.PHONY: svg-check
|
||||
svg-check: svg
|
||||
@@ -959,8 +1009,8 @@ generate-gitignore:
|
||||
|
||||
.PHONY: generate-images
|
||||
generate-images: | node_modules
|
||||
npm install --no-save fabric@6.0.0-beta20 imagemin-zopfli@7
|
||||
node tools/generate-images.js $(TAGS)
|
||||
npm install --no-save --no-package-lock fabric@5 imagemin-zopfli@7
|
||||
node build/generate-images.js $(TAGS)
|
||||
|
||||
.PHONY: generate-manpage
|
||||
generate-manpage:
|
||||
@@ -977,8 +1027,3 @@ docker:
|
||||
|
||||
# This endif closes the if at the top of the file
|
||||
endif
|
||||
|
||||
# Disable parallel execution because it would break some targets that don't
|
||||
# specify exact dependencies like 'backend' which does currently not depend
|
||||
# on 'frontend' to enable Node.js-less builds from source tarballs.
|
||||
.NOTPARALLEL:
|
||||
|
||||
93
README.md
93
README.md
@@ -1,18 +1,58 @@
|
||||
# Gitea
|
||||
<p align="center">
|
||||
<a href="https://gitea.io/">
|
||||
<img alt="Gitea" src="https://raw.githubusercontent.com/go-gitea/gitea/main/public/assets/img/gitea.svg" width="220"/>
|
||||
</a>
|
||||
</p>
|
||||
<h1 align="center">Gitea - Git with a cup of tea</h1>
|
||||
|
||||
[](https://github.com/go-gitea/gitea/actions/workflows/release-nightly.yml?query=branch%3Amain "Release Nightly")
|
||||
[](https://discord.gg/Gitea "Join the Discord chat at https://discord.gg/Gitea")
|
||||
[](https://goreportcard.com/report/code.gitea.io/gitea "Go Report Card")
|
||||
[](https://pkg.go.dev/code.gitea.io/gitea "GoDoc")
|
||||
[](https://github.com/go-gitea/gitea/releases/latest "GitHub release")
|
||||
[](https://www.codetriage.com/go-gitea/gitea "Help Contribute to Open Source")
|
||||
[](https://opencollective.com/gitea "Become a backer/sponsor of gitea")
|
||||
[](https://opensource.org/licenses/MIT "License: MIT")
|
||||
[](https://gitpod.io/#https://github.com/go-gitea/gitea)
|
||||
[](https://crowdin.com/project/gitea "Crowdin")
|
||||
[](https://www.tickgit.com/browse?repo=github.com/go-gitea/gitea&branch=main "TODOs")
|
||||
<p align="center">
|
||||
<a href="https://drone.gitea.io/go-gitea/gitea" title="Build Status">
|
||||
<img src="https://drone.gitea.io/api/badges/go-gitea/gitea/status.svg?ref=refs/heads/main">
|
||||
</a>
|
||||
<a href="https://discord.gg/Gitea" title="Join the Discord chat at https://discord.gg/Gitea">
|
||||
<img src="https://img.shields.io/discord/322538954119184384.svg">
|
||||
</a>
|
||||
<a href="https://app.codecov.io/gh/go-gitea/gitea" title="Codecov">
|
||||
<img src="https://codecov.io/gh/go-gitea/gitea/branch/main/graph/badge.svg">
|
||||
</a>
|
||||
<a href="https://goreportcard.com/report/code.gitea.io/gitea" title="Go Report Card">
|
||||
<img src="https://goreportcard.com/badge/code.gitea.io/gitea">
|
||||
</a>
|
||||
<a href="https://pkg.go.dev/code.gitea.io/gitea" title="GoDoc">
|
||||
<img src="https://pkg.go.dev/badge/code.gitea.io/gitea?status.svg">
|
||||
</a>
|
||||
<a href="https://github.com/go-gitea/gitea/releases/latest" title="GitHub release">
|
||||
<img src="https://img.shields.io/github/release/go-gitea/gitea.svg">
|
||||
</a>
|
||||
<a href="https://www.codetriage.com/go-gitea/gitea" title="Help Contribute to Open Source">
|
||||
<img src="https://www.codetriage.com/go-gitea/gitea/badges/users.svg">
|
||||
</a>
|
||||
<a href="https://opencollective.com/gitea" title="Become a backer/sponsor of gitea">
|
||||
<img src="https://opencollective.com/gitea/tiers/backers/badge.svg?label=backers&color=brightgreen">
|
||||
</a>
|
||||
<a href="https://opensource.org/licenses/MIT" title="License: MIT">
|
||||
<img src="https://img.shields.io/badge/License-MIT-blue.svg">
|
||||
</a>
|
||||
<a href="https://gitpod.io/#https://github.com/go-gitea/gitea">
|
||||
<img
|
||||
src="https://img.shields.io/badge/Contribute%20with-Gitpod-908a85?logo=gitpod"
|
||||
alt="Contribute with Gitpod"
|
||||
/>
|
||||
</a>
|
||||
<a href="https://crowdin.com/project/gitea" title="Crowdin">
|
||||
<img src="https://badges.crowdin.net/gitea/localized.svg">
|
||||
</a>
|
||||
<a href="https://www.tickgit.com/browse?repo=github.com/go-gitea/gitea&branch=main" title="TODOs">
|
||||
<img src="https://badgen.net/https/api.tickgit.com/badgen/github.com/go-gitea/gitea/main">
|
||||
</a>
|
||||
<a href="https://app.bountysource.com/teams/gitea" title="Bountysource">
|
||||
<img src="https://img.shields.io/bountysource/team/gitea/activity">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
[View this document in Chinese](./README_ZH.md)
|
||||
<p align="center">
|
||||
<a href="README_ZH.md">View this document in Chinese</a>
|
||||
</p>
|
||||
|
||||
## Purpose
|
||||
|
||||
@@ -22,16 +62,11 @@ painless way of setting up a self-hosted Git service.
|
||||
As Gitea is written in Go, it works across **all** the platforms and
|
||||
architectures that are supported by Go, including Linux, macOS, and
|
||||
Windows on x86, amd64, ARM and PowerPC architectures.
|
||||
You can try it out using [the online demo](https://try.gitea.io/).
|
||||
This project has been
|
||||
[forked](https://blog.gitea.com/welcome-to-gitea/) from
|
||||
[Gogs](https://gogs.io) since November of 2016, but a lot has changed.
|
||||
|
||||
For online demonstrations, you can visit [demo.gitea.com](https://demo.gitea.com).
|
||||
|
||||
For accessing free Gitea service (with a limited number of repositories), you can visit [gitea.com](https://gitea.com/user/login).
|
||||
|
||||
To quickly deploy your own dedicated Gitea instance on Gitea Cloud, you can start a free trial at [cloud.gitea.com](https://cloud.gitea.com).
|
||||
|
||||
## Building
|
||||
|
||||
From the root of the source tree, run:
|
||||
@@ -49,23 +84,25 @@ The `build` target is split into two sub-targets:
|
||||
|
||||
Internet connectivity is required to download the go and npm modules. When building from the official source tarballs which include pre-built frontend files, the `frontend` target will not be triggered, making it possible to build without Node.js.
|
||||
|
||||
Parallelism (`make -j <num>`) is not supported.
|
||||
|
||||
More info: https://docs.gitea.com/installation/install-from-source
|
||||
|
||||
## Using
|
||||
|
||||
./gitea web
|
||||
|
||||
> [!NOTE]
|
||||
> If you're interested in using our APIs, we have experimental support with [documentation](https://docs.gitea.com/api).
|
||||
NOTE: If you're interested in using our APIs, we have experimental
|
||||
support with [documentation](https://try.gitea.io/api/swagger).
|
||||
|
||||
## Contributing
|
||||
|
||||
Expected workflow is: Fork -> Patch -> Push -> Pull Request
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> 1. **YOU MUST READ THE [CONTRIBUTORS GUIDE](CONTRIBUTING.md) BEFORE STARTING TO WORK ON A PULL REQUEST.**
|
||||
> 2. If you have found a vulnerability in the project, please write privately to **security@gitea.io**. Thanks!
|
||||
NOTES:
|
||||
|
||||
1. **YOU MUST READ THE [CONTRIBUTORS GUIDE](CONTRIBUTING.md) BEFORE STARTING TO WORK ON A PULL REQUEST.**
|
||||
2. If you have found a vulnerability in the project, please write privately to **security@gitea.io**. Thanks!
|
||||
|
||||
## Translating
|
||||
|
||||
@@ -80,7 +117,7 @@ https://docs.gitea.com/contributing/localization
|
||||
## Further information
|
||||
|
||||
For more information and instructions about how to install Gitea, please look at our [documentation](https://docs.gitea.com/).
|
||||
If you have questions that are not covered by the documentation, you can get in contact with us on our [Discord server](https://discord.gg/Gitea) or create a post in the [discourse forum](https://forum.gitea.com/).
|
||||
If you have questions that are not covered by the documentation, you can get in contact with us on our [Discord server](https://discord.gg/Gitea) or create a post in the [discourse forum](https://discourse.gitea.io/).
|
||||
|
||||
We maintain a list of Gitea-related projects at [gitea/awesome-gitea](https://gitea.com/gitea/awesome-gitea).
|
||||
|
||||
@@ -136,5 +173,5 @@ Looking for an overview of the interface? Check it out!
|
||||
||||
|
||||
|:---:|:---:|:---:|
|
||||
||||
|
||||
||||
|
||||
||||
|
||||
|||
|
||||
|||
|
||||
|
||||
76
README_ZH.md
76
README_ZH.md
@@ -1,28 +1,64 @@
|
||||
# Gitea
|
||||
<p align="center">
|
||||
<a href="https://gitea.io/">
|
||||
<img alt="Gitea" src="https://raw.githubusercontent.com/go-gitea/gitea/main/public/assets/img/gitea.svg" width="220"/>
|
||||
</a>
|
||||
</p>
|
||||
<h1 align="center">Gitea - Git with a cup of tea</h1>
|
||||
|
||||
[](https://github.com/go-gitea/gitea/actions/workflows/release-nightly.yml?query=branch%3Amain "Release Nightly")
|
||||
[](https://discord.gg/Gitea "Join the Discord chat at https://discord.gg/Gitea")
|
||||
[](https://goreportcard.com/report/code.gitea.io/gitea "Go Report Card")
|
||||
[](https://pkg.go.dev/code.gitea.io/gitea "GoDoc")
|
||||
[](https://github.com/go-gitea/gitea/releases/latest "GitHub release")
|
||||
[](https://www.codetriage.com/go-gitea/gitea "Help Contribute to Open Source")
|
||||
[](https://opencollective.com/gitea "Become a backer/sponsor of gitea")
|
||||
[](https://opensource.org/licenses/MIT "License: MIT")
|
||||
[](https://gitpod.io/#https://github.com/go-gitea/gitea)
|
||||
[](https://crowdin.com/project/gitea "Crowdin")
|
||||
[](https://www.tickgit.com/browse?repo=github.com/go-gitea/gitea&branch=main "TODOs")
|
||||
<p align="center">
|
||||
<a href="https://drone.gitea.io/go-gitea/gitea" title="Build Status">
|
||||
<img src="https://drone.gitea.io/api/badges/go-gitea/gitea/status.svg?ref=refs/heads/main">
|
||||
</a>
|
||||
<a href="https://discord.gg/Gitea" title="Join the Discord chat at https://discord.gg/Gitea">
|
||||
<img src="https://img.shields.io/discord/322538954119184384.svg">
|
||||
</a>
|
||||
<a href="https://app.codecov.io/gh/go-gitea/gitea" title="Codecov">
|
||||
<img src="https://codecov.io/gh/go-gitea/gitea/branch/main/graph/badge.svg">
|
||||
</a>
|
||||
<a href="https://goreportcard.com/report/code.gitea.io/gitea" title="Go Report Card">
|
||||
<img src="https://goreportcard.com/badge/code.gitea.io/gitea">
|
||||
</a>
|
||||
<a href="https://pkg.go.dev/code.gitea.io/gitea" title="GoDoc">
|
||||
<img src="https://pkg.go.dev/badge/code.gitea.io/gitea?status.svg">
|
||||
</a>
|
||||
<a href="https://github.com/go-gitea/gitea/releases/latest" title="GitHub release">
|
||||
<img src="https://img.shields.io/github/release/go-gitea/gitea.svg">
|
||||
</a>
|
||||
<a href="https://www.codetriage.com/go-gitea/gitea" title="Help Contribute to Open Source">
|
||||
<img src="https://www.codetriage.com/go-gitea/gitea/badges/users.svg">
|
||||
</a>
|
||||
<a href="https://opencollective.com/gitea" title="Become a backer/sponsor of gitea">
|
||||
<img src="https://opencollective.com/gitea/tiers/backers/badge.svg?label=backers&color=brightgreen">
|
||||
</a>
|
||||
<a href="https://opensource.org/licenses/MIT" title="License: MIT">
|
||||
<img src="https://img.shields.io/badge/License-MIT-blue.svg">
|
||||
</a>
|
||||
<a href="https://gitpod.io/#https://github.com/go-gitea/gitea">
|
||||
<img
|
||||
src="https://img.shields.io/badge/Contribute%20with-Gitpod-908a85?logo=gitpod"
|
||||
alt="Contribute with Gitpod"
|
||||
/>
|
||||
</a>
|
||||
<a href="https://crowdin.com/project/gitea" title="Crowdin">
|
||||
<img src="https://badges.crowdin.net/gitea/localized.svg">
|
||||
</a>
|
||||
<a href="https://www.tickgit.com/browse?repo=github.com/go-gitea/gitea&branch=main" title="TODOs">
|
||||
<img src="https://badgen.net/https/api.tickgit.com/badgen/github.com/go-gitea/gitea/main">
|
||||
</a>
|
||||
<a href="https://app.bountysource.com/teams/gitea" title="Bountysource">
|
||||
<img src="https://img.shields.io/bountysource/team/gitea/activity">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
[View this document in English](./README.md)
|
||||
<p align="center">
|
||||
<a href="README.md">View this document in English</a>
|
||||
</p>
|
||||
|
||||
## 目标
|
||||
|
||||
Gitea 的首要目标是创建一个极易安装,运行非常快速,安装和使用体验良好的自建 Git 服务。我们采用 Go 作为后端语言,这使我们只要生成一个可执行程序即可。并且他还支持跨平台,支持 Linux, macOS 和 Windows 以及各种架构,除了 x86,amd64,还包括 ARM 和 PowerPC。
|
||||
|
||||
如果你想试用在线演示和报告问题,请访问 [demo.gitea.com](https://demo.gitea.com/)。
|
||||
|
||||
如果你想使用免费的 Gitea 服务(有仓库数量限制),请访问 [gitea.com](https://gitea.com/user/login)。
|
||||
|
||||
如果你想在 Gitea Cloud 上快速部署你自己独享的 Gitea 实例,请访问 [cloud.gitea.com](https://cloud.gitea.com) 开始免费试用。
|
||||
如果您想试用一下,请访问 [在线Demo](https://try.gitea.io/)!
|
||||
|
||||
## 提示
|
||||
|
||||
@@ -58,5 +94,5 @@ Fork -> Patch -> Push -> Pull Request
|
||||
||||
|
||||
|:---:|:---:|:---:|
|
||||
||||
|
||||
||||
|
||||
||||
|
||||
|||
|
||||
|||
|
||||
|
||||
@@ -12,7 +12,7 @@ Please **DO NOT** file a public issue, instead send your report privately to `se
|
||||
|
||||
## Protecting Security Information
|
||||
|
||||
Due to the sensitive nature of security information, you can use the below GPG public key to encrypt your mail body.
|
||||
Due to the sensitive nature of security information, you can use below GPG public key encrypt your mail body.
|
||||
|
||||
The PGP key is valid until June 24, 2024.
|
||||
|
||||
|
||||
105
assets/go-licenses.json
generated
105
assets/go-licenses.json
generated
File diff suppressed because one or more lines are too long
@@ -69,7 +69,6 @@ func newFileCollector(fileFilter string, batchSize int) (*fileCollector, error)
|
||||
co.includePatterns = append(co.includePatterns, regexp.MustCompile(`.*\.go$`))
|
||||
|
||||
co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`.*\bbindata\.go$`))
|
||||
co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`\.pb\.go$`))
|
||||
co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`tests/gitea-repositories-meta`))
|
||||
co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`tests/integration/migration-test`))
|
||||
co.excludePatterns = append(co.excludePatterns, regexp.MustCompile(`modules/git/tests`))
|
||||
@@ -204,6 +203,17 @@ Example:
|
||||
`, "file-batch-exec")
|
||||
}
|
||||
|
||||
func getGoVersion() string {
|
||||
goModFile, err := os.ReadFile("go.mod")
|
||||
if err != nil {
|
||||
log.Fatalf(`Faild to read "go.mod": %v`, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
goModVersionRegex := regexp.MustCompile(`go \d+\.\d+`)
|
||||
goModVersionLine := goModVersionRegex.Find(goModFile)
|
||||
return string(goModVersionLine[3:])
|
||||
}
|
||||
|
||||
func newFileCollectorFromMainOptions(mainOptions map[string]string) (fc *fileCollector, err error) {
|
||||
fileFilter := mainOptions["file-filter"]
|
||||
if fileFilter == "" {
|
||||
@@ -268,8 +278,7 @@ func main() {
|
||||
log.Print("the -d option is not supported by gitea-fmt")
|
||||
}
|
||||
cmdErrors = append(cmdErrors, giteaFormatGoImports(files, containsString(subArgs, "-w")))
|
||||
cmdErrors = append(cmdErrors, passThroughCmd("gofmt", append([]string{"-w", "-r", "interface{} -> any"}, substArgs...)))
|
||||
cmdErrors = append(cmdErrors, passThroughCmd("go", append([]string{"run", os.Getenv("GOFUMPT_PACKAGE"), "-extra"}, substArgs...)))
|
||||
cmdErrors = append(cmdErrors, passThroughCmd("go", append([]string{"run", os.Getenv("GOFUMPT_PACKAGE"), "-extra", "-lang", getGoVersion()}, substArgs...)))
|
||||
default:
|
||||
log.Fatalf("unknown cmd: %s %v", subCmd, subArgs)
|
||||
}
|
||||
|
||||
@@ -1,13 +1,20 @@
|
||||
#!/usr/bin/env node
|
||||
import imageminZopfli from 'imagemin-zopfli'; // eslint-disable-line i/no-unresolved
|
||||
import {loadSVGFromString, Canvas, Rect, util} from 'fabric/node'; // eslint-disable-line i/no-unresolved
|
||||
import imageminZopfli from 'imagemin-zopfli';
|
||||
import {optimize} from 'svgo';
|
||||
import {fabric} from 'fabric';
|
||||
import {readFile, writeFile} from 'node:fs/promises';
|
||||
import {argv, exit} from 'node:process';
|
||||
|
||||
function doExit(err) {
|
||||
function exit(err) {
|
||||
if (err) console.error(err);
|
||||
exit(err ? 1 : 0);
|
||||
process.exit(err ? 1 : 0);
|
||||
}
|
||||
|
||||
function loadSvg(svg) {
|
||||
return new Promise((resolve) => {
|
||||
fabric.loadSVGFromString(svg, (objects, options) => {
|
||||
resolve({objects, options});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function generate(svg, path, {size, bg}) {
|
||||
@@ -20,7 +27,7 @@ async function generate(svg, path, {size, bg}) {
|
||||
'removeDimensions',
|
||||
{
|
||||
name: 'addAttributesToSVGElement',
|
||||
params: {attributes: [{width: size}, {height: size}]},
|
||||
params: {attributes: [{width: size}, {height: size}]}
|
||||
},
|
||||
],
|
||||
});
|
||||
@@ -28,14 +35,14 @@ async function generate(svg, path, {size, bg}) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {objects, options} = await loadSVGFromString(svg);
|
||||
const canvas = new Canvas();
|
||||
const {objects, options} = await loadSvg(svg);
|
||||
const canvas = new fabric.Canvas();
|
||||
canvas.setDimensions({width: size, height: size});
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.scale(options.width ? (size / options.width) : 1, options.height ? (size / options.height) : 1);
|
||||
|
||||
if (bg) {
|
||||
canvas.add(new Rect({
|
||||
canvas.add(new fabric.Rect({
|
||||
left: 0,
|
||||
top: 0,
|
||||
height: size * (1 / (size / options.height)),
|
||||
@@ -44,7 +51,7 @@ async function generate(svg, path, {size, bg}) {
|
||||
}));
|
||||
}
|
||||
|
||||
canvas.add(util.groupSVGElements(objects, options));
|
||||
canvas.add(fabric.util.groupSVGElements(objects, options));
|
||||
canvas.renderAll();
|
||||
|
||||
let png = Buffer.from([]);
|
||||
@@ -57,7 +64,7 @@ async function generate(svg, path, {size, bg}) {
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const gitea = argv.slice(2).includes('gitea');
|
||||
const gitea = process.argv.slice(2).includes('gitea');
|
||||
const logoSvg = await readFile(new URL('../assets/logo.svg', import.meta.url), 'utf8');
|
||||
const faviconSvg = await readFile(new URL('../assets/favicon.svg', import.meta.url), 'utf8');
|
||||
|
||||
@@ -72,8 +79,4 @@ async function main() {
|
||||
]);
|
||||
}
|
||||
|
||||
try {
|
||||
doExit(await main());
|
||||
} catch (err) {
|
||||
doExit(err);
|
||||
}
|
||||
main().then(exit).catch(exit);
|
||||
@@ -4,16 +4,15 @@ import {optimize} from 'svgo';
|
||||
import {parse} from 'node:path';
|
||||
import {readFile, writeFile, mkdir} from 'node:fs/promises';
|
||||
import {fileURLToPath} from 'node:url';
|
||||
import {exit} from 'node:process';
|
||||
|
||||
const glob = (pattern) => fastGlob.sync(pattern, {
|
||||
cwd: fileURLToPath(new URL('..', import.meta.url)),
|
||||
absolute: true,
|
||||
});
|
||||
|
||||
function doExit(err) {
|
||||
function exit(err) {
|
||||
if (err) console.error(err);
|
||||
exit(err ? 1 : 0);
|
||||
process.exit(err ? 1 : 0);
|
||||
}
|
||||
|
||||
async function processFile(file, {prefix, fullName} = {}) {
|
||||
@@ -39,8 +38,8 @@ async function processFile(file, {prefix, fullName} = {}) {
|
||||
attributes: [
|
||||
{'xmlns': 'http://www.w3.org/2000/svg'},
|
||||
{'width': '16'}, {'height': '16'}, {'aria-hidden': 'true'},
|
||||
],
|
||||
},
|
||||
]
|
||||
}
|
||||
},
|
||||
],
|
||||
});
|
||||
@@ -64,8 +63,4 @@ async function main() {
|
||||
]);
|
||||
}
|
||||
|
||||
try {
|
||||
doExit(await main());
|
||||
} catch (err) {
|
||||
doExit(err);
|
||||
}
|
||||
main().then(exit).catch(exit);
|
||||
@@ -15,8 +15,9 @@ import (
|
||||
var (
|
||||
// CmdActions represents the available actions sub-commands.
|
||||
CmdActions = &cli.Command{
|
||||
Name: "actions",
|
||||
Usage: "Manage Gitea Actions",
|
||||
Name: "actions",
|
||||
Usage: "",
|
||||
Description: "Commands for managing Gitea Actions",
|
||||
Subcommands: []*cli.Command{
|
||||
subcmdActionsGenRunnerToken,
|
||||
},
|
||||
@@ -50,6 +51,6 @@ func runGenerateActionsRunnerToken(c *cli.Context) error {
|
||||
if extra.HasError() {
|
||||
return handleCliResponseExtra(extra)
|
||||
}
|
||||
_, _ = fmt.Printf("%s\n", respText.Text)
|
||||
_, _ = fmt.Printf("%s\n", respText)
|
||||
return nil
|
||||
}
|
||||
|
||||
626
cmd/admin.go
626
cmd/admin.go
@@ -6,14 +6,26 @@ package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
|
||||
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/gitrepo"
|
||||
"code.gitea.io/gitea/modules/graceful"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
repo_module "code.gitea.io/gitea/modules/repository"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
auth_service "code.gitea.io/gitea/services/auth"
|
||||
"code.gitea.io/gitea/services/auth/source/oauth2"
|
||||
"code.gitea.io/gitea/services/auth/source/smtp"
|
||||
repo_service "code.gitea.io/gitea/services/repository"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
@@ -22,7 +34,7 @@ var (
|
||||
// CmdAdmin represents the available admin sub-command.
|
||||
CmdAdmin = &cli.Command{
|
||||
Name: "admin",
|
||||
Usage: "Perform common administrative operations",
|
||||
Usage: "Command line interface to perform common administrative operations",
|
||||
Subcommands: []*cli.Command{
|
||||
subcmdUser,
|
||||
subcmdRepoSyncReleases,
|
||||
@@ -47,16 +59,28 @@ var (
|
||||
},
|
||||
}
|
||||
|
||||
microcmdRegenHooks = &cli.Command{
|
||||
Name: "hooks",
|
||||
Usage: "Regenerate git-hooks",
|
||||
Action: runRegenerateHooks,
|
||||
}
|
||||
|
||||
microcmdRegenKeys = &cli.Command{
|
||||
Name: "keys",
|
||||
Usage: "Regenerate authorized_keys file",
|
||||
Action: runRegenerateKeys,
|
||||
}
|
||||
|
||||
subcmdAuth = &cli.Command{
|
||||
Name: "auth",
|
||||
Usage: "Modify external auth providers",
|
||||
Subcommands: []*cli.Command{
|
||||
microcmdAuthAddOauth,
|
||||
microcmdAuthUpdateOauth,
|
||||
microcmdAuthAddLdapBindDn,
|
||||
microcmdAuthUpdateLdapBindDn,
|
||||
microcmdAuthAddLdapSimpleAuth,
|
||||
microcmdAuthUpdateLdapSimpleAuth,
|
||||
cmdAuthAddLdapBindDn,
|
||||
cmdAuthUpdateLdapBindDn,
|
||||
cmdAuthAddLdapSimpleAuth,
|
||||
cmdAuthUpdateLdapSimpleAuth,
|
||||
microcmdAuthAddSMTP,
|
||||
microcmdAuthUpdateSMTP,
|
||||
microcmdAuthList,
|
||||
@@ -64,6 +88,170 @@ var (
|
||||
},
|
||||
}
|
||||
|
||||
microcmdAuthList = &cli.Command{
|
||||
Name: "list",
|
||||
Usage: "List auth sources",
|
||||
Action: runListAuth,
|
||||
Flags: []cli.Flag{
|
||||
&cli.IntFlag{
|
||||
Name: "min-width",
|
||||
Usage: "Minimal cell width including any padding for the formatted table",
|
||||
Value: 0,
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: "tab-width",
|
||||
Usage: "width of tab characters in formatted table (equivalent number of spaces)",
|
||||
Value: 8,
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: "padding",
|
||||
Usage: "padding added to a cell before computing its width",
|
||||
Value: 1,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "pad-char",
|
||||
Usage: `ASCII char used for padding if padchar == '\\t', the Writer will assume that the width of a '\\t' in the formatted output is tabwidth, and cells are left-aligned independent of align_left (for correct-looking results, tabwidth must correspond to the tab width in the viewer displaying the result)`,
|
||||
Value: "\t",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "vertical-bars",
|
||||
Usage: "Set to true to print vertical bars between columns",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
idFlag = &cli.Int64Flag{
|
||||
Name: "id",
|
||||
Usage: "ID of authentication source",
|
||||
}
|
||||
|
||||
microcmdAuthDelete = &cli.Command{
|
||||
Name: "delete",
|
||||
Usage: "Delete specific auth source",
|
||||
Flags: []cli.Flag{idFlag},
|
||||
Action: runDeleteAuth,
|
||||
}
|
||||
|
||||
oauthCLIFlags = []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "name",
|
||||
Value: "",
|
||||
Usage: "Application Name",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "provider",
|
||||
Value: "",
|
||||
Usage: "OAuth2 Provider",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "key",
|
||||
Value: "",
|
||||
Usage: "Client ID (Key)",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "secret",
|
||||
Value: "",
|
||||
Usage: "Client Secret",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "auto-discover-url",
|
||||
Value: "",
|
||||
Usage: "OpenID Connect Auto Discovery URL (only required when using OpenID Connect as provider)",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "use-custom-urls",
|
||||
Value: "false",
|
||||
Usage: "Use custom URLs for GitLab/GitHub OAuth endpoints",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "custom-tenant-id",
|
||||
Value: "",
|
||||
Usage: "Use custom Tenant ID for OAuth endpoints",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "custom-auth-url",
|
||||
Value: "",
|
||||
Usage: "Use a custom Authorization URL (option for GitLab/GitHub)",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "custom-token-url",
|
||||
Value: "",
|
||||
Usage: "Use a custom Token URL (option for GitLab/GitHub)",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "custom-profile-url",
|
||||
Value: "",
|
||||
Usage: "Use a custom Profile URL (option for GitLab/GitHub)",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "custom-email-url",
|
||||
Value: "",
|
||||
Usage: "Use a custom Email URL (option for GitHub)",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "icon-url",
|
||||
Value: "",
|
||||
Usage: "Custom icon URL for OAuth2 login source",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "skip-local-2fa",
|
||||
Usage: "Set to true to skip local 2fa for users authenticated by this source",
|
||||
},
|
||||
&cli.StringSliceFlag{
|
||||
Name: "scopes",
|
||||
Value: nil,
|
||||
Usage: "Scopes to request when to authenticate against this OAuth2 source",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "required-claim-name",
|
||||
Value: "",
|
||||
Usage: "Claim name that has to be set to allow users to login with this source",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "required-claim-value",
|
||||
Value: "",
|
||||
Usage: "Claim value that has to be set to allow users to login with this source",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "group-claim-name",
|
||||
Value: "",
|
||||
Usage: "Claim name providing group names for this source",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "admin-group",
|
||||
Value: "",
|
||||
Usage: "Group Claim value for administrator users",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "restricted-group",
|
||||
Value: "",
|
||||
Usage: "Group Claim value for restricted users",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "group-team-map",
|
||||
Value: "",
|
||||
Usage: "JSON mapping between groups and org teams",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "group-team-map-removal",
|
||||
Usage: "Activate automatic team membership removal depending on groups",
|
||||
},
|
||||
}
|
||||
|
||||
microcmdAuthUpdateOauth = &cli.Command{
|
||||
Name: "update-oauth",
|
||||
Usage: "Update existing Oauth authentication source",
|
||||
Action: runUpdateOauth,
|
||||
Flags: append(oauthCLIFlags[:1], append([]cli.Flag{idFlag}, oauthCLIFlags[1:]...)...),
|
||||
}
|
||||
|
||||
microcmdAuthAddOauth = &cli.Command{
|
||||
Name: "add-oauth",
|
||||
Usage: "Add new Oauth authentication source",
|
||||
Action: runAddOauth,
|
||||
Flags: oauthCLIFlags,
|
||||
}
|
||||
|
||||
subcmdSendMail = &cli.Command{
|
||||
Name: "sendmail",
|
||||
Usage: "Send a message to all users",
|
||||
@@ -87,9 +275,75 @@ var (
|
||||
},
|
||||
}
|
||||
|
||||
idFlag = &cli.Int64Flag{
|
||||
Name: "id",
|
||||
Usage: "ID of authentication source",
|
||||
smtpCLIFlags = []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "name",
|
||||
Value: "",
|
||||
Usage: "Application Name",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "auth-type",
|
||||
Value: "PLAIN",
|
||||
Usage: "SMTP Authentication Type (PLAIN/LOGIN/CRAM-MD5) default PLAIN",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "host",
|
||||
Value: "",
|
||||
Usage: "SMTP Host",
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: "port",
|
||||
Usage: "SMTP Port",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "force-smtps",
|
||||
Usage: "SMTPS is always used on port 465. Set this to force SMTPS on other ports.",
|
||||
Value: true,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "skip-verify",
|
||||
Usage: "Skip TLS verify.",
|
||||
Value: true,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "helo-hostname",
|
||||
Value: "",
|
||||
Usage: "Hostname sent with HELO. Leave blank to send current hostname",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "disable-helo",
|
||||
Usage: "Disable SMTP helo.",
|
||||
Value: true,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "allowed-domains",
|
||||
Value: "",
|
||||
Usage: "Leave empty to allow all domains. Separate multiple domains with a comma (',')",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "skip-local-2fa",
|
||||
Usage: "Skip 2FA to log on.",
|
||||
Value: true,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "active",
|
||||
Usage: "This Authentication Source is Activated.",
|
||||
Value: true,
|
||||
},
|
||||
}
|
||||
|
||||
microcmdAuthAddSMTP = &cli.Command{
|
||||
Name: "add-smtp",
|
||||
Usage: "Add new SMTP authentication source",
|
||||
Action: runAddSMTP,
|
||||
Flags: smtpCLIFlags,
|
||||
}
|
||||
|
||||
microcmdAuthUpdateSMTP = &cli.Command{
|
||||
Name: "update-smtp",
|
||||
Usage: "Update existing SMTP authentication source",
|
||||
Action: runUpdateSMTP,
|
||||
Flags: append(smtpCLIFlags[:1], append([]cli.Flag{idFlag}, smtpCLIFlags[1:]...)...),
|
||||
}
|
||||
)
|
||||
|
||||
@@ -123,7 +377,7 @@ func runRepoSyncReleases(_ *cli.Context) error {
|
||||
log.Trace("Processing next %d repos of %d", len(repos), count)
|
||||
for _, repo := range repos {
|
||||
log.Trace("Synchronizing repo %s with path %s", repo.FullName(), repo.RepoPath())
|
||||
gitRepo, err := gitrepo.OpenRepository(ctx, repo)
|
||||
gitRepo, err := git.OpenRepository(ctx, repo.RepoPath())
|
||||
if err != nil {
|
||||
log.Warn("OpenRepository: %v", err)
|
||||
continue
|
||||
@@ -158,11 +412,359 @@ func runRepoSyncReleases(_ *cli.Context) error {
|
||||
}
|
||||
|
||||
func getReleaseCount(ctx context.Context, id int64) (int64, error) {
|
||||
return db.Count[repo_model.Release](
|
||||
return repo_model.GetReleaseCountByRepoID(
|
||||
ctx,
|
||||
id,
|
||||
repo_model.FindReleasesOptions{
|
||||
RepoID: id,
|
||||
IncludeTags: true,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func runRegenerateHooks(_ *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return repo_service.SyncRepositoryHooks(graceful.GetManager().ShutdownContext())
|
||||
}
|
||||
|
||||
func runRegenerateKeys(_ *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return asymkey_model.RewriteAllPublicKeys(ctx)
|
||||
}
|
||||
|
||||
func parseOAuth2Config(c *cli.Context) *oauth2.Source {
|
||||
var customURLMapping *oauth2.CustomURLMapping
|
||||
if c.IsSet("use-custom-urls") {
|
||||
customURLMapping = &oauth2.CustomURLMapping{
|
||||
TokenURL: c.String("custom-token-url"),
|
||||
AuthURL: c.String("custom-auth-url"),
|
||||
ProfileURL: c.String("custom-profile-url"),
|
||||
EmailURL: c.String("custom-email-url"),
|
||||
Tenant: c.String("custom-tenant-id"),
|
||||
}
|
||||
} else {
|
||||
customURLMapping = nil
|
||||
}
|
||||
return &oauth2.Source{
|
||||
Provider: c.String("provider"),
|
||||
ClientID: c.String("key"),
|
||||
ClientSecret: c.String("secret"),
|
||||
OpenIDConnectAutoDiscoveryURL: c.String("auto-discover-url"),
|
||||
CustomURLMapping: customURLMapping,
|
||||
IconURL: c.String("icon-url"),
|
||||
SkipLocalTwoFA: c.Bool("skip-local-2fa"),
|
||||
Scopes: c.StringSlice("scopes"),
|
||||
RequiredClaimName: c.String("required-claim-name"),
|
||||
RequiredClaimValue: c.String("required-claim-value"),
|
||||
GroupClaimName: c.String("group-claim-name"),
|
||||
AdminGroup: c.String("admin-group"),
|
||||
RestrictedGroup: c.String("restricted-group"),
|
||||
GroupTeamMap: c.String("group-team-map"),
|
||||
GroupTeamMapRemoval: c.Bool("group-team-map-removal"),
|
||||
}
|
||||
}
|
||||
|
||||
func runAddOauth(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
config := parseOAuth2Config(c)
|
||||
if config.Provider == "openidConnect" {
|
||||
discoveryURL, err := url.Parse(config.OpenIDConnectAutoDiscoveryURL)
|
||||
if err != nil || (discoveryURL.Scheme != "http" && discoveryURL.Scheme != "https") {
|
||||
return fmt.Errorf("invalid Auto Discovery URL: %s (this must be a valid URL starting with http:// or https://)", config.OpenIDConnectAutoDiscoveryURL)
|
||||
}
|
||||
}
|
||||
|
||||
return auth_model.CreateSource(&auth_model.Source{
|
||||
Type: auth_model.OAuth2,
|
||||
Name: c.String("name"),
|
||||
IsActive: true,
|
||||
Cfg: config,
|
||||
})
|
||||
}
|
||||
|
||||
func runUpdateOauth(c *cli.Context) error {
|
||||
if !c.IsSet("id") {
|
||||
return fmt.Errorf("--id flag is missing")
|
||||
}
|
||||
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
source, err := auth_model.GetSourceByID(c.Int64("id"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
oAuth2Config := source.Cfg.(*oauth2.Source)
|
||||
|
||||
if c.IsSet("name") {
|
||||
source.Name = c.String("name")
|
||||
}
|
||||
|
||||
if c.IsSet("provider") {
|
||||
oAuth2Config.Provider = c.String("provider")
|
||||
}
|
||||
|
||||
if c.IsSet("key") {
|
||||
oAuth2Config.ClientID = c.String("key")
|
||||
}
|
||||
|
||||
if c.IsSet("secret") {
|
||||
oAuth2Config.ClientSecret = c.String("secret")
|
||||
}
|
||||
|
||||
if c.IsSet("auto-discover-url") {
|
||||
oAuth2Config.OpenIDConnectAutoDiscoveryURL = c.String("auto-discover-url")
|
||||
}
|
||||
|
||||
if c.IsSet("icon-url") {
|
||||
oAuth2Config.IconURL = c.String("icon-url")
|
||||
}
|
||||
|
||||
if c.IsSet("scopes") {
|
||||
oAuth2Config.Scopes = c.StringSlice("scopes")
|
||||
}
|
||||
|
||||
if c.IsSet("required-claim-name") {
|
||||
oAuth2Config.RequiredClaimName = c.String("required-claim-name")
|
||||
}
|
||||
if c.IsSet("required-claim-value") {
|
||||
oAuth2Config.RequiredClaimValue = c.String("required-claim-value")
|
||||
}
|
||||
|
||||
if c.IsSet("group-claim-name") {
|
||||
oAuth2Config.GroupClaimName = c.String("group-claim-name")
|
||||
}
|
||||
if c.IsSet("admin-group") {
|
||||
oAuth2Config.AdminGroup = c.String("admin-group")
|
||||
}
|
||||
if c.IsSet("restricted-group") {
|
||||
oAuth2Config.RestrictedGroup = c.String("restricted-group")
|
||||
}
|
||||
if c.IsSet("group-team-map") {
|
||||
oAuth2Config.GroupTeamMap = c.String("group-team-map")
|
||||
}
|
||||
if c.IsSet("group-team-map-removal") {
|
||||
oAuth2Config.GroupTeamMapRemoval = c.Bool("group-team-map-removal")
|
||||
}
|
||||
|
||||
// update custom URL mapping
|
||||
customURLMapping := &oauth2.CustomURLMapping{}
|
||||
|
||||
if oAuth2Config.CustomURLMapping != nil {
|
||||
customURLMapping.TokenURL = oAuth2Config.CustomURLMapping.TokenURL
|
||||
customURLMapping.AuthURL = oAuth2Config.CustomURLMapping.AuthURL
|
||||
customURLMapping.ProfileURL = oAuth2Config.CustomURLMapping.ProfileURL
|
||||
customURLMapping.EmailURL = oAuth2Config.CustomURLMapping.EmailURL
|
||||
customURLMapping.Tenant = oAuth2Config.CustomURLMapping.Tenant
|
||||
}
|
||||
if c.IsSet("use-custom-urls") && c.IsSet("custom-token-url") {
|
||||
customURLMapping.TokenURL = c.String("custom-token-url")
|
||||
}
|
||||
|
||||
if c.IsSet("use-custom-urls") && c.IsSet("custom-auth-url") {
|
||||
customURLMapping.AuthURL = c.String("custom-auth-url")
|
||||
}
|
||||
|
||||
if c.IsSet("use-custom-urls") && c.IsSet("custom-profile-url") {
|
||||
customURLMapping.ProfileURL = c.String("custom-profile-url")
|
||||
}
|
||||
|
||||
if c.IsSet("use-custom-urls") && c.IsSet("custom-email-url") {
|
||||
customURLMapping.EmailURL = c.String("custom-email-url")
|
||||
}
|
||||
|
||||
if c.IsSet("use-custom-urls") && c.IsSet("custom-tenant-id") {
|
||||
customURLMapping.Tenant = c.String("custom-tenant-id")
|
||||
}
|
||||
|
||||
oAuth2Config.CustomURLMapping = customURLMapping
|
||||
source.Cfg = oAuth2Config
|
||||
|
||||
return auth_model.UpdateSource(source)
|
||||
}
|
||||
|
||||
func parseSMTPConfig(c *cli.Context, conf *smtp.Source) error {
|
||||
if c.IsSet("auth-type") {
|
||||
conf.Auth = c.String("auth-type")
|
||||
validAuthTypes := []string{"PLAIN", "LOGIN", "CRAM-MD5"}
|
||||
if !util.SliceContainsString(validAuthTypes, strings.ToUpper(c.String("auth-type"))) {
|
||||
return errors.New("Auth must be one of PLAIN/LOGIN/CRAM-MD5")
|
||||
}
|
||||
conf.Auth = c.String("auth-type")
|
||||
}
|
||||
if c.IsSet("host") {
|
||||
conf.Host = c.String("host")
|
||||
}
|
||||
if c.IsSet("port") {
|
||||
conf.Port = c.Int("port")
|
||||
}
|
||||
if c.IsSet("allowed-domains") {
|
||||
conf.AllowedDomains = c.String("allowed-domains")
|
||||
}
|
||||
if c.IsSet("force-smtps") {
|
||||
conf.ForceSMTPS = c.Bool("force-smtps")
|
||||
}
|
||||
if c.IsSet("skip-verify") {
|
||||
conf.SkipVerify = c.Bool("skip-verify")
|
||||
}
|
||||
if c.IsSet("helo-hostname") {
|
||||
conf.HeloHostname = c.String("helo-hostname")
|
||||
}
|
||||
if c.IsSet("disable-helo") {
|
||||
conf.DisableHelo = c.Bool("disable-helo")
|
||||
}
|
||||
if c.IsSet("skip-local-2fa") {
|
||||
conf.SkipLocalTwoFA = c.Bool("skip-local-2fa")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func runAddSMTP(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !c.IsSet("name") || len(c.String("name")) == 0 {
|
||||
return errors.New("name must be set")
|
||||
}
|
||||
if !c.IsSet("host") || len(c.String("host")) == 0 {
|
||||
return errors.New("host must be set")
|
||||
}
|
||||
if !c.IsSet("port") {
|
||||
return errors.New("port must be set")
|
||||
}
|
||||
active := true
|
||||
if c.IsSet("active") {
|
||||
active = c.Bool("active")
|
||||
}
|
||||
|
||||
var smtpConfig smtp.Source
|
||||
if err := parseSMTPConfig(c, &smtpConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If not set default to PLAIN
|
||||
if len(smtpConfig.Auth) == 0 {
|
||||
smtpConfig.Auth = "PLAIN"
|
||||
}
|
||||
|
||||
return auth_model.CreateSource(&auth_model.Source{
|
||||
Type: auth_model.SMTP,
|
||||
Name: c.String("name"),
|
||||
IsActive: active,
|
||||
Cfg: &smtpConfig,
|
||||
})
|
||||
}
|
||||
|
||||
func runUpdateSMTP(c *cli.Context) error {
|
||||
if !c.IsSet("id") {
|
||||
return fmt.Errorf("--id flag is missing")
|
||||
}
|
||||
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
source, err := auth_model.GetSourceByID(c.Int64("id"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
smtpConfig := source.Cfg.(*smtp.Source)
|
||||
|
||||
if err := parseSMTPConfig(c, smtpConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if c.IsSet("name") {
|
||||
source.Name = c.String("name")
|
||||
}
|
||||
|
||||
if c.IsSet("active") {
|
||||
source.IsActive = c.Bool("active")
|
||||
}
|
||||
|
||||
source.Cfg = smtpConfig
|
||||
|
||||
return auth_model.UpdateSource(source)
|
||||
}
|
||||
|
||||
func runListAuth(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
authSources, err := auth_model.Sources()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
flags := tabwriter.AlignRight
|
||||
if c.Bool("vertical-bars") {
|
||||
flags |= tabwriter.Debug
|
||||
}
|
||||
|
||||
padChar := byte('\t')
|
||||
if len(c.String("pad-char")) > 0 {
|
||||
padChar = c.String("pad-char")[0]
|
||||
}
|
||||
|
||||
// loop through each source and print
|
||||
w := tabwriter.NewWriter(os.Stdout, c.Int("min-width"), c.Int("tab-width"), c.Int("padding"), padChar, flags)
|
||||
fmt.Fprintf(w, "ID\tName\tType\tEnabled\n")
|
||||
for _, source := range authSources {
|
||||
fmt.Fprintf(w, "%d\t%s\t%s\t%t\n", source.ID, source.Name, source.Type.String(), source.IsActive)
|
||||
}
|
||||
w.Flush()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func runDeleteAuth(c *cli.Context) error {
|
||||
if !c.IsSet("id") {
|
||||
return fmt.Errorf("--id flag is missing")
|
||||
}
|
||||
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
source, err := auth_model.GetSourceByID(c.Int64("id"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return auth_service.DeleteSource(source)
|
||||
}
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"text/tabwriter"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
auth_service "code.gitea.io/gitea/services/auth"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var (
|
||||
microcmdAuthDelete = &cli.Command{
|
||||
Name: "delete",
|
||||
Usage: "Delete specific auth source",
|
||||
Flags: []cli.Flag{idFlag},
|
||||
Action: runDeleteAuth,
|
||||
}
|
||||
microcmdAuthList = &cli.Command{
|
||||
Name: "list",
|
||||
Usage: "List auth sources",
|
||||
Action: runListAuth,
|
||||
Flags: []cli.Flag{
|
||||
&cli.IntFlag{
|
||||
Name: "min-width",
|
||||
Usage: "Minimal cell width including any padding for the formatted table",
|
||||
Value: 0,
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: "tab-width",
|
||||
Usage: "width of tab characters in formatted table (equivalent number of spaces)",
|
||||
Value: 8,
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: "padding",
|
||||
Usage: "padding added to a cell before computing its width",
|
||||
Value: 1,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "pad-char",
|
||||
Usage: `ASCII char used for padding if padchar == '\\t', the Writer will assume that the width of a '\\t' in the formatted output is tabwidth, and cells are left-aligned independent of align_left (for correct-looking results, tabwidth must correspond to the tab width in the viewer displaying the result)`,
|
||||
Value: "\t",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "vertical-bars",
|
||||
Usage: "Set to true to print vertical bars between columns",
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func runListAuth(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
authSources, err := db.Find[auth_model.Source](ctx, auth_model.FindSourcesOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
flags := tabwriter.AlignRight
|
||||
if c.Bool("vertical-bars") {
|
||||
flags |= tabwriter.Debug
|
||||
}
|
||||
|
||||
padChar := byte('\t')
|
||||
if len(c.String("pad-char")) > 0 {
|
||||
padChar = c.String("pad-char")[0]
|
||||
}
|
||||
|
||||
// loop through each source and print
|
||||
w := tabwriter.NewWriter(os.Stdout, c.Int("min-width"), c.Int("tab-width"), c.Int("padding"), padChar, flags)
|
||||
fmt.Fprintf(w, "ID\tName\tType\tEnabled\n")
|
||||
for _, source := range authSources {
|
||||
fmt.Fprintf(w, "%d\t%s\t%s\t%t\n", source.ID, source.Name, source.Type.String(), source.IsActive)
|
||||
}
|
||||
w.Flush()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func runDeleteAuth(c *cli.Context) error {
|
||||
if !c.IsSet("id") {
|
||||
return errors.New("--id flag is missing")
|
||||
}
|
||||
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
source, err := auth_model.GetSourceByID(ctx, c.Int64("id"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return auth_service.DeleteSource(ctx, source)
|
||||
}
|
||||
@@ -17,9 +17,9 @@ import (
|
||||
type (
|
||||
authService struct {
|
||||
initDB func(ctx context.Context) error
|
||||
createAuthSource func(context.Context, *auth.Source) error
|
||||
updateAuthSource func(context.Context, *auth.Source) error
|
||||
getAuthSourceByID func(ctx context.Context, id int64) (*auth.Source, error)
|
||||
createAuthSource func(*auth.Source) error
|
||||
updateAuthSource func(*auth.Source) error
|
||||
getAuthSourceByID func(id int64) (*auth.Source, error)
|
||||
}
|
||||
)
|
||||
|
||||
@@ -132,10 +132,10 @@ var (
|
||||
ldapSimpleAuthCLIFlags = append(commonLdapCLIFlags,
|
||||
&cli.StringFlag{
|
||||
Name: "user-dn",
|
||||
Usage: "The user's DN.",
|
||||
Usage: "The user’s DN.",
|
||||
})
|
||||
|
||||
microcmdAuthAddLdapBindDn = &cli.Command{
|
||||
cmdAuthAddLdapBindDn = &cli.Command{
|
||||
Name: "add-ldap",
|
||||
Usage: "Add new LDAP (via Bind DN) authentication source",
|
||||
Action: func(c *cli.Context) error {
|
||||
@@ -144,7 +144,7 @@ var (
|
||||
Flags: ldapBindDnCLIFlags,
|
||||
}
|
||||
|
||||
microcmdAuthUpdateLdapBindDn = &cli.Command{
|
||||
cmdAuthUpdateLdapBindDn = &cli.Command{
|
||||
Name: "update-ldap",
|
||||
Usage: "Update existing LDAP (via Bind DN) authentication source",
|
||||
Action: func(c *cli.Context) error {
|
||||
@@ -153,7 +153,7 @@ var (
|
||||
Flags: append([]cli.Flag{idFlag}, ldapBindDnCLIFlags...),
|
||||
}
|
||||
|
||||
microcmdAuthAddLdapSimpleAuth = &cli.Command{
|
||||
cmdAuthAddLdapSimpleAuth = &cli.Command{
|
||||
Name: "add-ldap-simple",
|
||||
Usage: "Add new LDAP (simple auth) authentication source",
|
||||
Action: func(c *cli.Context) error {
|
||||
@@ -162,7 +162,7 @@ var (
|
||||
Flags: ldapSimpleAuthCLIFlags,
|
||||
}
|
||||
|
||||
microcmdAuthUpdateLdapSimpleAuth = &cli.Command{
|
||||
cmdAuthUpdateLdapSimpleAuth = &cli.Command{
|
||||
Name: "update-ldap-simple",
|
||||
Usage: "Update existing LDAP (simple auth) authentication source",
|
||||
Action: func(c *cli.Context) error {
|
||||
@@ -289,12 +289,12 @@ func findLdapSecurityProtocolByName(name string) (ldap.SecurityProtocol, bool) {
|
||||
|
||||
// getAuthSource gets the login source by its id defined in the command line flags.
|
||||
// It returns an error if the id is not set, does not match any source or if the source is not of expected type.
|
||||
func (a *authService) getAuthSource(ctx context.Context, c *cli.Context, authType auth.Type) (*auth.Source, error) {
|
||||
func (a *authService) getAuthSource(c *cli.Context, authType auth.Type) (*auth.Source, error) {
|
||||
if err := argsSet(c, "id"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
authSource, err := a.getAuthSourceByID(ctx, c.Int64("id"))
|
||||
authSource, err := a.getAuthSourceByID(c.Int64("id"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -332,7 +332,7 @@ func (a *authService) addLdapBindDn(c *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return a.createAuthSource(ctx, authSource)
|
||||
return a.createAuthSource(authSource)
|
||||
}
|
||||
|
||||
// updateLdapBindDn updates a new LDAP via Bind DN authentication source.
|
||||
@@ -344,7 +344,7 @@ func (a *authService) updateLdapBindDn(c *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
authSource, err := a.getAuthSource(ctx, c, auth.LDAP)
|
||||
authSource, err := a.getAuthSource(c, auth.LDAP)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -354,7 +354,7 @@ func (a *authService) updateLdapBindDn(c *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return a.updateAuthSource(ctx, authSource)
|
||||
return a.updateAuthSource(authSource)
|
||||
}
|
||||
|
||||
// addLdapSimpleAuth adds a new LDAP (simple auth) authentication source.
|
||||
@@ -383,7 +383,7 @@ func (a *authService) addLdapSimpleAuth(c *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return a.createAuthSource(ctx, authSource)
|
||||
return a.createAuthSource(authSource)
|
||||
}
|
||||
|
||||
// updateLdapBindDn updates a new LDAP (simple auth) authentication source.
|
||||
@@ -395,7 +395,7 @@ func (a *authService) updateLdapSimpleAuth(c *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
authSource, err := a.getAuthSource(ctx, c, auth.DLDAP)
|
||||
authSource, err := a.getAuthSource(c, auth.DLDAP)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -405,5 +405,5 @@ func (a *authService) updateLdapSimpleAuth(c *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return a.updateAuthSource(ctx, authSource)
|
||||
return a.updateAuthSource(authSource)
|
||||
}
|
||||
|
||||
@@ -210,15 +210,15 @@ func TestAddLdapBindDn(t *testing.T) {
|
||||
initDB: func(context.Context) error {
|
||||
return nil
|
||||
},
|
||||
createAuthSource: func(ctx context.Context, authSource *auth.Source) error {
|
||||
createAuthSource: func(authSource *auth.Source) error {
|
||||
createdAuthSource = authSource
|
||||
return nil
|
||||
},
|
||||
updateAuthSource: func(ctx context.Context, authSource *auth.Source) error {
|
||||
updateAuthSource: func(authSource *auth.Source) error {
|
||||
assert.FailNow(t, "case %d: should not call updateAuthSource", n)
|
||||
return nil
|
||||
},
|
||||
getAuthSourceByID: func(ctx context.Context, id int64) (*auth.Source, error) {
|
||||
getAuthSourceByID: func(id int64) (*auth.Source, error) {
|
||||
assert.FailNow(t, "case %d: should not call getAuthSourceByID", n)
|
||||
return nil, nil
|
||||
},
|
||||
@@ -226,7 +226,7 @@ func TestAddLdapBindDn(t *testing.T) {
|
||||
|
||||
// Create a copy of command to test
|
||||
app := cli.NewApp()
|
||||
app.Flags = microcmdAuthAddLdapBindDn.Flags
|
||||
app.Flags = cmdAuthAddLdapBindDn.Flags
|
||||
app.Action = service.addLdapBindDn
|
||||
|
||||
// Run it
|
||||
@@ -441,15 +441,15 @@ func TestAddLdapSimpleAuth(t *testing.T) {
|
||||
initDB: func(context.Context) error {
|
||||
return nil
|
||||
},
|
||||
createAuthSource: func(ctx context.Context, authSource *auth.Source) error {
|
||||
createAuthSource: func(authSource *auth.Source) error {
|
||||
createdAuthSource = authSource
|
||||
return nil
|
||||
},
|
||||
updateAuthSource: func(ctx context.Context, authSource *auth.Source) error {
|
||||
updateAuthSource: func(authSource *auth.Source) error {
|
||||
assert.FailNow(t, "case %d: should not call updateAuthSource", n)
|
||||
return nil
|
||||
},
|
||||
getAuthSourceByID: func(ctx context.Context, id int64) (*auth.Source, error) {
|
||||
getAuthSourceByID: func(id int64) (*auth.Source, error) {
|
||||
assert.FailNow(t, "case %d: should not call getAuthSourceByID", n)
|
||||
return nil, nil
|
||||
},
|
||||
@@ -457,7 +457,7 @@ func TestAddLdapSimpleAuth(t *testing.T) {
|
||||
|
||||
// Create a copy of command to test
|
||||
app := cli.NewApp()
|
||||
app.Flags = microcmdAuthAddLdapSimpleAuth.Flags
|
||||
app.Flags = cmdAuthAddLdapSimpleAuth.Flags
|
||||
app.Action = service.addLdapSimpleAuth
|
||||
|
||||
// Run it
|
||||
@@ -896,15 +896,15 @@ func TestUpdateLdapBindDn(t *testing.T) {
|
||||
initDB: func(context.Context) error {
|
||||
return nil
|
||||
},
|
||||
createAuthSource: func(ctx context.Context, authSource *auth.Source) error {
|
||||
createAuthSource: func(authSource *auth.Source) error {
|
||||
assert.FailNow(t, "case %d: should not call createAuthSource", n)
|
||||
return nil
|
||||
},
|
||||
updateAuthSource: func(ctx context.Context, authSource *auth.Source) error {
|
||||
updateAuthSource: func(authSource *auth.Source) error {
|
||||
updatedAuthSource = authSource
|
||||
return nil
|
||||
},
|
||||
getAuthSourceByID: func(ctx context.Context, id int64) (*auth.Source, error) {
|
||||
getAuthSourceByID: func(id int64) (*auth.Source, error) {
|
||||
if c.id != 0 {
|
||||
assert.Equal(t, c.id, id, "case %d: wrong id", n)
|
||||
}
|
||||
@@ -920,7 +920,7 @@ func TestUpdateLdapBindDn(t *testing.T) {
|
||||
|
||||
// Create a copy of command to test
|
||||
app := cli.NewApp()
|
||||
app.Flags = microcmdAuthUpdateLdapBindDn.Flags
|
||||
app.Flags = cmdAuthUpdateLdapBindDn.Flags
|
||||
app.Action = service.updateLdapBindDn
|
||||
|
||||
// Run it
|
||||
@@ -1286,15 +1286,15 @@ func TestUpdateLdapSimpleAuth(t *testing.T) {
|
||||
initDB: func(context.Context) error {
|
||||
return nil
|
||||
},
|
||||
createAuthSource: func(ctx context.Context, authSource *auth.Source) error {
|
||||
createAuthSource: func(authSource *auth.Source) error {
|
||||
assert.FailNow(t, "case %d: should not call createAuthSource", n)
|
||||
return nil
|
||||
},
|
||||
updateAuthSource: func(ctx context.Context, authSource *auth.Source) error {
|
||||
updateAuthSource: func(authSource *auth.Source) error {
|
||||
updatedAuthSource = authSource
|
||||
return nil
|
||||
},
|
||||
getAuthSourceByID: func(ctx context.Context, id int64) (*auth.Source, error) {
|
||||
getAuthSourceByID: func(id int64) (*auth.Source, error) {
|
||||
if c.id != 0 {
|
||||
assert.Equal(t, c.id, id, "case %d: wrong id", n)
|
||||
}
|
||||
@@ -1310,7 +1310,7 @@ func TestUpdateLdapSimpleAuth(t *testing.T) {
|
||||
|
||||
// Create a copy of command to test
|
||||
app := cli.NewApp()
|
||||
app.Flags = microcmdAuthUpdateLdapSimpleAuth.Flags
|
||||
app.Flags = cmdAuthUpdateLdapSimpleAuth.Flags
|
||||
app.Action = service.updateLdapSimpleAuth
|
||||
|
||||
// Run it
|
||||
|
||||
@@ -1,299 +0,0 @@
|
||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/services/auth/source/oauth2"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var (
|
||||
oauthCLIFlags = []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "name",
|
||||
Value: "",
|
||||
Usage: "Application Name",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "provider",
|
||||
Value: "",
|
||||
Usage: "OAuth2 Provider",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "key",
|
||||
Value: "",
|
||||
Usage: "Client ID (Key)",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "secret",
|
||||
Value: "",
|
||||
Usage: "Client Secret",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "auto-discover-url",
|
||||
Value: "",
|
||||
Usage: "OpenID Connect Auto Discovery URL (only required when using OpenID Connect as provider)",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "use-custom-urls",
|
||||
Value: "false",
|
||||
Usage: "Use custom URLs for GitLab/GitHub OAuth endpoints",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "custom-tenant-id",
|
||||
Value: "",
|
||||
Usage: "Use custom Tenant ID for OAuth endpoints",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "custom-auth-url",
|
||||
Value: "",
|
||||
Usage: "Use a custom Authorization URL (option for GitLab/GitHub)",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "custom-token-url",
|
||||
Value: "",
|
||||
Usage: "Use a custom Token URL (option for GitLab/GitHub)",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "custom-profile-url",
|
||||
Value: "",
|
||||
Usage: "Use a custom Profile URL (option for GitLab/GitHub)",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "custom-email-url",
|
||||
Value: "",
|
||||
Usage: "Use a custom Email URL (option for GitHub)",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "icon-url",
|
||||
Value: "",
|
||||
Usage: "Custom icon URL for OAuth2 login source",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "skip-local-2fa",
|
||||
Usage: "Set to true to skip local 2fa for users authenticated by this source",
|
||||
},
|
||||
&cli.StringSliceFlag{
|
||||
Name: "scopes",
|
||||
Value: nil,
|
||||
Usage: "Scopes to request when to authenticate against this OAuth2 source",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "required-claim-name",
|
||||
Value: "",
|
||||
Usage: "Claim name that has to be set to allow users to login with this source",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "required-claim-value",
|
||||
Value: "",
|
||||
Usage: "Claim value that has to be set to allow users to login with this source",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "group-claim-name",
|
||||
Value: "",
|
||||
Usage: "Claim name providing group names for this source",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "admin-group",
|
||||
Value: "",
|
||||
Usage: "Group Claim value for administrator users",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "restricted-group",
|
||||
Value: "",
|
||||
Usage: "Group Claim value for restricted users",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "group-team-map",
|
||||
Value: "",
|
||||
Usage: "JSON mapping between groups and org teams",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "group-team-map-removal",
|
||||
Usage: "Activate automatic team membership removal depending on groups",
|
||||
},
|
||||
}
|
||||
|
||||
microcmdAuthAddOauth = &cli.Command{
|
||||
Name: "add-oauth",
|
||||
Usage: "Add new Oauth authentication source",
|
||||
Action: runAddOauth,
|
||||
Flags: oauthCLIFlags,
|
||||
}
|
||||
|
||||
microcmdAuthUpdateOauth = &cli.Command{
|
||||
Name: "update-oauth",
|
||||
Usage: "Update existing Oauth authentication source",
|
||||
Action: runUpdateOauth,
|
||||
Flags: append(oauthCLIFlags[:1], append([]cli.Flag{idFlag}, oauthCLIFlags[1:]...)...),
|
||||
}
|
||||
)
|
||||
|
||||
func parseOAuth2Config(c *cli.Context) *oauth2.Source {
|
||||
var customURLMapping *oauth2.CustomURLMapping
|
||||
if c.IsSet("use-custom-urls") {
|
||||
customURLMapping = &oauth2.CustomURLMapping{
|
||||
TokenURL: c.String("custom-token-url"),
|
||||
AuthURL: c.String("custom-auth-url"),
|
||||
ProfileURL: c.String("custom-profile-url"),
|
||||
EmailURL: c.String("custom-email-url"),
|
||||
Tenant: c.String("custom-tenant-id"),
|
||||
}
|
||||
} else {
|
||||
customURLMapping = nil
|
||||
}
|
||||
return &oauth2.Source{
|
||||
Provider: c.String("provider"),
|
||||
ClientID: c.String("key"),
|
||||
ClientSecret: c.String("secret"),
|
||||
OpenIDConnectAutoDiscoveryURL: c.String("auto-discover-url"),
|
||||
CustomURLMapping: customURLMapping,
|
||||
IconURL: c.String("icon-url"),
|
||||
SkipLocalTwoFA: c.Bool("skip-local-2fa"),
|
||||
Scopes: c.StringSlice("scopes"),
|
||||
RequiredClaimName: c.String("required-claim-name"),
|
||||
RequiredClaimValue: c.String("required-claim-value"),
|
||||
GroupClaimName: c.String("group-claim-name"),
|
||||
AdminGroup: c.String("admin-group"),
|
||||
RestrictedGroup: c.String("restricted-group"),
|
||||
GroupTeamMap: c.String("group-team-map"),
|
||||
GroupTeamMapRemoval: c.Bool("group-team-map-removal"),
|
||||
}
|
||||
}
|
||||
|
||||
func runAddOauth(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
config := parseOAuth2Config(c)
|
||||
if config.Provider == "openidConnect" {
|
||||
discoveryURL, err := url.Parse(config.OpenIDConnectAutoDiscoveryURL)
|
||||
if err != nil || (discoveryURL.Scheme != "http" && discoveryURL.Scheme != "https") {
|
||||
return fmt.Errorf("invalid Auto Discovery URL: %s (this must be a valid URL starting with http:// or https://)", config.OpenIDConnectAutoDiscoveryURL)
|
||||
}
|
||||
}
|
||||
|
||||
return auth_model.CreateSource(ctx, &auth_model.Source{
|
||||
Type: auth_model.OAuth2,
|
||||
Name: c.String("name"),
|
||||
IsActive: true,
|
||||
Cfg: config,
|
||||
})
|
||||
}
|
||||
|
||||
func runUpdateOauth(c *cli.Context) error {
|
||||
if !c.IsSet("id") {
|
||||
return errors.New("--id flag is missing")
|
||||
}
|
||||
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
source, err := auth_model.GetSourceByID(ctx, c.Int64("id"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
oAuth2Config := source.Cfg.(*oauth2.Source)
|
||||
|
||||
if c.IsSet("name") {
|
||||
source.Name = c.String("name")
|
||||
}
|
||||
|
||||
if c.IsSet("provider") {
|
||||
oAuth2Config.Provider = c.String("provider")
|
||||
}
|
||||
|
||||
if c.IsSet("key") {
|
||||
oAuth2Config.ClientID = c.String("key")
|
||||
}
|
||||
|
||||
if c.IsSet("secret") {
|
||||
oAuth2Config.ClientSecret = c.String("secret")
|
||||
}
|
||||
|
||||
if c.IsSet("auto-discover-url") {
|
||||
oAuth2Config.OpenIDConnectAutoDiscoveryURL = c.String("auto-discover-url")
|
||||
}
|
||||
|
||||
if c.IsSet("icon-url") {
|
||||
oAuth2Config.IconURL = c.String("icon-url")
|
||||
}
|
||||
|
||||
if c.IsSet("scopes") {
|
||||
oAuth2Config.Scopes = c.StringSlice("scopes")
|
||||
}
|
||||
|
||||
if c.IsSet("required-claim-name") {
|
||||
oAuth2Config.RequiredClaimName = c.String("required-claim-name")
|
||||
}
|
||||
if c.IsSet("required-claim-value") {
|
||||
oAuth2Config.RequiredClaimValue = c.String("required-claim-value")
|
||||
}
|
||||
|
||||
if c.IsSet("group-claim-name") {
|
||||
oAuth2Config.GroupClaimName = c.String("group-claim-name")
|
||||
}
|
||||
if c.IsSet("admin-group") {
|
||||
oAuth2Config.AdminGroup = c.String("admin-group")
|
||||
}
|
||||
if c.IsSet("restricted-group") {
|
||||
oAuth2Config.RestrictedGroup = c.String("restricted-group")
|
||||
}
|
||||
if c.IsSet("group-team-map") {
|
||||
oAuth2Config.GroupTeamMap = c.String("group-team-map")
|
||||
}
|
||||
if c.IsSet("group-team-map-removal") {
|
||||
oAuth2Config.GroupTeamMapRemoval = c.Bool("group-team-map-removal")
|
||||
}
|
||||
|
||||
// update custom URL mapping
|
||||
customURLMapping := &oauth2.CustomURLMapping{}
|
||||
|
||||
if oAuth2Config.CustomURLMapping != nil {
|
||||
customURLMapping.TokenURL = oAuth2Config.CustomURLMapping.TokenURL
|
||||
customURLMapping.AuthURL = oAuth2Config.CustomURLMapping.AuthURL
|
||||
customURLMapping.ProfileURL = oAuth2Config.CustomURLMapping.ProfileURL
|
||||
customURLMapping.EmailURL = oAuth2Config.CustomURLMapping.EmailURL
|
||||
customURLMapping.Tenant = oAuth2Config.CustomURLMapping.Tenant
|
||||
}
|
||||
if c.IsSet("use-custom-urls") && c.IsSet("custom-token-url") {
|
||||
customURLMapping.TokenURL = c.String("custom-token-url")
|
||||
}
|
||||
|
||||
if c.IsSet("use-custom-urls") && c.IsSet("custom-auth-url") {
|
||||
customURLMapping.AuthURL = c.String("custom-auth-url")
|
||||
}
|
||||
|
||||
if c.IsSet("use-custom-urls") && c.IsSet("custom-profile-url") {
|
||||
customURLMapping.ProfileURL = c.String("custom-profile-url")
|
||||
}
|
||||
|
||||
if c.IsSet("use-custom-urls") && c.IsSet("custom-email-url") {
|
||||
customURLMapping.EmailURL = c.String("custom-email-url")
|
||||
}
|
||||
|
||||
if c.IsSet("use-custom-urls") && c.IsSet("custom-tenant-id") {
|
||||
customURLMapping.Tenant = c.String("custom-tenant-id")
|
||||
}
|
||||
|
||||
oAuth2Config.CustomURLMapping = customURLMapping
|
||||
source.Cfg = oAuth2Config
|
||||
|
||||
return auth_model.UpdateSource(ctx, source)
|
||||
}
|
||||
@@ -1,200 +0,0 @@
|
||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"code.gitea.io/gitea/services/auth/source/smtp"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var (
|
||||
smtpCLIFlags = []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "name",
|
||||
Value: "",
|
||||
Usage: "Application Name",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "auth-type",
|
||||
Value: "PLAIN",
|
||||
Usage: "SMTP Authentication Type (PLAIN/LOGIN/CRAM-MD5) default PLAIN",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "host",
|
||||
Value: "",
|
||||
Usage: "SMTP Host",
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: "port",
|
||||
Usage: "SMTP Port",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "force-smtps",
|
||||
Usage: "SMTPS is always used on port 465. Set this to force SMTPS on other ports.",
|
||||
Value: true,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "skip-verify",
|
||||
Usage: "Skip TLS verify.",
|
||||
Value: true,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "helo-hostname",
|
||||
Value: "",
|
||||
Usage: "Hostname sent with HELO. Leave blank to send current hostname",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "disable-helo",
|
||||
Usage: "Disable SMTP helo.",
|
||||
Value: true,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "allowed-domains",
|
||||
Value: "",
|
||||
Usage: "Leave empty to allow all domains. Separate multiple domains with a comma (',')",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "skip-local-2fa",
|
||||
Usage: "Skip 2FA to log on.",
|
||||
Value: true,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "active",
|
||||
Usage: "This Authentication Source is Activated.",
|
||||
Value: true,
|
||||
},
|
||||
}
|
||||
|
||||
microcmdAuthAddSMTP = &cli.Command{
|
||||
Name: "add-smtp",
|
||||
Usage: "Add new SMTP authentication source",
|
||||
Action: runAddSMTP,
|
||||
Flags: smtpCLIFlags,
|
||||
}
|
||||
|
||||
microcmdAuthUpdateSMTP = &cli.Command{
|
||||
Name: "update-smtp",
|
||||
Usage: "Update existing SMTP authentication source",
|
||||
Action: runUpdateSMTP,
|
||||
Flags: append(smtpCLIFlags[:1], append([]cli.Flag{idFlag}, smtpCLIFlags[1:]...)...),
|
||||
}
|
||||
)
|
||||
|
||||
func parseSMTPConfig(c *cli.Context, conf *smtp.Source) error {
|
||||
if c.IsSet("auth-type") {
|
||||
conf.Auth = c.String("auth-type")
|
||||
validAuthTypes := []string{"PLAIN", "LOGIN", "CRAM-MD5"}
|
||||
if !util.SliceContainsString(validAuthTypes, strings.ToUpper(c.String("auth-type"))) {
|
||||
return errors.New("Auth must be one of PLAIN/LOGIN/CRAM-MD5")
|
||||
}
|
||||
conf.Auth = c.String("auth-type")
|
||||
}
|
||||
if c.IsSet("host") {
|
||||
conf.Host = c.String("host")
|
||||
}
|
||||
if c.IsSet("port") {
|
||||
conf.Port = c.Int("port")
|
||||
}
|
||||
if c.IsSet("allowed-domains") {
|
||||
conf.AllowedDomains = c.String("allowed-domains")
|
||||
}
|
||||
if c.IsSet("force-smtps") {
|
||||
conf.ForceSMTPS = c.Bool("force-smtps")
|
||||
}
|
||||
if c.IsSet("skip-verify") {
|
||||
conf.SkipVerify = c.Bool("skip-verify")
|
||||
}
|
||||
if c.IsSet("helo-hostname") {
|
||||
conf.HeloHostname = c.String("helo-hostname")
|
||||
}
|
||||
if c.IsSet("disable-helo") {
|
||||
conf.DisableHelo = c.Bool("disable-helo")
|
||||
}
|
||||
if c.IsSet("skip-local-2fa") {
|
||||
conf.SkipLocalTwoFA = c.Bool("skip-local-2fa")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func runAddSMTP(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !c.IsSet("name") || len(c.String("name")) == 0 {
|
||||
return errors.New("name must be set")
|
||||
}
|
||||
if !c.IsSet("host") || len(c.String("host")) == 0 {
|
||||
return errors.New("host must be set")
|
||||
}
|
||||
if !c.IsSet("port") {
|
||||
return errors.New("port must be set")
|
||||
}
|
||||
active := true
|
||||
if c.IsSet("active") {
|
||||
active = c.Bool("active")
|
||||
}
|
||||
|
||||
var smtpConfig smtp.Source
|
||||
if err := parseSMTPConfig(c, &smtpConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If not set default to PLAIN
|
||||
if len(smtpConfig.Auth) == 0 {
|
||||
smtpConfig.Auth = "PLAIN"
|
||||
}
|
||||
|
||||
return auth_model.CreateSource(ctx, &auth_model.Source{
|
||||
Type: auth_model.SMTP,
|
||||
Name: c.String("name"),
|
||||
IsActive: active,
|
||||
Cfg: &smtpConfig,
|
||||
})
|
||||
}
|
||||
|
||||
func runUpdateSMTP(c *cli.Context) error {
|
||||
if !c.IsSet("id") {
|
||||
return errors.New("--id flag is missing")
|
||||
}
|
||||
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
source, err := auth_model.GetSourceByID(ctx, c.Int64("id"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
smtpConfig := source.Cfg.(*smtp.Source)
|
||||
|
||||
if err := parseSMTPConfig(c, smtpConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if c.IsSet("name") {
|
||||
source.Name = c.String("name")
|
||||
}
|
||||
|
||||
if c.IsSet("active") {
|
||||
source.IsActive = c.Bool("active")
|
||||
}
|
||||
|
||||
source.Cfg = smtpConfig
|
||||
|
||||
return auth_model.UpdateSource(ctx, source)
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"code.gitea.io/gitea/modules/graceful"
|
||||
asymkey_service "code.gitea.io/gitea/services/asymkey"
|
||||
repo_service "code.gitea.io/gitea/services/repository"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var (
|
||||
microcmdRegenHooks = &cli.Command{
|
||||
Name: "hooks",
|
||||
Usage: "Regenerate git-hooks",
|
||||
Action: runRegenerateHooks,
|
||||
}
|
||||
|
||||
microcmdRegenKeys = &cli.Command{
|
||||
Name: "keys",
|
||||
Usage: "Regenerate authorized_keys file",
|
||||
Action: runRegenerateKeys,
|
||||
}
|
||||
)
|
||||
|
||||
func runRegenerateHooks(_ *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return repo_service.SyncRepositoryHooks(graceful.GetManager().ShutdownContext())
|
||||
}
|
||||
|
||||
func runRegenerateKeys(_ *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return asymkey_service.RewriteAllPublicKeys(ctx)
|
||||
}
|
||||
@@ -4,14 +4,13 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/auth/password"
|
||||
"code.gitea.io/gitea/modules/optional"
|
||||
pwd "code.gitea.io/gitea/modules/auth/password"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
user_service "code.gitea.io/gitea/services/user"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
@@ -33,11 +32,6 @@ var microcmdUserChangePassword = &cli.Command{
|
||||
Value: "",
|
||||
Usage: "New password to set for user",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "must-change-password",
|
||||
Usage: "User must change password (can be disabled by --must-change-password=false)",
|
||||
Value: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -52,27 +46,31 @@ func runChangePassword(c *cli.Context) error {
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(c.String("password")) < setting.MinPasswordLength {
|
||||
return fmt.Errorf("Password is not long enough. Needs to be at least %d", setting.MinPasswordLength)
|
||||
}
|
||||
|
||||
user, err := user_model.GetUserByName(ctx, c.String("username"))
|
||||
if !pwd.IsComplexEnough(c.String("password")) {
|
||||
return errors.New("Password does not meet complexity requirements")
|
||||
}
|
||||
pwned, err := pwd.IsPwned(context.Background(), c.String("password"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
opts := &user_service.UpdateAuthOptions{
|
||||
Password: optional.Some(c.String("password")),
|
||||
MustChangePassword: optional.Some(c.Bool("must-change-password")),
|
||||
if pwned {
|
||||
return errors.New("The password you chose is on a list of stolen passwords previously exposed in public data breaches. Please try again with a different password.\nFor more details, see https://haveibeenpwned.com/Passwords")
|
||||
}
|
||||
if err := user_service.UpdateAuth(ctx, user, opts); err != nil {
|
||||
switch {
|
||||
case errors.Is(err, password.ErrMinLength):
|
||||
return fmt.Errorf("password is not long enough, needs to be at least %d characters", setting.MinPasswordLength)
|
||||
case errors.Is(err, password.ErrComplexity):
|
||||
return errors.New("password does not meet complexity requirements")
|
||||
case errors.Is(err, password.ErrIsPwned):
|
||||
return errors.New("the password is in a list of stolen passwords previously exposed in public data breaches, please try again with a different password, to see more details: https://haveibeenpwned.com/Passwords")
|
||||
default:
|
||||
return err
|
||||
}
|
||||
uname := c.String("username")
|
||||
user, err := user_model.GetUserByName(ctx, uname)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = user.SetPassword(c.String("password")); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = user_model.UpdateUserCols(ctx, user, "passwd", "passwd_hash_algo", "salt"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("%s's password has been successfully updated!\n", user.Name)
|
||||
|
||||
@@ -4,16 +4,14 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
pwd "code.gitea.io/gitea/modules/auth/password"
|
||||
"code.gitea.io/gitea/modules/optional"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
@@ -48,9 +46,8 @@ var microcmdUserCreate = &cli.Command{
|
||||
Usage: "Generate a random password for the user",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "must-change-password",
|
||||
Usage: "User must change password after initial login, defaults to true for all users except the first one (can be disabled by --must-change-password=false)",
|
||||
DisableDefaultText: true,
|
||||
Name: "must-change-password",
|
||||
Usage: "Set this option to false to prevent forcing the user to change their password after initial login, (Default: true)",
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: "random-password-length",
|
||||
@@ -74,10 +71,10 @@ func runCreateUser(c *cli.Context) error {
|
||||
}
|
||||
|
||||
if c.IsSet("name") && c.IsSet("username") {
|
||||
return errors.New("cannot set both --name and --username flags")
|
||||
return errors.New("Cannot set both --name and --username flags")
|
||||
}
|
||||
if !c.IsSet("name") && !c.IsSet("username") {
|
||||
return errors.New("one of --name or --username flags must be set")
|
||||
return errors.New("One of --name or --username flags must be set")
|
||||
}
|
||||
|
||||
if c.IsSet("password") && c.IsSet("random-password") {
|
||||
@@ -92,16 +89,11 @@ func runCreateUser(c *cli.Context) error {
|
||||
_, _ = fmt.Fprintf(c.App.ErrWriter, "--name flag is deprecated. Use --username instead.\n")
|
||||
}
|
||||
|
||||
ctx := c.Context
|
||||
if !setting.IsInTesting {
|
||||
// FIXME: need to refactor the "installSignals/initDB" related code later
|
||||
// it doesn't make sense to call it in (almost) every command action function
|
||||
var cancel context.CancelFunc
|
||||
ctx, cancel = installSignals()
|
||||
defer cancel()
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
if err := initDB(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var password string
|
||||
@@ -118,27 +110,23 @@ func runCreateUser(c *cli.Context) error {
|
||||
return errors.New("must set either password or random-password flag")
|
||||
}
|
||||
|
||||
isAdmin := c.Bool("admin")
|
||||
mustChangePassword := true // always default to true
|
||||
if c.IsSet("must-change-password") {
|
||||
// if the flag is set, use the value provided by the user
|
||||
mustChangePassword = c.Bool("must-change-password")
|
||||
} else {
|
||||
// check whether there are users in the database
|
||||
hasUserRecord, err := db.IsTableNotEmpty(&user_model.User{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("IsTableNotEmpty: %w", err)
|
||||
}
|
||||
if !hasUserRecord {
|
||||
// if this is the first one being created, don't force to change password (keep the old behavior)
|
||||
mustChangePassword = false
|
||||
}
|
||||
// always default to true
|
||||
changePassword := true
|
||||
|
||||
// If this is the first user being created.
|
||||
// Take it as the admin and don't force a password update.
|
||||
if n := user_model.CountUsers(ctx, nil); n == 0 {
|
||||
changePassword = false
|
||||
}
|
||||
|
||||
restricted := optional.None[bool]()
|
||||
if c.IsSet("must-change-password") {
|
||||
changePassword = c.Bool("must-change-password")
|
||||
}
|
||||
|
||||
restricted := util.OptionalBoolNone
|
||||
|
||||
if c.IsSet("restricted") {
|
||||
restricted = optional.Some(c.Bool("restricted"))
|
||||
restricted = util.OptionalBoolOf(c.Bool("restricted"))
|
||||
}
|
||||
|
||||
// default user visibility in app.ini
|
||||
@@ -148,13 +136,13 @@ func runCreateUser(c *cli.Context) error {
|
||||
Name: username,
|
||||
Email: c.String("email"),
|
||||
Passwd: password,
|
||||
IsAdmin: isAdmin,
|
||||
MustChangePassword: mustChangePassword,
|
||||
IsAdmin: c.Bool("admin"),
|
||||
MustChangePassword: changePassword,
|
||||
Visibility: visibility,
|
||||
}
|
||||
|
||||
overwriteDefault := &user_model.CreateUserOverwriteOptions{
|
||||
IsActive: optional.Some(true),
|
||||
IsActive: util.OptionalBoolTrue,
|
||||
IsRestricted: restricted,
|
||||
}
|
||||
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestAdminUserCreate(t *testing.T) {
|
||||
app := NewMainApp(AppVersion{})
|
||||
|
||||
reset := func() {
|
||||
assert.NoError(t, db.TruncateBeans(db.DefaultContext, &user_model.User{}))
|
||||
assert.NoError(t, db.TruncateBeans(db.DefaultContext, &user_model.EmailAddress{}))
|
||||
}
|
||||
|
||||
type createCheck struct{ IsAdmin, MustChangePassword bool }
|
||||
createUser := func(name, args string) createCheck {
|
||||
assert.NoError(t, app.Run(strings.Fields(fmt.Sprintf("./gitea admin user create --username %s --email %s@gitea.local %s --password foobar", name, name, args))))
|
||||
u := unittest.AssertExistsAndLoadBean(t, &user_model.User{LowerName: name})
|
||||
return createCheck{u.IsAdmin, u.MustChangePassword}
|
||||
}
|
||||
reset()
|
||||
assert.Equal(t, createCheck{IsAdmin: false, MustChangePassword: false}, createUser("u", ""), "first non-admin user doesn't need to change password")
|
||||
|
||||
reset()
|
||||
assert.Equal(t, createCheck{IsAdmin: true, MustChangePassword: false}, createUser("u", "--admin"), "first admin user doesn't need to change password")
|
||||
|
||||
reset()
|
||||
assert.Equal(t, createCheck{IsAdmin: true, MustChangePassword: true}, createUser("u", "--admin --must-change-password"))
|
||||
assert.Equal(t, createCheck{IsAdmin: true, MustChangePassword: true}, createUser("u2", "--admin"))
|
||||
assert.Equal(t, createCheck{IsAdmin: true, MustChangePassword: false}, createUser("u3", "--admin --must-change-password=false"))
|
||||
assert.Equal(t, createCheck{IsAdmin: false, MustChangePassword: true}, createUser("u4", ""))
|
||||
assert.Equal(t, createCheck{IsAdmin: false, MustChangePassword: false}, createUser("u5", "--must-change-password=false"))
|
||||
}
|
||||
@@ -4,7 +4,6 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
@@ -43,7 +42,7 @@ var microcmdUserDelete = &cli.Command{
|
||||
|
||||
func runDeleteUser(c *cli.Context) error {
|
||||
if !c.IsSet("id") && !c.IsSet("username") && !c.IsSet("email") {
|
||||
return errors.New("You must provide the id, username or email of a user to delete")
|
||||
return fmt.Errorf("You must provide the id, username or email of a user to delete")
|
||||
}
|
||||
|
||||
ctx, cancel := installSignals()
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
@@ -43,7 +42,7 @@ var microcmdUserGenerateAccessToken = &cli.Command{
|
||||
|
||||
func runGenerateAccessToken(c *cli.Context) error {
|
||||
if !c.IsSet("username") {
|
||||
return errors.New("You must provide a username to generate a token for")
|
||||
return fmt.Errorf("You must provide a username to generate a token for")
|
||||
}
|
||||
|
||||
ctx, cancel := installSignals()
|
||||
@@ -69,7 +68,7 @@ func runGenerateAccessToken(c *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
if exist {
|
||||
return errors.New("access token name has been used already")
|
||||
return fmt.Errorf("access token name has been used already")
|
||||
}
|
||||
|
||||
// make sure the scopes are valid
|
||||
|
||||
@@ -14,28 +14,14 @@ import (
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/models/migrations"
|
||||
migrate_base "code.gitea.io/gitea/models/migrations/base"
|
||||
"code.gitea.io/gitea/modules/container"
|
||||
"code.gitea.io/gitea/modules/doctor"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/services/doctor"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
// CmdDoctor represents the available doctor sub-command.
|
||||
var CmdDoctor = &cli.Command{
|
||||
Name: "doctor",
|
||||
Usage: "Diagnose and optionally fix problems, convert or re-create database tables",
|
||||
Description: "A command to diagnose problems with the current Gitea instance according to the given configuration. Some problems can optionally be fixed by modifying the database or data storage.",
|
||||
|
||||
Subcommands: []*cli.Command{
|
||||
cmdDoctorCheck,
|
||||
cmdRecreateTable,
|
||||
cmdDoctorConvert,
|
||||
},
|
||||
}
|
||||
|
||||
var cmdDoctorCheck = &cli.Command{
|
||||
Name: "check",
|
||||
Usage: "Diagnose and optionally fix problems",
|
||||
@@ -74,6 +60,19 @@ var cmdDoctorCheck = &cli.Command{
|
||||
},
|
||||
}
|
||||
|
||||
// CmdDoctor represents the available doctor sub-command.
|
||||
var CmdDoctor = &cli.Command{
|
||||
Name: "doctor",
|
||||
Usage: "Diagnose and optionally fix problems",
|
||||
Description: "A command to diagnose problems with the current Gitea instance according to the given configuration. Some problems can optionally be fixed by modifying the database or data storage.",
|
||||
|
||||
Subcommands: []*cli.Command{
|
||||
cmdDoctorCheck,
|
||||
cmdRecreateTable,
|
||||
cmdDoctorConvert,
|
||||
},
|
||||
}
|
||||
|
||||
var cmdRecreateTable = &cli.Command{
|
||||
Name: "recreate-table",
|
||||
Usage: "Recreate tables from XORM definitions and copy the data.",
|
||||
@@ -178,7 +177,6 @@ func runDoctorCheck(ctx *cli.Context) error {
|
||||
if ctx.IsSet("list") {
|
||||
w := tabwriter.NewWriter(os.Stdout, 0, 8, 1, '\t', 0)
|
||||
_, _ = w.Write([]byte("Default\tName\tTitle\n"))
|
||||
doctor.SortChecks(doctor.Checks)
|
||||
for _, check := range doctor.Checks {
|
||||
if check.IsDefault {
|
||||
_, _ = w.Write([]byte{'*'})
|
||||
@@ -194,19 +192,25 @@ func runDoctorCheck(ctx *cli.Context) error {
|
||||
|
||||
var checks []*doctor.Check
|
||||
if ctx.Bool("all") {
|
||||
checks = make([]*doctor.Check, len(doctor.Checks))
|
||||
copy(checks, doctor.Checks)
|
||||
checks = doctor.Checks
|
||||
} else if ctx.IsSet("run") {
|
||||
addDefault := ctx.Bool("default")
|
||||
runNamesSet := container.SetOf(ctx.StringSlice("run")...)
|
||||
for _, check := range doctor.Checks {
|
||||
if (addDefault && check.IsDefault) || runNamesSet.Contains(check.Name) {
|
||||
checks = append(checks, check)
|
||||
runNamesSet.Remove(check.Name)
|
||||
}
|
||||
names := ctx.StringSlice("run")
|
||||
for i, name := range names {
|
||||
names[i] = strings.ToLower(strings.TrimSpace(name))
|
||||
}
|
||||
if len(runNamesSet) > 0 {
|
||||
return fmt.Errorf("unknown checks: %q", strings.Join(runNamesSet.Values(), ","))
|
||||
|
||||
for _, check := range doctor.Checks {
|
||||
if addDefault && check.IsDefault {
|
||||
checks = append(checks, check)
|
||||
continue
|
||||
}
|
||||
for _, name := range names {
|
||||
if name == check.Name {
|
||||
checks = append(checks, check)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for _, check := range doctor.Checks {
|
||||
@@ -215,5 +219,6 @@ func runDoctorCheck(ctx *cli.Context) error {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return doctor.RunChecks(stdCtx, colorize, ctx.Bool("fix"), checks)
|
||||
}
|
||||
|
||||
@@ -37,8 +37,8 @@ func runDoctorConvert(ctx *cli.Context) error {
|
||||
|
||||
switch {
|
||||
case setting.Database.Type.IsMySQL():
|
||||
if err := db.ConvertDatabaseTable(); err != nil {
|
||||
log.Fatal("Failed to convert database & table: %v", err)
|
||||
if err := db.ConvertUtf8ToUtf8mb4(); err != nil {
|
||||
log.Fatal("Failed to convert database from utf8 to utf8mb4: %v", err)
|
||||
return err
|
||||
}
|
||||
fmt.Println("Converted successfully, please confirm your database's character set is now utf8mb4")
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/services/doctor"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func TestDoctorRun(t *testing.T) {
|
||||
doctor.Register(&doctor.Check{
|
||||
Title: "Test Check",
|
||||
Name: "test-check",
|
||||
Run: func(ctx context.Context, logger log.Logger, autofix bool) error { return nil },
|
||||
|
||||
SkipDatabaseInitialization: true,
|
||||
})
|
||||
app := cli.NewApp()
|
||||
app.Commands = []*cli.Command{cmdDoctorCheck}
|
||||
err := app.Run([]string{"./gitea", "check", "--run", "test-check"})
|
||||
assert.NoError(t, err)
|
||||
err = app.Run([]string{"./gitea", "check", "--run", "no-such"})
|
||||
assert.ErrorContains(t, err, `unknown checks: "no-such"`)
|
||||
err = app.Run([]string{"./gitea", "check", "--run", "test-check,no-such"})
|
||||
assert.ErrorContains(t, err, `unknown checks: "no-such"`)
|
||||
}
|
||||
354
cmd/dump.go
354
cmd/dump.go
@@ -6,13 +6,14 @@ package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/modules/dump"
|
||||
"code.gitea.io/gitea/modules/json"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
@@ -24,17 +25,89 @@ import (
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func addReader(w archiver.Writer, r io.ReadCloser, info os.FileInfo, customName string, verbose bool) error {
|
||||
if verbose {
|
||||
log.Info("Adding file %s", customName)
|
||||
}
|
||||
|
||||
return w.Write(archiver.File{
|
||||
FileInfo: archiver.FileInfo{
|
||||
FileInfo: info,
|
||||
CustomName: customName,
|
||||
},
|
||||
ReadCloser: r,
|
||||
})
|
||||
}
|
||||
|
||||
func addFile(w archiver.Writer, filePath, absPath string, verbose bool) error {
|
||||
file, err := os.Open(absPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
fileInfo, err := file.Stat()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return addReader(w, file, fileInfo, filePath, verbose)
|
||||
}
|
||||
|
||||
func isSubdir(upper, lower string) (bool, error) {
|
||||
if relPath, err := filepath.Rel(upper, lower); err != nil {
|
||||
return false, err
|
||||
} else if relPath == "." || !strings.HasPrefix(relPath, ".") {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
type outputType struct {
|
||||
Enum []string
|
||||
Default string
|
||||
selected string
|
||||
}
|
||||
|
||||
func (o outputType) Join() string {
|
||||
return strings.Join(o.Enum, ", ")
|
||||
}
|
||||
|
||||
func (o *outputType) Set(value string) error {
|
||||
for _, enum := range o.Enum {
|
||||
if enum == value {
|
||||
o.selected = value
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf("allowed values are %s", o.Join())
|
||||
}
|
||||
|
||||
func (o outputType) String() string {
|
||||
if o.selected == "" {
|
||||
return o.Default
|
||||
}
|
||||
return o.selected
|
||||
}
|
||||
|
||||
var outputTypeEnum = &outputType{
|
||||
Enum: []string{"zip", "tar", "tar.sz", "tar.gz", "tar.xz", "tar.bz2", "tar.br", "tar.lz4", "tar.zst"},
|
||||
Default: "zip",
|
||||
}
|
||||
|
||||
// CmdDump represents the available dump sub-command.
|
||||
var CmdDump = &cli.Command{
|
||||
Name: "dump",
|
||||
Usage: "Dump Gitea files and database",
|
||||
Description: `Dump compresses all related files and database into zip file. It can be used for backup and capture Gitea server image to send to maintainer`,
|
||||
Action: runDump,
|
||||
Name: "dump",
|
||||
Usage: "Dump Gitea files and database",
|
||||
Description: `Dump compresses all related files and database into zip file.
|
||||
It can be used for backup and capture Gitea server image to send to maintainer`,
|
||||
Action: runDump,
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "file",
|
||||
Aliases: []string{"f"},
|
||||
Usage: `Name of the dump file which will be created, default to "gitea-dump-{time}.zip". Supply '-' for stdout. See type for available types.`,
|
||||
Value: fmt.Sprintf("gitea-dump-%d.zip", time.Now().Unix()),
|
||||
Usage: "Name of the dump file which will be created. Supply '-' for stdout. See type for available types.",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "verbose",
|
||||
@@ -87,56 +160,64 @@ var CmdDump = &cli.Command{
|
||||
Name: "skip-index",
|
||||
Usage: "Skip bleve index data",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "skip-db",
|
||||
Usage: "Skip database",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
&cli.GenericFlag{
|
||||
Name: "type",
|
||||
Usage: fmt.Sprintf(`Dump output format, default to "zip", supported types: %s`, strings.Join(dump.SupportedOutputTypes, ", ")),
|
||||
Value: outputTypeEnum,
|
||||
Usage: fmt.Sprintf("Dump output format: %s", outputTypeEnum.Join()),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func fatal(format string, args ...any) {
|
||||
fmt.Fprintf(os.Stderr, format+"\n", args...)
|
||||
log.Fatal(format, args...)
|
||||
}
|
||||
|
||||
func runDump(ctx *cli.Context) error {
|
||||
var file *os.File
|
||||
fileName := ctx.String("file")
|
||||
outType := ctx.String("type")
|
||||
if fileName == "-" {
|
||||
file = os.Stdout
|
||||
setupConsoleLogger(log.FATAL, log.CanColorStderr, os.Stderr)
|
||||
} else {
|
||||
for _, suffix := range outputTypeEnum.Enum {
|
||||
if strings.HasSuffix(fileName, "."+suffix) {
|
||||
fileName = strings.TrimSuffix(fileName, "."+suffix)
|
||||
break
|
||||
}
|
||||
}
|
||||
fileName += "." + outType
|
||||
}
|
||||
setting.MustInstalled()
|
||||
|
||||
quite := ctx.Bool("quiet")
|
||||
verbose := ctx.Bool("verbose")
|
||||
if verbose && quite {
|
||||
fatal("Option --quiet and --verbose cannot both be set")
|
||||
// make sure we are logging to the console no matter what the configuration tells us do to
|
||||
// FIXME: don't use CfgProvider directly
|
||||
if _, err := setting.CfgProvider.Section("log").NewKey("MODE", "console"); err != nil {
|
||||
fatal("Setting logging mode to console failed: %v", err)
|
||||
}
|
||||
if _, err := setting.CfgProvider.Section("log.console").NewKey("STDERR", "true"); err != nil {
|
||||
fatal("Setting console logger to stderr failed: %v", err)
|
||||
}
|
||||
|
||||
// outFileName is either "-" or a file name (will be made absolute)
|
||||
outFileName, outType := dump.PrepareFileNameAndType(ctx.String("file"), ctx.String("type"))
|
||||
if outType == "" {
|
||||
fatal("Invalid output type")
|
||||
// Set loglevel to Warn if quiet-mode is requested
|
||||
if ctx.Bool("quiet") {
|
||||
if _, err := setting.CfgProvider.Section("log.console").NewKey("LEVEL", "Warn"); err != nil {
|
||||
fatal("Setting console log-level failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
outFile := os.Stdout
|
||||
if outFileName != "-" {
|
||||
var err error
|
||||
if outFileName, err = filepath.Abs(outFileName); err != nil {
|
||||
fatal("Unable to get absolute path of dump file: %v", err)
|
||||
}
|
||||
if exist, _ := util.IsExist(outFileName); exist {
|
||||
fatal("Dump file %q exists", outFileName)
|
||||
}
|
||||
if outFile, err = os.Create(outFileName); err != nil {
|
||||
fatal("Unable to create dump file %q: %v", outFileName, err)
|
||||
}
|
||||
defer outFile.Close()
|
||||
if !setting.InstallLock {
|
||||
log.Error("Is '%s' really the right config path?\n", setting.CustomConf)
|
||||
return fmt.Errorf("gitea is not initialized")
|
||||
}
|
||||
|
||||
setupConsoleLogger(util.Iif(quite, log.WARN, log.INFO), log.CanColorStderr, os.Stderr)
|
||||
|
||||
setting.DisableLoggerInit()
|
||||
setting.LoadSettings() // cannot access session settings otherwise
|
||||
|
||||
verbose := ctx.Bool("verbose")
|
||||
if verbose && ctx.Bool("quiet") {
|
||||
return fmt.Errorf("--quiet and --verbose cannot both be set")
|
||||
}
|
||||
|
||||
stdCtx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
@@ -145,32 +226,44 @@ func runDump(ctx *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = storage.Init(); err != nil {
|
||||
if err := storage.Init(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
archiverGeneric, err := archiver.ByExtension("." + outType)
|
||||
if file == nil {
|
||||
file, err = os.Create(fileName)
|
||||
if err != nil {
|
||||
fatal("Unable to open %s: %v", fileName, err)
|
||||
}
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
absFileName, err := filepath.Abs(fileName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var iface any
|
||||
if fileName == "-" {
|
||||
iface, err = archiver.ByExtension(fmt.Sprintf(".%s", outType))
|
||||
} else {
|
||||
iface, err = archiver.ByExtension(fileName)
|
||||
}
|
||||
if err != nil {
|
||||
fatal("Unable to get archiver for extension: %v", err)
|
||||
}
|
||||
|
||||
archiverWriter := archiverGeneric.(archiver.Writer)
|
||||
if err := archiverWriter.Create(outFile); err != nil {
|
||||
w, _ := iface.(archiver.Writer)
|
||||
if err := w.Create(file); err != nil {
|
||||
fatal("Creating archiver.Writer failed: %v", err)
|
||||
}
|
||||
defer archiverWriter.Close()
|
||||
|
||||
dumper := &dump.Dumper{
|
||||
Writer: archiverWriter,
|
||||
Verbose: verbose,
|
||||
}
|
||||
dumper.GlobalExcludeAbsPath(outFileName)
|
||||
defer w.Close()
|
||||
|
||||
if ctx.IsSet("skip-repository") && ctx.Bool("skip-repository") {
|
||||
log.Info("Skip dumping local repositories")
|
||||
} else {
|
||||
log.Info("Dumping local repositories... %s", setting.RepoRootPath)
|
||||
if err := dumper.AddRecursiveExclude("repos", setting.RepoRootPath, nil); err != nil {
|
||||
if err := addRecursiveExclude(w, "repos", setting.RepoRootPath, []string{absFileName}, verbose); err != nil {
|
||||
fatal("Failed to include repositories: %v", err)
|
||||
}
|
||||
|
||||
@@ -183,52 +276,49 @@ func runDump(ctx *cli.Context) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return dumper.AddReader(object, info, path.Join("data", "lfs", objPath))
|
||||
|
||||
return addReader(w, object, info, path.Join("data", "lfs", objPath), verbose)
|
||||
}); err != nil {
|
||||
fatal("Failed to dump LFS objects: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if ctx.Bool("skip-db") {
|
||||
// Ensure that we don't dump the database file that may reside in setting.AppDataPath or elsewhere.
|
||||
dumper.GlobalExcludeAbsPath(setting.Database.Path)
|
||||
log.Info("Skipping database")
|
||||
} else {
|
||||
tmpDir := ctx.String("tempdir")
|
||||
if _, err := os.Stat(tmpDir); os.IsNotExist(err) {
|
||||
fatal("Path does not exist: %s", tmpDir)
|
||||
}
|
||||
|
||||
dbDump, err := os.CreateTemp(tmpDir, "gitea-db.sql")
|
||||
if err != nil {
|
||||
fatal("Failed to create tmp file: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
_ = dbDump.Close()
|
||||
if err := util.Remove(dbDump.Name()); err != nil {
|
||||
log.Warn("Unable to remove temporary file: %s: Error: %v", dbDump.Name(), err)
|
||||
}
|
||||
}()
|
||||
|
||||
targetDBType := ctx.String("database")
|
||||
if len(targetDBType) > 0 && targetDBType != setting.Database.Type.String() {
|
||||
log.Info("Dumping database %s => %s...", setting.Database.Type, targetDBType)
|
||||
} else {
|
||||
log.Info("Dumping database...")
|
||||
}
|
||||
|
||||
if err := db.DumpDatabase(dbDump.Name(), targetDBType); err != nil {
|
||||
fatal("Failed to dump database: %v", err)
|
||||
}
|
||||
|
||||
if err = dumper.AddFile("gitea-db.sql", dbDump.Name()); err != nil {
|
||||
fatal("Failed to include gitea-db.sql: %v", err)
|
||||
}
|
||||
tmpDir := ctx.String("tempdir")
|
||||
if _, err := os.Stat(tmpDir); os.IsNotExist(err) {
|
||||
fatal("Path does not exist: %s", tmpDir)
|
||||
}
|
||||
|
||||
log.Info("Adding custom configuration file from %s", setting.CustomConf)
|
||||
if err = dumper.AddFile("app.ini", setting.CustomConf); err != nil {
|
||||
fatal("Failed to include specified app.ini: %v", err)
|
||||
dbDump, err := os.CreateTemp(tmpDir, "gitea-db.sql")
|
||||
if err != nil {
|
||||
fatal("Failed to create tmp file: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
_ = dbDump.Close()
|
||||
if err := util.Remove(dbDump.Name()); err != nil {
|
||||
log.Warn("Unable to remove temporary file: %s: Error: %v", dbDump.Name(), err)
|
||||
}
|
||||
}()
|
||||
|
||||
targetDBType := ctx.String("database")
|
||||
if len(targetDBType) > 0 && targetDBType != setting.Database.Type.String() {
|
||||
log.Info("Dumping database %s => %s...", setting.Database.Type, targetDBType)
|
||||
} else {
|
||||
log.Info("Dumping database...")
|
||||
}
|
||||
|
||||
if err := db.DumpDatabase(dbDump.Name(), targetDBType); err != nil {
|
||||
fatal("Failed to dump database: %v", err)
|
||||
}
|
||||
|
||||
if err := addFile(w, "gitea-db.sql", dbDump.Name(), verbose); err != nil {
|
||||
fatal("Failed to include gitea-db.sql: %v", err)
|
||||
}
|
||||
|
||||
if len(setting.CustomConf) > 0 {
|
||||
log.Info("Adding custom configuration file from %s", setting.CustomConf)
|
||||
if err := addFile(w, "app.ini", setting.CustomConf, verbose); err != nil {
|
||||
fatal("Failed to include specified app.ini: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if ctx.IsSet("skip-custom-dir") && ctx.Bool("skip-custom-dir") {
|
||||
@@ -236,8 +326,8 @@ func runDump(ctx *cli.Context) error {
|
||||
} else {
|
||||
customDir, err := os.Stat(setting.CustomPath)
|
||||
if err == nil && customDir.IsDir() {
|
||||
if is, _ := dump.IsSubdir(setting.AppDataPath, setting.CustomPath); !is {
|
||||
if err := dumper.AddRecursiveExclude("custom", setting.CustomPath, nil); err != nil {
|
||||
if is, _ := isSubdir(setting.AppDataPath, setting.CustomPath); !is {
|
||||
if err := addRecursiveExclude(w, "custom", setting.CustomPath, []string{absFileName}, verbose); err != nil {
|
||||
fatal("Failed to include custom: %v", err)
|
||||
}
|
||||
} else {
|
||||
@@ -274,7 +364,8 @@ func runDump(ctx *cli.Context) error {
|
||||
excludes = append(excludes, setting.Attachment.Storage.Path)
|
||||
excludes = append(excludes, setting.Packages.Storage.Path)
|
||||
excludes = append(excludes, setting.Log.RootPath)
|
||||
if err := dumper.AddRecursiveExclude("data", setting.AppDataPath, excludes); err != nil {
|
||||
excludes = append(excludes, absFileName)
|
||||
if err := addRecursiveExclude(w, "data", setting.AppDataPath, excludes, verbose); err != nil {
|
||||
fatal("Failed to include data directory: %v", err)
|
||||
}
|
||||
}
|
||||
@@ -286,7 +377,8 @@ func runDump(ctx *cli.Context) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return dumper.AddReader(object, info, path.Join("data", "attachments", objPath))
|
||||
|
||||
return addReader(w, object, info, path.Join("data", "attachments", objPath), verbose)
|
||||
}); err != nil {
|
||||
fatal("Failed to dump attachments: %v", err)
|
||||
}
|
||||
@@ -300,7 +392,8 @@ func runDump(ctx *cli.Context) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return dumper.AddReader(object, info, path.Join("data", "packages", objPath))
|
||||
|
||||
return addReader(w, object, info, path.Join("data", "packages", objPath), verbose)
|
||||
}); err != nil {
|
||||
fatal("Failed to dump packages: %v", err)
|
||||
}
|
||||
@@ -316,23 +409,80 @@ func runDump(ctx *cli.Context) error {
|
||||
log.Error("Unable to check if %s exists. Error: %v", setting.Log.RootPath, err)
|
||||
}
|
||||
if isExist {
|
||||
if err := dumper.AddRecursiveExclude("log", setting.Log.RootPath, nil); err != nil {
|
||||
if err := addRecursiveExclude(w, "log", setting.Log.RootPath, []string{absFileName}, verbose); err != nil {
|
||||
fatal("Failed to include log: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if outFileName == "-" {
|
||||
log.Info("Finish dumping to stdout")
|
||||
} else {
|
||||
if err = archiverWriter.Close(); err != nil {
|
||||
_ = os.Remove(outFileName)
|
||||
fatal("Failed to save %q: %v", outFileName, err)
|
||||
if fileName != "-" {
|
||||
if err = w.Close(); err != nil {
|
||||
_ = util.Remove(fileName)
|
||||
fatal("Failed to save %s: %v", fileName, err)
|
||||
}
|
||||
if err = os.Chmod(outFileName, 0o600); err != nil {
|
||||
|
||||
if err := os.Chmod(fileName, 0o600); err != nil {
|
||||
log.Info("Can't change file access permissions mask to 0600: %v", err)
|
||||
}
|
||||
log.Info("Finish dumping in file %s", outFileName)
|
||||
}
|
||||
|
||||
if fileName != "-" {
|
||||
log.Info("Finish dumping in file %s", fileName)
|
||||
} else {
|
||||
log.Info("Finish dumping to stdout")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// addRecursiveExclude zips absPath to specified insidePath inside writer excluding excludeAbsPath
|
||||
func addRecursiveExclude(w archiver.Writer, insidePath, absPath string, excludeAbsPath []string, verbose bool) error {
|
||||
absPath, err := filepath.Abs(absPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dir, err := os.Open(absPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer dir.Close()
|
||||
|
||||
files, err := dir.Readdir(0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, file := range files {
|
||||
currentAbsPath := path.Join(absPath, file.Name())
|
||||
currentInsidePath := path.Join(insidePath, file.Name())
|
||||
if file.IsDir() {
|
||||
if !util.SliceContainsString(excludeAbsPath, currentAbsPath) {
|
||||
if err := addFile(w, currentInsidePath, currentAbsPath, false); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = addRecursiveExclude(w, currentInsidePath, currentAbsPath, excludeAbsPath, verbose); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// only copy regular files and symlink regular files, skip non-regular files like socket/pipe/...
|
||||
shouldAdd := file.Mode().IsRegular()
|
||||
if !shouldAdd && file.Mode()&os.ModeSymlink == os.ModeSymlink {
|
||||
target, err := filepath.EvalSymlinks(currentAbsPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
targetStat, err := os.Stat(target)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
shouldAdd = targetStat.Mode().IsRegular()
|
||||
}
|
||||
if shouldAdd {
|
||||
if err = addFile(w, currentInsidePath, currentAbsPath, verbose); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -157,9 +157,9 @@ func runViewDo(c *cli.Context) error {
|
||||
}
|
||||
|
||||
if len(matchedAssetFiles) == 0 {
|
||||
return errors.New("no files matched the given pattern")
|
||||
return fmt.Errorf("no files matched the given pattern")
|
||||
} else if len(matchedAssetFiles) > 1 {
|
||||
return errors.New("too many files matched the given pattern, try to be more specific")
|
||||
return fmt.Errorf("too many files matched the given pattern, try to be more specific")
|
||||
}
|
||||
|
||||
data, err := matchedAssetFiles[0].fs.ReadFile(matchedAssetFiles[0].name)
|
||||
@@ -180,7 +180,7 @@ func runExtractDo(c *cli.Context) error {
|
||||
}
|
||||
|
||||
if c.NArg() == 0 {
|
||||
return errors.New("a list of pattern of files to extract is mandatory (e.g. '**' for all)")
|
||||
return fmt.Errorf("a list of pattern of files to extract is mandatory (e.g. '**' for all)")
|
||||
}
|
||||
|
||||
destdir := "."
|
||||
|
||||
@@ -18,7 +18,7 @@ var (
|
||||
// CmdGenerate represents the available generate sub-command.
|
||||
CmdGenerate = &cli.Command{
|
||||
Name: "generate",
|
||||
Usage: "Generate Gitea's secrets/keys/tokens",
|
||||
Usage: "Command line interface for running generators",
|
||||
Subcommands: []*cli.Command{
|
||||
subcmdSecret,
|
||||
},
|
||||
@@ -70,7 +70,7 @@ func runGenerateInternalToken(c *cli.Context) error {
|
||||
}
|
||||
|
||||
func runGenerateLfsJwtSecret(c *cli.Context) error {
|
||||
_, jwtSecretBase64, err := generate.NewJwtSecretWithBase64()
|
||||
_, jwtSecretBase64, err := generate.NewJwtSecretBase64()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
70
cmd/hook.go
70
cmd/hook.go
@@ -31,8 +31,8 @@ var (
|
||||
// CmdHook represents the available hooks sub-command.
|
||||
CmdHook = &cli.Command{
|
||||
Name: "hook",
|
||||
Usage: "(internal) Should only be called by Git",
|
||||
Description: "Delegate commands to corresponding Git hooks",
|
||||
Usage: "Delegate commands to corresponding Git hooks",
|
||||
Description: "This should only be called by Git",
|
||||
Before: PrepareConsoleLoggerLevel(log.FATAL),
|
||||
Subcommands: []*cli.Command{
|
||||
subcmdHookPreReceive,
|
||||
@@ -220,7 +220,10 @@ Gitea or set your environment appropriately.`, "")
|
||||
}
|
||||
}
|
||||
|
||||
supportProcReceive := git.DefaultFeatures().SupportProcReceive
|
||||
supportProcReceive := false
|
||||
if git.CheckGitVersionAtLeast("2.29") == nil {
|
||||
supportProcReceive = true
|
||||
}
|
||||
|
||||
for scanner.Scan() {
|
||||
// TODO: support news feeds for wiki
|
||||
@@ -290,22 +293,8 @@ Gitea or set your environment appropriately.`, "")
|
||||
return nil
|
||||
}
|
||||
|
||||
// runHookUpdate avoid to do heavy operations on update hook because it will be
|
||||
// invoked for every ref update which does not like pre-receive and post-receive
|
||||
func runHookUpdate(c *cli.Context) error {
|
||||
if isInternal, _ := strconv.ParseBool(os.Getenv(repo_module.EnvIsInternal)); isInternal {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Update is empty and is kept only for backwards compatibility
|
||||
if len(os.Args) < 3 {
|
||||
return nil
|
||||
}
|
||||
refName := git.RefName(os.Args[len(os.Args)-3])
|
||||
if refName.IsPull() {
|
||||
// ignore update to refs/pull/xxx/head, so we don't need to output any information
|
||||
os.Exit(1)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -352,7 +341,6 @@ Gitea or set your environment appropriately.`, "")
|
||||
isWiki, _ := strconv.ParseBool(os.Getenv(repo_module.EnvRepoIsWiki))
|
||||
repoName := os.Getenv(repo_module.EnvRepoName)
|
||||
pusherID, _ := strconv.ParseInt(os.Getenv(repo_module.EnvPusherID), 10, 64)
|
||||
prID, _ := strconv.ParseInt(os.Getenv(repo_module.EnvPRID), 10, 64)
|
||||
pusherName := os.Getenv(repo_module.EnvPusherName)
|
||||
|
||||
hookOptions := private.HookOptions{
|
||||
@@ -362,8 +350,6 @@ Gitea or set your environment appropriately.`, "")
|
||||
GitObjectDirectory: os.Getenv(private.GitObjectDirectory),
|
||||
GitQuarantinePath: os.Getenv(private.GitQuarantinePath),
|
||||
GitPushOptions: pushOptions(),
|
||||
PullRequestID: prID,
|
||||
PushTrigger: repo_module.PushTrigger(os.Getenv(repo_module.EnvPushTrigger)),
|
||||
}
|
||||
oldCommitIDs := make([]string, hookBatchSize)
|
||||
newCommitIDs := make([]string, hookBatchSize)
|
||||
@@ -390,9 +376,7 @@ Gitea or set your environment appropriately.`, "")
|
||||
oldCommitIDs[count] = string(fields[0])
|
||||
newCommitIDs[count] = string(fields[1])
|
||||
refFullNames[count] = git.RefName(fields[2])
|
||||
|
||||
commitID, _ := git.NewIDFromString(newCommitIDs[count])
|
||||
if refFullNames[count] == git.BranchPrefix+"master" && !commitID.IsZero() && count == total {
|
||||
if refFullNames[count] == git.BranchPrefix+"master" && newCommitIDs[count] != git.EmptySHA && count == total {
|
||||
masterPushed = true
|
||||
}
|
||||
count++
|
||||
@@ -462,24 +446,21 @@ Gitea or set your environment appropriately.`, "")
|
||||
|
||||
func hookPrintResults(results []private.HookPostReceiveBranchResult) {
|
||||
for _, res := range results {
|
||||
hookPrintResult(res.Message, res.Create, res.Branch, res.URL)
|
||||
}
|
||||
}
|
||||
if !res.Message {
|
||||
continue
|
||||
}
|
||||
|
||||
func hookPrintResult(output, isCreate bool, branch, url string) {
|
||||
if !output {
|
||||
return
|
||||
fmt.Fprintln(os.Stderr, "")
|
||||
if res.Create {
|
||||
fmt.Fprintf(os.Stderr, "Create a new pull request for '%s':\n", res.Branch)
|
||||
fmt.Fprintf(os.Stderr, " %s\n", res.URL)
|
||||
} else {
|
||||
fmt.Fprint(os.Stderr, "Visit the existing pull request:\n")
|
||||
fmt.Fprintf(os.Stderr, " %s\n", res.URL)
|
||||
}
|
||||
fmt.Fprintln(os.Stderr, "")
|
||||
os.Stderr.Sync()
|
||||
}
|
||||
fmt.Fprintln(os.Stderr, "")
|
||||
if isCreate {
|
||||
fmt.Fprintf(os.Stderr, "Create a new pull request for '%s':\n", branch)
|
||||
fmt.Fprintf(os.Stderr, " %s\n", url)
|
||||
} else {
|
||||
fmt.Fprint(os.Stderr, "Visit the existing pull request:\n")
|
||||
fmt.Fprintf(os.Stderr, " %s\n", url)
|
||||
}
|
||||
fmt.Fprintln(os.Stderr, "")
|
||||
_ = os.Stderr.Sync()
|
||||
}
|
||||
|
||||
func pushOptions() map[string]string {
|
||||
@@ -511,7 +492,7 @@ Gitea or set your environment appropriately.`, "")
|
||||
return nil
|
||||
}
|
||||
|
||||
if !git.DefaultFeatures().SupportProcReceive {
|
||||
if git.CheckGitVersionAtLeast("2.29") != nil {
|
||||
return fail(ctx, "No proc-receive support", "current git version doesn't support proc-receive.")
|
||||
}
|
||||
|
||||
@@ -688,8 +669,7 @@ Gitea or set your environment appropriately.`, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
commitID, _ := git.NewIDFromString(rs.OldOID)
|
||||
if !commitID.IsZero() {
|
||||
if rs.OldOID != git.EmptySHA {
|
||||
err = writeDataPktLine(ctx, os.Stdout, []byte("option old-oid "+rs.OldOID))
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -708,12 +688,6 @@ Gitea or set your environment appropriately.`, "")
|
||||
}
|
||||
err = writeFlushPktLine(ctx, os.Stdout)
|
||||
|
||||
if err == nil {
|
||||
for _, res := range resp.Results {
|
||||
hookPrintResult(res.ShouldShowMessage, res.IsCreatePR, res.HeadBranch, res.URL)
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
13
cmd/keys.go
13
cmd/keys.go
@@ -16,11 +16,10 @@ import (
|
||||
|
||||
// CmdKeys represents the available keys sub-command
|
||||
var CmdKeys = &cli.Command{
|
||||
Name: "keys",
|
||||
Usage: "(internal) Should only be called by SSH server",
|
||||
Description: "Queries the Gitea database to get the authorized command for a given ssh key fingerprint",
|
||||
Before: PrepareConsoleLoggerLevel(log.FATAL),
|
||||
Action: runKeys,
|
||||
Name: "keys",
|
||||
Usage: "This command queries the Gitea database to get the authorized command for a given ssh key fingerprint",
|
||||
Before: PrepareConsoleLoggerLevel(log.FATAL),
|
||||
Action: runKeys,
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "expected",
|
||||
@@ -71,13 +70,13 @@ func runKeys(c *cli.Context) error {
|
||||
ctx, cancel := installSignals()
|
||||
defer cancel()
|
||||
|
||||
setup(ctx, c.Bool("debug"))
|
||||
setup(ctx, false)
|
||||
|
||||
authorizedString, extra := private.AuthorizedPublicKeyByContent(ctx, content)
|
||||
// do not use handleCliResponseExtra or cli.NewExitError, if it exists immediately, it breaks some tests like Test_CmdKeys
|
||||
if extra.Error != nil {
|
||||
return extra.Error
|
||||
}
|
||||
_, _ = fmt.Fprintln(c.App.Writer, strings.TrimSpace(authorizedString.Text))
|
||||
_, _ = fmt.Fprintln(c.App.Writer, strings.TrimSpace(authorizedString))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -45,6 +45,6 @@ func runSendMail(c *cli.Context) error {
|
||||
if extra.HasError() {
|
||||
return handleCliResponseExtra(extra)
|
||||
}
|
||||
_, _ = fmt.Printf("Sent %s email(s) to all users\n", respText.Text)
|
||||
_, _ = fmt.Printf("Sent %s email(s) to all users\n", respText)
|
||||
return nil
|
||||
}
|
||||
|
||||
30
cmd/main.go
30
cmd/main.go
@@ -10,12 +10,12 @@ import (
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// cmdHelp is our own help subcommand with more information
|
||||
// Keep in mind that the "./gitea help"(subcommand) is different from "./gitea --help"(flag), the flag doesn't parse the config or output "DEFAULT CONFIGURATION:" information
|
||||
func cmdHelp() *cli.Command {
|
||||
c := &cli.Command{
|
||||
Name: "help",
|
||||
@@ -47,10 +47,16 @@ DEFAULT CONFIGURATION:
|
||||
return c
|
||||
}
|
||||
|
||||
var helpFlag = cli.HelpFlag
|
||||
|
||||
func init() {
|
||||
// cli.HelpFlag = nil TODO: after https://github.com/urfave/cli/issues/1794 we can use this
|
||||
}
|
||||
|
||||
func appGlobalFlags() []cli.Flag {
|
||||
return []cli.Flag{
|
||||
// make the builtin flags at the top
|
||||
cli.HelpFlag,
|
||||
helpFlag,
|
||||
|
||||
// shared configuration flags, they are for global and for each sub-command at the same time
|
||||
// eg: such command is valid: "./gitea --config /tmp/app.ini web --config /tmp/app.ini", while it's discouraged indeed
|
||||
@@ -112,30 +118,23 @@ func prepareWorkPathAndCustomConf(action cli.ActionFunc) func(ctx *cli.Context)
|
||||
}
|
||||
}
|
||||
|
||||
type AppVersion struct {
|
||||
Version string
|
||||
Extra string
|
||||
}
|
||||
|
||||
func NewMainApp(appVer AppVersion) *cli.App {
|
||||
func NewMainApp(version, versionExtra string) *cli.App {
|
||||
app := cli.NewApp()
|
||||
app.Name = "Gitea"
|
||||
app.HelpName = "gitea"
|
||||
app.Usage = "A painless self-hosted Git service"
|
||||
app.Description = `Gitea program contains "web" and other subcommands. If no subcommand is given, it starts the web server by default. Use "web" subcommand for more web server arguments, use other subcommands for other purposes.`
|
||||
app.Version = appVer.Version + appVer.Extra
|
||||
app.Description = `By default, Gitea will start serving using the web-server with no argument, which can alternatively be run by running the subcommand "web".`
|
||||
app.Version = version + versionExtra
|
||||
app.EnableBashCompletion = true
|
||||
|
||||
// these sub-commands need to use config file
|
||||
subCmdWithConfig := []*cli.Command{
|
||||
cmdHelp(), // the "help" sub-command was used to show the more information for "work path" and "custom config"
|
||||
CmdWeb,
|
||||
CmdServ,
|
||||
CmdHook,
|
||||
CmdKeys,
|
||||
CmdDump,
|
||||
CmdAdmin,
|
||||
CmdMigrate,
|
||||
CmdKeys,
|
||||
CmdDoctor,
|
||||
CmdManager,
|
||||
CmdEmbedded,
|
||||
@@ -143,8 +142,13 @@ func NewMainApp(appVer AppVersion) *cli.App {
|
||||
CmdDumpRepository,
|
||||
CmdRestoreRepository,
|
||||
CmdActions,
|
||||
cmdHelp(), // the "help" sub-command was used to show the more information for "work path" and "custom config"
|
||||
}
|
||||
|
||||
cmdConvert := util.ToPointer(*cmdDoctorConvert)
|
||||
cmdConvert.Hidden = true // still support the legacy "./gitea doctor" by the hidden sub-command, remove it in next release
|
||||
subCmdWithConfig = append(subCmdWithConfig, cmdConvert)
|
||||
|
||||
// these sub-commands do not need the config file, and they do not depend on any path or environment variable.
|
||||
subCmdStandalone := []*cli.Command{
|
||||
CmdCert,
|
||||
|
||||
@@ -20,7 +20,9 @@ import (
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m)
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: "..",
|
||||
})
|
||||
}
|
||||
|
||||
func makePathOutput(workPath, customPath, customConf string) string {
|
||||
@@ -28,7 +30,7 @@ func makePathOutput(workPath, customPath, customConf string) string {
|
||||
}
|
||||
|
||||
func newTestApp(testCmdAction func(ctx *cli.Context) error) *cli.App {
|
||||
app := NewMainApp(AppVersion{})
|
||||
app := NewMainApp("version", "version-extra")
|
||||
testCmd := &cli.Command{Name: "test-cmd", Action: testCmdAction}
|
||||
prepareSubcommandWithConfig(testCmd, appGlobalFlags())
|
||||
app.Commands = append(app.Commands, testCmd)
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
@@ -250,7 +249,7 @@ func runAddFileLogger(c *cli.Context) error {
|
||||
if c.IsSet("filename") {
|
||||
vals["filename"] = c.String("filename")
|
||||
} else {
|
||||
return errors.New("filename must be set when creating a file logger")
|
||||
return fmt.Errorf("filename must be set when creating a file logger")
|
||||
}
|
||||
if c.IsSet("rotate") {
|
||||
vals["rotate"] = c.Bool("rotate")
|
||||
|
||||
@@ -5,9 +5,7 @@ package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"strings"
|
||||
|
||||
actions_model "code.gitea.io/gitea/models/actions"
|
||||
@@ -36,7 +34,7 @@ var CmdMigrateStorage = &cli.Command{
|
||||
Name: "type",
|
||||
Aliases: []string{"t"},
|
||||
Value: "",
|
||||
Usage: "Type of stored files to copy. Allowed types: 'attachments', 'lfs', 'avatars', 'repo-avatars', 'repo-archivers', 'packages', 'actions-log', 'actions-artifacts",
|
||||
Usage: "Type of stored files to copy. Allowed types: 'attachments', 'lfs', 'avatars', 'repo-avatars', 'repo-archivers', 'packages', 'actions-log'",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "storage",
|
||||
@@ -112,9 +110,6 @@ func migrateLFS(ctx context.Context, dstStorage storage.ObjectStorage) error {
|
||||
|
||||
func migrateAvatars(ctx context.Context, dstStorage storage.ObjectStorage) error {
|
||||
return db.Iterate(ctx, nil, func(ctx context.Context, user *user_model.User) error {
|
||||
if user.CustomAvatarRelativePath() == "" {
|
||||
return nil
|
||||
}
|
||||
_, err := storage.Copy(dstStorage, user.CustomAvatarRelativePath(), storage.Avatars, user.CustomAvatarRelativePath())
|
||||
return err
|
||||
})
|
||||
@@ -122,9 +117,6 @@ func migrateAvatars(ctx context.Context, dstStorage storage.ObjectStorage) error
|
||||
|
||||
func migrateRepoAvatars(ctx context.Context, dstStorage storage.ObjectStorage) error {
|
||||
return db.Iterate(ctx, nil, func(ctx context.Context, repo *repo_model.Repository) error {
|
||||
if repo.CustomAvatarRelativePath() == "" {
|
||||
return nil
|
||||
}
|
||||
_, err := storage.Copy(dstStorage, repo.CustomAvatarRelativePath(), storage.RepoAvatars, repo.CustomAvatarRelativePath())
|
||||
return err
|
||||
})
|
||||
@@ -162,25 +154,6 @@ func migrateActionsLog(ctx context.Context, dstStorage storage.ObjectStorage) er
|
||||
})
|
||||
}
|
||||
|
||||
func migrateActionsArtifacts(ctx context.Context, dstStorage storage.ObjectStorage) error {
|
||||
return db.Iterate(ctx, nil, func(ctx context.Context, artifact *actions_model.ActionArtifact) error {
|
||||
if artifact.Status == int64(actions_model.ArtifactStatusExpired) {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err := storage.Copy(dstStorage, artifact.StoragePath, storage.ActionsArtifacts, artifact.StoragePath)
|
||||
if err != nil {
|
||||
// ignore files that do not exist
|
||||
if errors.Is(err, fs.ErrNotExist) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func runMigrateStorage(ctx *cli.Context) error {
|
||||
stdCtx, cancel := installSignals()
|
||||
defer cancel()
|
||||
@@ -244,14 +217,13 @@ func runMigrateStorage(ctx *cli.Context) error {
|
||||
}
|
||||
|
||||
migratedMethods := map[string]func(context.Context, storage.ObjectStorage) error{
|
||||
"attachments": migrateAttachments,
|
||||
"lfs": migrateLFS,
|
||||
"avatars": migrateAvatars,
|
||||
"repo-avatars": migrateRepoAvatars,
|
||||
"repo-archivers": migrateRepoArchivers,
|
||||
"packages": migratePackages,
|
||||
"actions-log": migrateActionsLog,
|
||||
"actions-artifacts": migrateActionsArtifacts,
|
||||
"attachments": migrateAttachments,
|
||||
"lfs": migrateLFS,
|
||||
"avatars": migrateAvatars,
|
||||
"repo-avatars": migrateRepoAvatars,
|
||||
"repo-archivers": migrateRepoArchivers,
|
||||
"packages": migratePackages,
|
||||
"actions-log": migrateActionsLog,
|
||||
}
|
||||
|
||||
tp := strings.ToLower(ctx.String("type"))
|
||||
|
||||
29
cmd/serv.go
29
cmd/serv.go
@@ -42,7 +42,7 @@ const (
|
||||
// CmdServ represents the available serv sub-command.
|
||||
var CmdServ = &cli.Command{
|
||||
Name: "serv",
|
||||
Usage: "(internal) Should only be called by SSH shell",
|
||||
Usage: "This command should only be called by SSH shell",
|
||||
Description: "Serv provides access auth for repositories",
|
||||
Before: PrepareConsoleLoggerLevel(log.FATAL),
|
||||
Action: runServ,
|
||||
@@ -63,10 +63,21 @@ func setup(ctx context.Context, debug bool) {
|
||||
setupConsoleLogger(log.FATAL, false, os.Stderr)
|
||||
}
|
||||
setting.MustInstalled()
|
||||
if debug {
|
||||
setting.RunMode = "dev"
|
||||
}
|
||||
|
||||
// Check if setting.RepoRootPath exists. It could be the case that it doesn't exist, this can happen when
|
||||
// `[repository]` `ROOT` is a relative path and $GITEA_WORK_DIR isn't passed to the SSH connection.
|
||||
if _, err := os.Stat(setting.RepoRootPath); err != nil {
|
||||
_ = fail(ctx, "Unable to access repository path", "Unable to access repository path %q, err: %v", setting.RepoRootPath, err)
|
||||
if os.IsNotExist(err) {
|
||||
_ = fail(ctx, "Incorrect configuration, no repository directory.", "Directory `[repository].ROOT` %q was not found, please check if $GITEA_WORK_DIR is passed to the SSH connection or make `[repository].ROOT` an absolute value.", setting.RepoRootPath)
|
||||
} else {
|
||||
_ = fail(ctx, "Incorrect configuration, repository directory is inaccessible", "Directory `[repository].ROOT` %q is inaccessible. err: %v", setting.RepoRootPath, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if err := git.InitSimple(context.Background()); err != nil {
|
||||
_ = fail(ctx, "Failed to init git", "Failed to init git, err: %v", err)
|
||||
}
|
||||
@@ -178,7 +189,7 @@ func runServ(c *cli.Context) error {
|
||||
}
|
||||
|
||||
if len(words) < 2 {
|
||||
if git.DefaultFeatures().SupportProcReceive {
|
||||
if git.CheckGitVersionAtLeast("2.29") == nil {
|
||||
// for AGit Flow
|
||||
if cmd == "ssh_info" {
|
||||
fmt.Print(`{"type":"gitea","version":1}`)
|
||||
@@ -205,18 +216,16 @@ func runServ(c *cli.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
// LowerCase and trim the repoPath as that's how they are stored.
|
||||
repoPath = strings.ToLower(strings.TrimSpace(repoPath))
|
||||
|
||||
rr := strings.SplitN(repoPath, "/", 2)
|
||||
if len(rr) != 2 {
|
||||
return fail(ctx, "Invalid repository path", "Invalid repository path: %v", repoPath)
|
||||
}
|
||||
|
||||
username := rr[0]
|
||||
reponame := strings.TrimSuffix(rr[1], ".git")
|
||||
|
||||
// LowerCase and trim the repoPath as that's how they are stored.
|
||||
// This should be done after splitting the repoPath into username and reponame
|
||||
// so that username and reponame are not affected.
|
||||
repoPath = strings.ToLower(strings.TrimSpace(repoPath))
|
||||
username := strings.ToLower(rr[0])
|
||||
reponame := strings.ToLower(strings.TrimSuffix(rr[1], ".git"))
|
||||
|
||||
if alphaDashDotPattern.MatchString(reponame) {
|
||||
return fail(ctx, "Invalid repo name", "Invalid repo name: %s", reponame)
|
||||
|
||||
@@ -114,7 +114,7 @@ func showWebStartupMessage(msg string) {
|
||||
log.Info("* WorkPath: %s", setting.AppWorkPath)
|
||||
log.Info("* CustomPath: %s", setting.CustomPath)
|
||||
log.Info("* ConfigFile: %s", setting.CustomConf)
|
||||
log.Info("%s", msg) // show startup message
|
||||
log.Info("%s", msg)
|
||||
}
|
||||
|
||||
func serveInstall(ctx *cli.Context) error {
|
||||
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/google/go-github/v57/github"
|
||||
"github.com/google/go-github/v53/github"
|
||||
"github.com/urfave/cli/v2"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
@@ -47,28 +47,24 @@ func main() {
|
||||
on the configuration cheat sheet.`
|
||||
app.Flags = []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "custom-path",
|
||||
Aliases: []string{"C"},
|
||||
Value: setting.CustomPath,
|
||||
Usage: "Custom path file path",
|
||||
Name: "custom-path, C",
|
||||
Value: setting.CustomPath,
|
||||
Usage: "Custom path file path",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "config",
|
||||
Aliases: []string{"c"},
|
||||
Value: setting.CustomConf,
|
||||
Usage: "Custom configuration file path",
|
||||
Name: "config, c",
|
||||
Value: setting.CustomConf,
|
||||
Usage: "Custom configuration file path",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "work-path",
|
||||
Aliases: []string{"w"},
|
||||
Value: setting.AppWorkPath,
|
||||
Usage: "Set the gitea working path",
|
||||
Name: "work-path, w",
|
||||
Value: setting.AppWorkPath,
|
||||
Usage: "Set the gitea working path",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "out",
|
||||
Aliases: []string{"o"},
|
||||
Value: "",
|
||||
Usage: "Destination file to write to",
|
||||
Name: "out, o",
|
||||
Value: "",
|
||||
Usage: "Destination file to write to",
|
||||
},
|
||||
}
|
||||
app.Action = runEnvironmentToIni
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -19,7 +18,7 @@ import (
|
||||
|
||||
var (
|
||||
generators = []struct {
|
||||
gen func(ctx context.Context) (string, error)
|
||||
gen func() (string, error)
|
||||
name string
|
||||
}{
|
||||
{
|
||||
@@ -42,17 +41,16 @@ func main() {
|
||||
fmt.Printf("PrepareTestDatabase: %+v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
ctx := context.Background()
|
||||
if len(os.Args) == 0 {
|
||||
for _, r := range os.Args {
|
||||
if err := generate(ctx, r); err != nil {
|
||||
if err := generate(r); err != nil {
|
||||
fmt.Printf("generate '%s': %+v\n", r, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for _, g := range generators {
|
||||
if err := generate(ctx, g.name); err != nil {
|
||||
if err := generate(g.name); err != nil {
|
||||
fmt.Printf("generate '%s': %+v\n", g.name, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
@@ -60,10 +58,10 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
func generate(ctx context.Context, name string) error {
|
||||
func generate(name string) error {
|
||||
for _, g := range generators {
|
||||
if g.name == name {
|
||||
data, err := g.gen(ctx)
|
||||
data, err := g.gen()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
[Unit]
|
||||
Description=Gitea (Git with a cup of tea)
|
||||
After=syslog.target
|
||||
After=network.target
|
||||
###
|
||||
# Don't forget to add the database service dependencies
|
||||
@@ -51,7 +52,7 @@ After=network.target
|
||||
# Uncomment the next line if you have repos with lots of files and get a HTTP 500 error because of that
|
||||
# LimitNOFILE=524288:524288
|
||||
RestartSec=2s
|
||||
Type=simple
|
||||
Type=notify
|
||||
User=git
|
||||
Group=git
|
||||
WorkingDirectory=/var/lib/gitea/
|
||||
@@ -61,6 +62,7 @@ WorkingDirectory=/var/lib/gitea/
|
||||
ExecStart=/usr/local/bin/gitea web --config /etc/gitea/app.ini
|
||||
Restart=always
|
||||
Environment=USER=git HOME=/home/git GITEA_WORK_DIR=/var/lib/gitea
|
||||
WatchdogSec=30s
|
||||
# If you install Git to directory prefix other than default PATH (which happens
|
||||
# for example if you install other versions of Git side-to-side with
|
||||
# distribution version), uncomment below line and add that prefix to PATH
|
||||
|
||||
12
crowdin.yml
12
crowdin.yml
@@ -1,12 +0,0 @@
|
||||
project_id_env: CROWDIN_PROJECT_ID
|
||||
api_token_env: CROWDIN_KEY
|
||||
base_path: "."
|
||||
base_url: "https://api.crowdin.com"
|
||||
preserve_hierarchy: true
|
||||
files:
|
||||
- source: "/options/locale/locale_en-US.ini"
|
||||
translation: "/options/locale/locale_%locale%.ini"
|
||||
type: "ini"
|
||||
skip_untranslated_strings: true
|
||||
export_only_approved: true
|
||||
update_option: "update_as_unapproved"
|
||||
@@ -60,7 +60,6 @@ RUN_USER = ; git
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;
|
||||
;; The protocol the server listens on. One of 'http', 'https', 'http+unix', 'fcgi' or 'fcgi+unix'. Defaults to 'http'
|
||||
;; Note: Value must be lowercase.
|
||||
;PROTOCOL = http
|
||||
;;
|
||||
;; Expect PROXY protocol headers on connections
|
||||
@@ -234,7 +233,7 @@ RUN_USER = ; git
|
||||
;MINIMUM_KEY_SIZE_CHECK = false
|
||||
;;
|
||||
;; Disable CDN even in "prod" mode
|
||||
;OFFLINE_MODE = true
|
||||
;OFFLINE_MODE = false
|
||||
;;
|
||||
;; TLS Settings: Either ACME or manual
|
||||
;; (Other common TLS configuration are found before)
|
||||
@@ -351,7 +350,6 @@ NAME = gitea
|
||||
USER = root
|
||||
;PASSWD = ;Use PASSWD = `your password` for quoting if you use special characters in the password.
|
||||
;SSL_MODE = false ; either "false" (default), "true", or "skip-verify"
|
||||
;CHARSET_COLLATION = ; Empty as default, Gitea will try to find a case-sensitive collation. Don't change it unless you clearly know what you need.
|
||||
;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;
|
||||
@@ -383,7 +381,6 @@ USER = root
|
||||
;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.
|
||||
;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;
|
||||
@@ -412,10 +409,6 @@ USER = root
|
||||
;;
|
||||
;; Whether execute database models migrations automatically
|
||||
;AUTO_MIGRATION = true
|
||||
;;
|
||||
;; Threshold value (in seconds) beyond which query execution time is logged as a warning in the xorm logger
|
||||
;;
|
||||
;SLOW_QUERY_THRESHOLD = 5s
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
@@ -435,13 +428,13 @@ SECRET_KEY =
|
||||
;SECRET_KEY_URI = file:/etc/gitea/secret_key
|
||||
;;
|
||||
;; Secret used to validate communication within Gitea binary.
|
||||
INTERNAL_TOKEN =
|
||||
INTERNAL_TOKEN=
|
||||
;;
|
||||
;; Alternative location to specify internal token, instead of this file; you cannot specify both this and INTERNAL_TOKEN, and must pick one
|
||||
;INTERNAL_TOKEN_URI = file:/etc/gitea/internal_token
|
||||
;;
|
||||
;; How long to remember that a user is logged in before requiring relogin (in days)
|
||||
;LOGIN_REMEMBER_DAYS = 31
|
||||
;LOGIN_REMEMBER_DAYS = 7
|
||||
;;
|
||||
;; Name of the cookie used to store the current username.
|
||||
;COOKIE_USERNAME = gitea_awesome
|
||||
@@ -498,11 +491,6 @@ INTERNAL_TOKEN =
|
||||
;; Cache successful token hashes. API tokens are stored in the DB as pbkdf2 hashes however, this means that there is a potentially significant hashing load when there are multiple API operations.
|
||||
;; This cache will store the successfully hashed tokens in a LRU cache as a balance between performance and security.
|
||||
;SUCCESSFUL_TOKENS_CACHE_SIZE = 20
|
||||
;;
|
||||
;; Reject API tokens sent in URL query string (Accept Header-based API tokens only). This avoids security vulnerabilities
|
||||
;; stemming from cached/logged plain-text API tokens.
|
||||
;; In future releases, this will become the default behavior
|
||||
;DISABLE_QUERY_AUTH_TOKEN = false
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
@@ -528,7 +516,7 @@ INTERNAL_TOKEN =
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;
|
||||
;; Enables OAuth2 provider
|
||||
ENABLED = true
|
||||
ENABLE = true
|
||||
;;
|
||||
;; Algorithm used to sign OAuth2 tokens. Valid values: HS256, HS384, HS512, RS256, RS384, RS512, ES256, ES384, ES512, EdDSA
|
||||
;JWT_SIGNING_ALGORITHM = RS256
|
||||
@@ -560,8 +548,7 @@ ENABLED = true
|
||||
;; Pre-register OAuth2 applications for some universally useful services
|
||||
;; * https://github.com/hickford/git-credential-oauth
|
||||
;; * https://github.com/git-ecosystem/git-credential-manager
|
||||
;; * https://gitea.com/gitea/tea
|
||||
;DEFAULT_APPLICATIONS = git-credential-oauth, git-credential-manager, tea
|
||||
;DEFAULT_APPLICATIONS = git-credential-oauth, git-credential-manager
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
@@ -956,12 +943,6 @@ LEVEL = Info
|
||||
;GO_GET_CLONE_URL_PROTOCOL = https
|
||||
;;
|
||||
;; Close issues as long as a commit on any branch marks it as fixed
|
||||
;DEFAULT_CLOSE_ISSUES_VIA_COMMITS_IN_ANY_BRANCH = false
|
||||
;;
|
||||
;; Allow users to push local repositories to Gitea and have them automatically created for a user or an org
|
||||
;ENABLE_PUSH_CREATE_USER = false
|
||||
;ENABLE_PUSH_CREATE_ORG = false
|
||||
;;
|
||||
;; Comma separated list of globally disabled repo units. Allowed values: repo.issues, repo.ext_issues, repo.pulls, repo.wiki, repo.ext_wiki, repo.projects, repo.packages, repo.actions.
|
||||
;DISABLED_REPO_UNITS =
|
||||
;;
|
||||
@@ -969,7 +950,7 @@ LEVEL = Info
|
||||
;; Note: Code and Releases can currently not be deactivated. If you specify default repo units you should still list them for future compatibility.
|
||||
;; External wiki and issue tracker can't be enabled by default as it requires additional settings.
|
||||
;; Disabled repo units will not be added to new repositories regardless if it is in the default list.
|
||||
;DEFAULT_REPO_UNITS = repo.code,repo.releases,repo.issues,repo.pulls,repo.wiki,repo.projects,repo.packages,repo.actions
|
||||
;DEFAULT_REPO_UNITS = repo.code,repo.releases,repo.issues,repo.pulls,repo.wiki,repo.projects,repo.packages
|
||||
;;
|
||||
;; Comma separated list of default forked repo units.
|
||||
;; The set of allowed values and rules are the same as DEFAULT_REPO_UNITS.
|
||||
@@ -1033,8 +1014,8 @@ LEVEL = Info
|
||||
;; 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 =
|
||||
;;
|
||||
;; Max size of each file in megabytes. Defaults to 50MB
|
||||
;FILE_MAX_SIZE = 50
|
||||
;; Max size of each file in megabytes. Defaults to 3MB
|
||||
;FILE_MAX_SIZE = 3
|
||||
;;
|
||||
;; Max number of files per upload. Defaults to 5
|
||||
;MAX_FILES = 5
|
||||
@@ -1054,7 +1035,7 @@ LEVEL = Info
|
||||
;; List of keywords used in Pull Request comments to automatically reopen a related issue
|
||||
;REOPEN_KEYWORDS = reopen,reopens,reopened
|
||||
;;
|
||||
;; Set default merge style for repository creating, valid options: merge, rebase, rebase-merge, squash, fast-forward-only
|
||||
;; Set default merge style for repository creating, valid options: merge, rebase, rebase-merge, squash
|
||||
;DEFAULT_MERGE_STYLE = merge
|
||||
;;
|
||||
;; In the default merge message for squash commits include at most this many commits
|
||||
@@ -1077,9 +1058,6 @@ LEVEL = Info
|
||||
;;
|
||||
;; In addition to testing patches using the three-way merge method, re-test conflicting patches with git apply
|
||||
;TEST_CONFLICTING_PATCHES_WITH_GIT_APPLY = false
|
||||
;;
|
||||
;; Retarget child pull requests to the parent pull request branch target on merge of parent pull request. It only works on merged PRs where the head and base branch target the same repo.
|
||||
;RETARGET_CHILDREN_ON_MERGE = true
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
@@ -1173,9 +1151,15 @@ LEVEL = Info
|
||||
;; enable cors headers (disabled by default)
|
||||
;ENABLED = false
|
||||
;;
|
||||
;; list of requesting origins that are allowed, eg: "https://*.example.com"
|
||||
;; scheme of allowed requests
|
||||
;SCHEME = http
|
||||
;;
|
||||
;; list of requesting domains that are allowed
|
||||
;ALLOW_DOMAIN = *
|
||||
;;
|
||||
;; allow subdomains of headers listed above to request
|
||||
;ALLOW_SUBDOMAIN = false
|
||||
;;
|
||||
;; list of methods allowed to request
|
||||
;METHODS = GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS
|
||||
;;
|
||||
@@ -1221,27 +1205,20 @@ LEVEL = Info
|
||||
;; Max size of files to be displayed (default is 8MiB)
|
||||
;MAX_DISPLAY_FILE_SIZE = 8388608
|
||||
;;
|
||||
;; Detect ambiguous unicode characters in file contents and show warnings on the UI
|
||||
;AMBIGUOUS_UNICODE_DETECTION = true
|
||||
;;
|
||||
;; Whether the email of the user should be shown in the Explore Users page
|
||||
;SHOW_USER_EMAIL = true
|
||||
;;
|
||||
;; Set the default theme for the Gitea install
|
||||
;DEFAULT_THEME = gitea-auto
|
||||
;DEFAULT_THEME = auto
|
||||
;;
|
||||
;; All available themes. Allow users select personalized themes regardless of the value of `DEFAULT_THEME`.
|
||||
;; Leave it empty to allow users to select any theme from "{CustomPath}/public/assets/css/theme-*.css"
|
||||
;THEMES =
|
||||
;THEMES = auto,gitea,arc-green
|
||||
;;
|
||||
;; All available reactions users can choose on issues/prs and comments.
|
||||
;; Values can be emoji alias (:smile:) or a unicode emoji.
|
||||
;; For custom reactions, add a tightly cropped square image to public/assets/img/emoji/reaction_name.png
|
||||
;REACTIONS = +1, -1, laugh, hooray, confused, heart, rocket, eyes
|
||||
;;
|
||||
;; Change the number of users that are displayed in reactions tooltip (triggered by mouse hover).
|
||||
;REACTION_MAX_USER_NUM = 10
|
||||
;;
|
||||
;; Additional Emojis not defined in the utf8 standard
|
||||
;; By default we support gitea (:gitea:), to add more copy them to public/assets/img/emoji/emoji_name.png and add it to this config.
|
||||
;; Dont mistake it for Reactions.
|
||||
@@ -1256,14 +1233,6 @@ LEVEL = Info
|
||||
;; Whether to only show relevant repos on the explore page when no keyword is specified and default sorting is used.
|
||||
;; A repo is considered irrelevant if it's a fork or if it has no metadata (no description, no icon, no topic).
|
||||
;ONLY_SHOW_RELEVANT_REPOS = false
|
||||
;;
|
||||
;; Change the sort type of the explore pages.
|
||||
;; Default is "recentupdate", but you also have "alphabetically", "reverselastlogin", "newest", "oldest".
|
||||
;EXPLORE_PAGING_DEFAULT_SORT = recentupdate
|
||||
;;
|
||||
;; The tense all timestamps should be rendered in. Possible values are `absolute` time (i.e. 1970-01-01, 11:59) and `mixed`.
|
||||
;; `mixed` means most timestamps are rendered in relative time (i.e. 2 days ago).
|
||||
;PREFERRED_TIMESTAMP_TENSE = mixed
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
@@ -1451,7 +1420,7 @@ LEVEL = Info
|
||||
;DATADIR = queues/ ; Relative paths will be made absolute against `%(APP_DATA_PATH)s`.
|
||||
;;
|
||||
;; Default queue length before a channel queue will block
|
||||
;LENGTH = 100000
|
||||
;LENGTH = 100
|
||||
;;
|
||||
;; Batch size to send for batched queues
|
||||
;BATCH_LENGTH = 20
|
||||
@@ -1481,16 +1450,6 @@ LEVEL = Info
|
||||
;;
|
||||
;; Default configuration for email notifications for users (user configurable). Options: enabled, onmention, disabled
|
||||
;DEFAULT_EMAIL_NOTIFICATIONS = enabled
|
||||
;; Disabled features for users, could be "deletion", "manage_ssh_keys","manage_gpg_keys" more features can be disabled in future
|
||||
;; - deletion: a user cannot delete their own account
|
||||
;; - manage_ssh_keys: a user cannot configure ssh keys
|
||||
;; - manage_gpg_keys: a user cannot configure gpg keys
|
||||
;USER_DISABLED_FEATURES =
|
||||
;; Comma separated list of disabled features ONLY if the user has an external login type (eg. LDAP, Oauth, etc.), could be `deletion`, `manage_ssh_keys`, `manage_gpg_keys`. This setting is independent from `USER_DISABLED_FEATURES` and supplements its behavior.
|
||||
;; - deletion: a user cannot delete their own account
|
||||
;; - manage_ssh_keys: a user cannot configure ssh keys
|
||||
;; - manage_gpg_keys: a user cannot configure gpg keys
|
||||
;;EXTERNAL_USER_DISABLE_FEATURES =
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
@@ -1554,12 +1513,7 @@ LEVEL = Info
|
||||
;; The source of the username for new oauth2 accounts:
|
||||
;; userid = use the userid / sub attribute
|
||||
;; nickname = use the nickname attribute
|
||||
;; preferred_username = use the preferred_username attribute
|
||||
;; email = use the username part of the email attribute
|
||||
;; Note: `nickname`, `preferred_username` and `email` options will normalize input strings using the following criteria:
|
||||
;; - diacritics are removed
|
||||
;; - the characters in the set ['´`] are removed
|
||||
;; - the characters in the set [\s~+] are replaced with "-"
|
||||
;USERNAME = nickname
|
||||
;;
|
||||
;; Update avatar if available from oauth2 provider.
|
||||
@@ -1734,6 +1688,9 @@ LEVEL = Info
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;
|
||||
;; if the cache enabled
|
||||
;ENABLED = true
|
||||
;;
|
||||
;; Either "memory", "redis", "memcache", or "twoqueue". default is "memory"
|
||||
;ADAPTER = memory
|
||||
;;
|
||||
@@ -1758,6 +1715,8 @@ LEVEL = Info
|
||||
;[cache.last_commit]
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; if the cache enabled
|
||||
;ENABLED = true
|
||||
;;
|
||||
;; Time to keep items in cache if not used, default is 8760 hours.
|
||||
;; Setting it to -1 disables caching
|
||||
@@ -1853,8 +1812,8 @@ LEVEL = Info
|
||||
;; 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 = .csv,.docx,.fodg,.fodp,.fods,.fodt,.gif,.gz,.jpeg,.jpg,.log,.md,.mov,.mp4,.odf,.odg,.odp,.ods,.odt,.patch,.pdf,.png,.pptx,.svg,.tgz,.txt,.webm,.xls,.xlsx,.zip
|
||||
;;
|
||||
;; Max size of each file. Defaults to 2048MB
|
||||
;MAX_SIZE = 2048
|
||||
;; Max size of each file. Defaults to 4MB
|
||||
;MAX_SIZE = 4
|
||||
;;
|
||||
;; Max number of files per upload. Defaults to 5
|
||||
;MAX_FILES = 5
|
||||
@@ -2035,17 +1994,6 @@ LEVEL = Info
|
||||
;; or only create new users if UPDATE_EXISTING is set to false
|
||||
;UPDATE_EXISTING = true
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Cleanup expired actions assets
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;[cron.cleanup_actions]
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;ENABLED = true
|
||||
;RUN_AT_START = true
|
||||
;SCHEDULE = @midnight
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Clean-up deleted branches
|
||||
@@ -2328,8 +2276,6 @@ LEVEL = Info
|
||||
;SHOW_FOOTER_VERSION = true
|
||||
;; Show template execution time in the footer
|
||||
;SHOW_FOOTER_TEMPLATE_LOAD_TIME = true
|
||||
;; Show the "powered by" text in the footer
|
||||
;SHOW_FOOTER_POWERED_BY = true
|
||||
;; Generate sitemap. Defaults to `true`.
|
||||
;ENABLE_SITEMAP = true
|
||||
;; Enable/Disable RSS/Atom feed
|
||||
@@ -2389,6 +2335,22 @@ LEVEL = Info
|
||||
;; Enable issue by repository metrics; default is false
|
||||
;ENABLED_ISSUE_BY_REPOSITORY = false
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;[task]
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;
|
||||
;; Task queue type, could be `channel` or `redis`.
|
||||
;QUEUE_TYPE = channel
|
||||
;;
|
||||
;; Task queue length, available only when `QUEUE_TYPE` is `channel`.
|
||||
;QUEUE_LENGTH = 1000
|
||||
;;
|
||||
;; Task queue connection string, available only when `QUEUE_TYPE` is `redis`.
|
||||
;; If there is a password of redis, use `redis://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s` or `redis+cluster://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s` for `redis-clsuter`.
|
||||
;QUEUE_CONN_STR = "redis://127.0.0.1:6379/0?pool_size=100&idle_timeout=180s"
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;[migrations]
|
||||
@@ -2604,7 +2566,7 @@ LEVEL = Info
|
||||
;;
|
||||
;; Default platform to get action plugins, `github` for `https://github.com`, `self` for the current Gitea instance.
|
||||
;DEFAULT_ACTIONS_URL = github
|
||||
;; Default artifact retention time in days. Artifacts could have their own retention periods by setting the `retention-days` option in `actions/upload-artifact` step.
|
||||
;; Default artifact retention time in days, default is 90 days
|
||||
;ARTIFACT_RETENTION_DAYS = 90
|
||||
;; Timeout to stop the task which have running status, but haven't been updated for a long time
|
||||
;ZOMBIE_TASK_TIMEOUT = 10m
|
||||
@@ -2612,8 +2574,6 @@ LEVEL = Info
|
||||
;ENDLESS_TASK_TIMEOUT = 3h
|
||||
;; Timeout to cancel the jobs which have waiting status, but haven't been picked by a runner for a long time
|
||||
;ABANDONED_JOB_TIMEOUT = 24h
|
||||
;; Strings committers can place inside a commit message or PR title to skip executing the corresponding actions workflow
|
||||
;SKIP_WORKFLOW_STRINGS = [skip ci],[ci skip],[no ci],[skip actions],[actions skip]
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
@@ -7,7 +7,7 @@ if [ ! -x /bin/sh ]; then
|
||||
fi
|
||||
|
||||
if [ "${USER}" != "git" ]; then
|
||||
# Rename user
|
||||
# rename user
|
||||
sed -i -e "s/^git\:/${USER}\:/g" /etc/passwd
|
||||
fi
|
||||
|
||||
@@ -19,13 +19,13 @@ if [ -z "${USER_UID}" ]; then
|
||||
USER_UID="`id -u ${USER}`"
|
||||
fi
|
||||
|
||||
# Change GID for USER?
|
||||
## Change GID for USER?
|
||||
if [ -n "${USER_GID}" ] && [ "${USER_GID}" != "`id -g ${USER}`" ]; then
|
||||
sed -i -e "s/^${USER}:\([^:]*\):[0-9]*/${USER}:\1:${USER_GID}/" /etc/group
|
||||
sed -i -e "s/^${USER}:\([^:]*\):\([0-9]*\):[0-9]*/${USER}:\1:\2:${USER_GID}/" /etc/passwd
|
||||
fi
|
||||
|
||||
# Change UID for USER?
|
||||
## Change UID for USER?
|
||||
if [ -n "${USER_UID}" ] && [ "${USER_UID}" != "`id -u ${USER}`" ]; then
|
||||
sed -i -e "s/^${USER}:\([^:]*\):[0-9]*:\([0-9]*\)/${USER}:\1:${USER_UID}:\2/" /etc/passwd
|
||||
fi
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
# Gitea: Docs
|
||||
|
||||
[](https://discord.gg/Gitea)
|
||||
[](http://microbadger.com/images/gitea/docs "Get your own image badge on microbadger.com")
|
||||
|
||||
These docs are ingested by our [docs repo](https://gitea.com/gitea/gitea-docusaurus).
|
||||
|
||||
## Authors
|
||||
@@ -15,5 +18,5 @@ for the full license text.
|
||||
## Copyright
|
||||
|
||||
```
|
||||
Copyright (c) 2016 The Gitea Authors
|
||||
Copyright (c) 2016 The Gitea Authors <https://gitea.io>
|
||||
```
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
# Gitea: 文档
|
||||
|
||||
[](http://drone.gitea.io/go-gitea/docs)
|
||||
[](https://discord.gg/Gitea)
|
||||
[](http://microbadger.com/images/gitea/docs "Get your own image badge on microbadger.com")
|
||||
|
||||
https://gitea.com/gitea/gitea-docusaurus
|
||||
|
||||
## 关于我们
|
||||
@@ -14,5 +18,5 @@ https://gitea.com/gitea/gitea-docusaurus
|
||||
## 版权声明
|
||||
|
||||
```
|
||||
Copyright (c) 2016 The Gitea Authors
|
||||
Copyright (c) 2016 The Gitea Authors <https://gitea.io>
|
||||
```
|
||||
|
||||
13
docs/content/administration.fr-fr.md
Normal file
13
docs/content/administration.fr-fr.md
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
date: "2017-08-23T09:00:00+02:00"
|
||||
title: "Avancé"
|
||||
slug: "administration"
|
||||
sidebar_position: 30
|
||||
toc: false
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
name: "Avancé"
|
||||
sidebar_position: 20
|
||||
identifier: "administration"
|
||||
---
|
||||
13
docs/content/administration.zh-tw.md
Normal file
13
docs/content/administration.zh-tw.md
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
date: "2016-12-01T16:00:00+02:00"
|
||||
title: "運維"
|
||||
slug: "administration"
|
||||
sidebar_position: 30
|
||||
toc: false
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
name: "運維"
|
||||
sidebar_position: 20
|
||||
identifier: "administration"
|
||||
---
|
||||
0
docs/content/administration/_index.zh-tw.md
Normal file
0
docs/content/administration/_index.zh-tw.md
Normal file
@@ -19,10 +19,10 @@ Some jurisdictions (such as EU), requires certain legal pages (e.g. Privacy Poli
|
||||
|
||||
## Getting Pages
|
||||
|
||||
Gitea source code ships with sample pages, available in `contrib/legal` directory. Copy them to `custom/public/assets/`. For example, to add Privacy Policy:
|
||||
Gitea source code ships with sample pages, available in `contrib/legal` directory. Copy them to `custom/public/`. For example, to add Privacy Policy:
|
||||
|
||||
```
|
||||
wget -O /path/to/custom/public/assets/privacy.html https://raw.githubusercontent.com/go-gitea/gitea/main/contrib/legal/privacy.html.sample
|
||||
wget -O /path/to/custom/public/privacy.html https://raw.githubusercontent.com/go-gitea/gitea/main/contrib/legal/privacy.html.sample
|
||||
```
|
||||
|
||||
Now you need to edit the page to meet your requirements. In particular you must change the email addresses, web addresses and references to "Your Gitea Instance" to match your situation.
|
||||
|
||||
@@ -19,10 +19,10 @@ menu:
|
||||
|
||||
## 获取页面
|
||||
|
||||
Gitea 源代码附带了示例页面,位于 `contrib/legal` 目录中。将它们复制到 `custom/public/assets/` 目录下。例如,如果要添加隐私政策:
|
||||
Gitea 源代码附带了示例页面,位于 `contrib/legal` 目录中。将它们复制到 `custom/public/` 目录下。例如,如果要添加隐私政策:
|
||||
|
||||
```
|
||||
wget -O /path/to/custom/public/assets/privacy.html https://raw.githubusercontent.com/go-gitea/gitea/main/contrib/legal/privacy.html.sample
|
||||
wget -O /path/to/custom/public/privacy.html https://raw.githubusercontent.com/go-gitea/gitea/main/contrib/legal/privacy.html.sample
|
||||
```
|
||||
|
||||
现在,你需要编辑该页面以满足你的需求。特别是,你必须更改电子邮件地址、网址以及与 "Your Gitea Instance" 相关的引用,以匹配你的情况。
|
||||
|
||||
@@ -92,7 +92,7 @@ cd gitea-dump-1610949662
|
||||
mv app.ini /etc/gitea/conf/app.ini
|
||||
mv data/* /var/lib/gitea/data/
|
||||
mv log/* /var/lib/gitea/log/
|
||||
mv repos/* /var/lib/gitea/data/gitea-repositories/
|
||||
mv repos/* /var/lib/gitea/gitea-repositories/
|
||||
chown -R gitea:gitea /etc/gitea/conf/app.ini /var/lib/gitea
|
||||
|
||||
# mysql
|
||||
@@ -111,8 +111,6 @@ With Gitea running, and from the directory Gitea's binary is located, execute: `
|
||||
|
||||
This ensures that application and configuration file paths in repository Git Hooks are consistent and applicable to the current installation. If these paths are not updated, repository `push` actions will fail.
|
||||
|
||||
If you still have issues, consider running `./gitea doctor check` to inspect possible errors (or run with `--fix`).
|
||||
|
||||
### Using Docker (`restore`)
|
||||
|
||||
There is also no support for a recovery command in a Docker-based gitea instance. The restore process contains the same steps as described in the previous section but with different paths.
|
||||
|
||||
@@ -19,12 +19,6 @@ menu:
|
||||
|
||||
Gitea 已经实现了 `dump` 命令可以用来备份所有需要的文件到一个zip压缩文件。该压缩文件可以被用来进行数据恢复。
|
||||
|
||||
## 备份一致性
|
||||
|
||||
为了确保 Gitea 实例的一致性,在备份期间必须关闭它。
|
||||
|
||||
Gitea 包括数据库、文件和 Git 仓库,当它被使用时所有这些都会发生变化。例如,当迁移正在进行时,在数据库中创建一个事务,而 Git 仓库正在被复制。如果备份发生在迁移的中间,Git 仓库可能是不完整的,尽管数据库声称它是完整的,因为它是在之后被转储的。避免这种竞争条件的唯一方法是在备份期间停止 Gitea 实例。
|
||||
|
||||
## 备份命令 (`dump`)
|
||||
|
||||
先转到git用户的权限: `su git`. 再Gitea目录运行 `./gitea dump`。一般会显示类似如下的输出:
|
||||
@@ -40,43 +34,15 @@ Gitea 包括数据库、文件和 Git 仓库,当它被使用时所有这些都
|
||||
|
||||
最后生成的 `gitea-dump-1482906742.zip` 文件将会包含如下内容:
|
||||
|
||||
* `app.ini` - 如果原先存储在默认的 custom/ 目录之外,则是配置文件的可选副本
|
||||
* `custom/` - 所有保存在 `custom/` 目录下的配置和自定义的文件。
|
||||
* `data/` - 数据目录(APP_DATA_PATH),如果使用文件会话,则不包括会话。该目录包括 `attachments`、`avatars`、`lfs`、`indexers`、如果使用 SQLite 则包括 SQLite 文件。
|
||||
* `repos/` - 仓库目录的完整副本。
|
||||
* `custom` - 所有保存在 `custom/` 目录下的配置和自定义的文件。
|
||||
* `data` - 数据目录下的所有内容不包含使用文件session的文件。该目录包含 `attachments`, `avatars`, `lfs`, `indexers`, 如果使用sqlite 还会包含 sqlite 数据库文件。
|
||||
* `gitea-db.sql` - 数据库dump出来的 SQL。
|
||||
* `gitea-repo.zip` - Git仓库压缩文件。
|
||||
* `log/` - Logs文件,如果用作迁移不是必须的。
|
||||
|
||||
中间备份文件将会在临时目录进行创建,如果您要重新指定临时目录,可以用 `--tempdir` 参数,或者用 `TMPDIR` 环境变量。
|
||||
|
||||
## 备份数据库
|
||||
|
||||
`gitea dump` 创建的 SQL 转储使用 XORM,Gitea 管理员可能更喜欢使用本地的 MySQL 和 PostgreSQL 转储工具。使用 XORM 转储数据库时仍然存在一些问题,可能会导致在尝试恢复时出现问题。
|
||||
|
||||
```sh
|
||||
# mysql
|
||||
mysqldump -u$USER -p$PASS --database $DATABASE > gitea-db.sql
|
||||
# postgres
|
||||
pg_dump -U $USER $DATABASE > gitea-db.sql
|
||||
```
|
||||
|
||||
### 使用Docker (`dump`)
|
||||
|
||||
在使用 Docker 时,使用 `dump` 命令有一些注意事项。
|
||||
|
||||
必须以 `gitea/conf/app.ini` 中指定的 `RUN_USER = <OS_USERNAME>` 执行该命令;并且,为了让备份文件夹的压缩过程能够顺利执行,`docker exec` 命令必须在 `--tempdir` 内部执行。
|
||||
|
||||
示例:
|
||||
|
||||
```none
|
||||
docker exec -u <OS_USERNAME> -it -w <--tempdir> $(docker ps -qf 'name=^<NAME_OF_DOCKER_CONTAINER>$') bash -c '/usr/local/bin/gitea dump -c </path/to/app.ini>'
|
||||
```
|
||||
|
||||
\*注意:`--tempdir` 指的是 Gitea 使用的 Docker 环境的临时目录;如果您没有指定自定义的 `--tempdir`,那么 Gitea 将使用 `/tmp` 或 Docker 容器的 `TMPDIR` 环境变量。对于 `--tempdir`,请相应调整您的 `docker exec` 命令选项。
|
||||
|
||||
结果应该是一个文件,存储在指定的 `--tempdir` 中,类似于:`gitea-dump-1482906742.zip`
|
||||
|
||||
## 恢复命令 (`restore`)
|
||||
## Restore Command (`restore`)
|
||||
|
||||
当前还没有恢复命令,恢复需要人工进行。主要是把文件和数据库进行恢复。
|
||||
|
||||
@@ -85,10 +51,10 @@ docker exec -u <OS_USERNAME> -it -w <--tempdir> $(docker ps -qf 'name=^<NAME_OF_
|
||||
```sh
|
||||
unzip gitea-dump-1610949662.zip
|
||||
cd gitea-dump-1610949662
|
||||
mv app.ini /etc/gitea/conf/app.ini
|
||||
mv data/conf/app.ini /etc/gitea/conf/app.ini
|
||||
mv data/* /var/lib/gitea/data/
|
||||
mv log/* /var/lib/gitea/log/
|
||||
mv repos/* /var/lib/gitea/gitea-repositories/
|
||||
mv repos/* /var/lib/gitea/repositories/
|
||||
chown -R gitea:gitea /etc/gitea/conf/app.ini /var/lib/gitea
|
||||
|
||||
# mysql
|
||||
@@ -100,55 +66,3 @@ psql -U $USER -d $DATABASE < gitea-db.sql
|
||||
|
||||
service gitea restart
|
||||
```
|
||||
|
||||
如果安装方式发生了变化(例如 二进制 -> Docker),或者 Gitea 安装到了与之前安装不同的目录,则需要重新生成仓库 Git 钩子。
|
||||
|
||||
在 Gitea 运行时,并从 Gitea 二进制文件所在的目录执行:`./gitea admin regenerate hooks`
|
||||
|
||||
这样可以确保仓库 Git 钩子中的应用程序和配置文件路径与当前安装一致。如果这些路径没有更新,仓库的 `push` 操作将失败。
|
||||
|
||||
### 使用 Docker (`restore`)
|
||||
|
||||
在基于 Docker 的 Gitea 实例中,也没有恢复命令的支持。恢复过程与前面描述的步骤相同,但路径不同。
|
||||
|
||||
示例:
|
||||
|
||||
```sh
|
||||
# 在容器中打开 bash 会话
|
||||
docker exec --user git -it 2a83b293548e bash
|
||||
# 在容器内解压您的备份文件
|
||||
unzip gitea-dump-1610949662.zip
|
||||
cd gitea-dump-1610949662
|
||||
# 恢复 Gitea 数据
|
||||
mv data/* /data/gitea
|
||||
# 恢复仓库本身
|
||||
mv repos/* /data/git/gitea-repositories/
|
||||
# 调整文件权限
|
||||
chown -R git:git /data
|
||||
# 重新生成 Git 钩子
|
||||
/usr/local/bin/gitea -c '/data/gitea/conf/app.ini' admin regenerate hooks
|
||||
```
|
||||
|
||||
Gitea 容器中的默认用户是 `git`(1000:1000)。请用您的 Gitea 容器 ID 或名称替换 `2a83b293548e`。
|
||||
|
||||
### 使用 Docker-rootless (`restore`)
|
||||
|
||||
在 Docker-rootless 容器中的恢复工作流程只是要使用的目录不同:
|
||||
|
||||
```sh
|
||||
# 在容器中打开 bash 会话
|
||||
docker exec --user git -it 2a83b293548e bash
|
||||
# 在容器内解压您的备份文件
|
||||
unzip gitea-dump-1610949662.zip
|
||||
cd gitea-dump-1610949662
|
||||
# 恢复 app.ini
|
||||
mv data/conf/app.ini /etc/gitea/app.ini
|
||||
# 恢复 Gitea 数据
|
||||
mv data/* /var/lib/gitea
|
||||
# 恢复仓库本身
|
||||
mv repos/* /var/lib/gitea/git/gitea-repositories
|
||||
# 调整文件权限
|
||||
chown -R git:git /etc/gitea/app.ini /var/lib/gitea
|
||||
# 重新生成 Git 钩子
|
||||
/usr/local/bin/gitea -c '/etc/gitea/app.ini' admin regenerate hooks
|
||||
```
|
||||
|
||||
68
docs/content/administration/backup-and-restore.zh-tw.md
Normal file
68
docs/content/administration/backup-and-restore.zh-tw.md
Normal file
@@ -0,0 +1,68 @@
|
||||
---
|
||||
date: "2017-01-01T16:00:00+02:00"
|
||||
title: "用法: 備份與還原"
|
||||
slug: "backup-and-restore"
|
||||
sidebar_position: 11
|
||||
toc: false
|
||||
draft: false
|
||||
aliases:
|
||||
- /zh-tw/backup-and-restore
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "administration"
|
||||
name: "備份與還原"
|
||||
sidebar_position: 11
|
||||
identifier: "backup-and-restore"
|
||||
---
|
||||
|
||||
# 備份與還原
|
||||
|
||||
Gitea 目前支援 `dump` 指令,用來將資料備份成 zip 檔案,後續會提供還原指令,讓你可以輕易的將備份資料及還原到另外一台機器。
|
||||
|
||||
## 備份指令 (`dump`)
|
||||
|
||||
首先,切換到執行 Gitea 的使用者: `su git` (請修改成您指定的使用者),並在安裝目錄內執行 `./gitea dump` 指令,你可以看到 console 畫面如下:
|
||||
|
||||
```
|
||||
2016/12/27 22:32:09 Creating tmp work dir: /tmp/gitea-dump-417443001
|
||||
2016/12/27 22:32:09 Dumping local repositories.../home/git/gitea-repositories
|
||||
2016/12/27 22:32:22 Dumping database...
|
||||
2016/12/27 22:32:22 Packing dump files...
|
||||
2016/12/27 22:32:34 Removing tmp work dir: /tmp/gitea-dump-417443001
|
||||
2016/12/27 22:32:34 Finish dumping in file gitea-dump-1482906742.zip
|
||||
```
|
||||
|
||||
備份出來的 `gitea-dump-1482906742.zip` 檔案,檔案內會包含底下內容:
|
||||
|
||||
* `custom/conf/app.ini` - 伺服器設定檔。
|
||||
* `gitea-db.sql` - SQL 備份檔案。
|
||||
* `gitea-repo.zip` - 此 zip 檔案為全部的 repo 目錄。
|
||||
請參考 Config -> repository -> `ROOT` 所設定的路徑。
|
||||
* `log/` - 全部 logs 檔案,如果你要 migrate 到其他伺服器,此目錄不用保留。
|
||||
|
||||
你可以透過設定 `--tempdir` 指令參數來指定備份檔案目錄,或者是設定 `TMPDIR` 環境變數來達到此功能。
|
||||
|
||||
## 還原指令 (`restore`)
|
||||
|
||||
持續更新中: 此文件尚未完成.
|
||||
|
||||
例:
|
||||
|
||||
```sh
|
||||
unzip gitea-dump-1610949662.zip
|
||||
cd gitea-dump-1610949662
|
||||
mv data/conf/app.ini /etc/gitea/conf/app.ini
|
||||
mv data/* /var/lib/gitea/data/
|
||||
mv log/* /var/lib/gitea/log/
|
||||
mv repos/* /var/lib/gitea/repositories/
|
||||
chown -R gitea:gitea /etc/gitea/conf/app.ini /var/lib/gitea
|
||||
|
||||
# mysql
|
||||
mysql --default-character-set=utf8mb4 -u$USER -p$PASS $DATABASE <gitea-db.sql
|
||||
# sqlite3
|
||||
sqlite3 $DATABASE_PATH <gitea-db.sql
|
||||
# postgres
|
||||
psql -U $USER -d $DATABASE < gitea-db.sql
|
||||
|
||||
service gitea restart
|
||||
```
|
||||
@@ -50,7 +50,7 @@ a special meaning for your command shell.
|
||||
|
||||
If no pattern is provided, all files are listed.
|
||||
|
||||
### Example: Listing all embedded files
|
||||
### Example
|
||||
|
||||
Listing all embedded files with `openid` in their path:
|
||||
|
||||
@@ -101,7 +101,7 @@ When Gitea is upgraded to a new version (by replacing the executable), many of t
|
||||
embedded files will suffer changes. Gitea will honor and use any files found
|
||||
in the `custom` directory, even if they are old and incompatible.
|
||||
|
||||
### Example: Extracting mail templates
|
||||
### Example
|
||||
|
||||
Extracting mail templates to a temporary directory:
|
||||
|
||||
|
||||
@@ -37,20 +37,20 @@ gitea embedded list [--include-vendored] [patterns...]
|
||||
|
||||
- 列出所有模板文件,无论在哪个虚拟目录下:`**.tmpl`
|
||||
- 列出所有邮件模板文件:`templates/mail/**.tmpl`
|
||||
列出 `public/assets/img` 目录下的所有文件:`public/assets/img/**`
|
||||
- 列出 `public/img` 目录下的所有文件:`public/img/**`
|
||||
|
||||
不要忘记为模式使用引号,因为空格、`*` 和其他字符可能对命令行解释器有特殊含义。
|
||||
|
||||
如果未提供模式,则列出所有文件。
|
||||
|
||||
### 示例:列出所有嵌入文件
|
||||
### 示例
|
||||
|
||||
列出所有路径中包含 `openid` 的嵌入文件:
|
||||
|
||||
```sh
|
||||
$ gitea embedded list '**openid**'
|
||||
public/assets/img/auth/openid_connect.svg
|
||||
public/assets/img/openid-16x16.png
|
||||
public/img/auth/openid_connect.svg
|
||||
public/img/openid-16x16.png
|
||||
templates/user/auth/finalize_openid.tmpl
|
||||
templates/user/auth/signin_openid.tmpl
|
||||
templates/user/auth/signup_openid_connect.tmpl
|
||||
@@ -83,7 +83,7 @@ gitea [--config {file}] embedded extract [--destination {dir}|--custom] [--overw
|
||||
|
||||
请确保**只提取需要自定义的文件**。位于 `custom` 目录中的文件不会受到 Gitea 的升级过程的影响。当 Gitea 升级到新版本(通过替换可执行文件)时,许多嵌入文件将发生变化。Gitea 将尊重并使用在 `custom` 目录中找到的任何文件,即使这些文件是旧的和不兼容的。
|
||||
|
||||
### 示例:提取邮件模板
|
||||
### 示例
|
||||
|
||||
将邮件模板提取到临时目录:
|
||||
|
||||
|
||||
@@ -83,7 +83,8 @@ Admin operations:
|
||||
- `--email value`: Email. Required.
|
||||
- `--admin`: If provided, this makes the user an admin. Optional.
|
||||
- `--access-token`: If provided, an access token will be created for the user. Optional. (default: false).
|
||||
- `--must-change-password`: The created user will be required to set a new password after the initial login, default: true. It could be disabled by `--must-change-password=false`.
|
||||
- `--must-change-password`: If provided, the created user will be required to choose a newer password after the
|
||||
initial login. Optional. (default: true).
|
||||
- `--random-password`: If provided, a randomly generated password will be used as the password of the created
|
||||
user. The value of `--password` will be discarded. Optional.
|
||||
- `--random-password-length`: If provided, it will be used to configure the length of the randomly generated
|
||||
@@ -94,7 +95,6 @@ Admin operations:
|
||||
- Options:
|
||||
- `--username value`, `-u value`: Username. Required.
|
||||
- `--password value`, `-p value`: New password. Required.
|
||||
- `--must-change-password`: The user is required to set a new password after the login, default: true. It could be disabled by `--must-change-password=false`.
|
||||
- Examples:
|
||||
- `gitea admin user change-password --username myname --password asecurepassword`
|
||||
- `must-change-password`:
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user